private void MoveShips()
{
for (int index = 0; index < spheres [0].transform.childCount; index++) {
Transform oneChild = spheres [0].transform.GetChild (index);
lastPositions [index] = oneChild.transform.position;
if (!hasRotated [index])
{
oneChild.transform.position += Vector3.forward * Time.deltaTime * moveSpeed;
}
else
{
oneChild.transform.position += oneChild.transform.forward * Time.deltaTime * moveSpeed;
}
}
if (updateOn == true) {
for(int index =0;index < spheres[0].transform.childCount;index++)
{
Transform child = spheres[0].transform.GetChild(index);
distanceTraveled[index] += Vector3.Distance (child.transform.position, lastPositions [index]);
if (distanceTraveled [index] >= randomNumbers [index] && !hasRotated [index])
{
targetAngles = child.transform.eulerAngles + 180f * Vector3.up;
StartCoroutine (TurnShip (child.transform, child.transform.eulerAngles, targetAngles, smooth));
hasRotated [index] = true;
}
}
}
}
IEnumerator TurnShip(Transform ship, Vector3 startAngle, Vector3 endAngle, float smooth)
{
float lerpSpeed = 0;
while(lerpSpeed < 1)
{
ship.eulerAngles = Vector3.Lerp(startAngle, endAngle, lerpSpeed);
lerpSpeed += Time.deltaTime * smooth;
yield return null;
}
}
例如我有300艘船。他们正在使用Vector3.forward向前移动,然后我希望在每个孩子完成旋转之后将其改变,然后将其移动方向改变到它现在面向的方向。所以在我将船只旋转180度但船只向上移动的情况下。
这一行让他们向上移动:
oneChild.transform.position += oneChild.transform.forward * Time.deltaTime * moveSpeed;
我还尝试将此行更改为:
oneChild.transform.position += oneChild.transform.forward * moveSpeed;
这使船舶消失。
我也尝试过:
oneChild.transform.position += oneChild.transform.forward * -1 * moveSpeed;
或者
oneChild.transform.position += -oneChild.transform.forward * Time.deltaTime * moveSpeed; --- This line make the ships move up turn and move down. But i want them to move forward not up and down. Move forward to the direction they are facing after the rotation.
或
oneChild.transform.position += oneChild.transform.forward * -1;
我也尝试过仅使用Vector3:
if (!hasRotated [index])
{
oneChild.transform.position += Vector3.forward * Time.deltaTime * moveSpeed;
}
else
{
oneChild.transform.position += Vector3.back * Time.deltaTime * moveSpeed;
}
但这会使船只向后移动而不是朝向他们所面对的方向。如果我将船只旋转60度,它们将向后移动而不是面向方向。
另一个问题我认为,如果船只在完成旋转之前向上移动,那么它就会改变运动模式。我希望首先船只每艘船完成旋转并在旋转时保持向原始方向移动,只有当旋转端然后将移动改变到它面向的方向时。
脚本
using System;
using UnityEngine;
using Random = UnityEngine.Random;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class SphereBuilder : MonoBehaviour
{
public GameObject SpaceShip;
GameObject[] spheres;
public float moveSpeed = 50;
private float distanceTravelled;
public bool updateOn = true;
private Vector3 lastPosition;
List<bool> hasRotated = new List<bool>();
List<float> distanceTraveled = new List<float>();
List<Vector3> lastPositions = new List<Vector3>();
List<int> randomNumbers = new List<int> ();
public float smooth = 1f;
private Vector3 targetAngles;
private bool isRunning = false;
// for tracking properties change
private Vector3 _extents;
private int _sphereCount;
private float _sphereSize;
/// <summary>
/// How far to place spheres randomly.
/// </summary>
public Vector3 Extents;
/// <summary>
/// How many spheres wanted.
/// </summary>
public int SphereCount;
public float SphereSize;
private void rndNumbers()
{
int Min = 20;
int Max = 50;
System.Random rnd = new System.Random ();
randomNumbers = Enumerable.Range(Min, Max).OrderBy(x => rnd.Next()).Take(spheres[0].transform.childCount).ToList();
}
private void Start()
{
UpdateSpheres ();
spheres = GameObject.FindGameObjectsWithTag("MySphere");
rndNumbers ();
for(int index = 0; index < spheres[0].transform.childCount;index++)
{
Transform child = spheres[0].transform.GetChild(index);
lastPosition = new Vector3(child.transform.position.x,child.transform.position.y,child.transform.position.z);
lastPositions.Add (lastPosition);
hasRotated.Add(false);
distanceTraveled.Add(0f);
}
}
private void OnValidate()
{
// prevent wrong values to be entered
Extents = new Vector3(Mathf.Max(0.0f, Extents.x), Mathf.Max(0.0f, Extents.y), Mathf.Max(0.0f, Extents.z));
SphereCount = Mathf.Max(0, SphereCount);
SphereSize = Mathf.Max(0.0f, SphereSize);
}
private void Reset()
{
Extents = new Vector3(250.0f, 20.0f, 250.0f);
SphereCount = 100;
SphereSize = 20.0f;
}
private void Update()
{
UpdateSpheres();
MoveShips ();
}
private void MoveShips()
{
for (int index = 0; index < spheres [0].transform.childCount; index++) {
Transform oneChild = spheres [0].transform.GetChild (index);
lastPositions [index] = oneChild.transform.position;
if (!hasRotated [index])
{
oneChild.transform.position += Vector3.forward * Time.deltaTime * moveSpeed;
}
else
{
oneChild.transform.position += Vector3.back * Time.deltaTime * moveSpeed;
}
}
if (updateOn == true) {
for(int index =0;index < spheres[0].transform.childCount;index++)
{
Transform child = spheres[0].transform.GetChild(index);
distanceTraveled[index] += Vector3.Distance (child.transform.position, lastPositions [index]);
if (distanceTraveled [index] >= randomNumbers [index] && !hasRotated [index]) {
//child.transform.Rotate (new Vector3 (0f, 180f, 0f));
targetAngles = child.transform.eulerAngles + 180f * Vector3.up;
//if (!isRunning)
//{
StartCoroutine (TurnShip (child.transform, child.transform.eulerAngles, targetAngles, smooth));
//}
hasRotated [index] = true;
child.transform.position += Vector3.back * Time.deltaTime * moveSpeed;
}
}
}
}
IEnumerator TurnShip(Transform ship, Vector3 startAngle, Vector3 endAngle, float smooth)
{
isRunning = true;
float lerpSpeed = 0;
while(lerpSpeed < 1)
{
ship.eulerAngles = Vector3.Lerp(startAngle, endAngle, lerpSpeed);
lerpSpeed += 1 * smooth;
yield return new WaitForSeconds(0.01f);
}
isRunning = false;
}
private void UpdateSpheres()
{
if (Extents == _extents && SphereCount == _sphereCount && Mathf.Approximately(SphereSize, _sphereSize))
return;
// cleanup
var spheres = GameObject.FindGameObjectsWithTag("Sphere");
foreach (var t in spheres)
{
if (Application.isEditor)
{
DestroyImmediate(t);
}
else
{
Destroy(t);
}
}
var withTag = GameObject.FindWithTag("Terrain");
if (withTag == null)
throw new InvalidOperationException("Terrain not found");
for (var i = 0; i < SphereCount; i++)
{
var o = Instantiate(SpaceShip);
o.tag = "Sphere";
o.transform.SetParent(gameObject.transform);
o.transform.localScale = new Vector3(SphereSize, SphereSize, SphereSize);
// get random position
var x = Random.Range(-Extents.x, Extents.x);
var y = Extents.y; // sphere altitude relative to terrain below
var z = Random.Range(-Extents.z, Extents.z);
// now send a ray down terrain to adjust Y according terrain below
var height = 10000.0f; // should be higher than highest terrain altitude
var origin = new Vector3(x, height, z);
var ray = new Ray(origin, Vector3.down);
RaycastHit hit;
var maxDistance = 20000.0f;
var nameToLayer = LayerMask.NameToLayer("Terrain");
var layerMask = 1 << nameToLayer;
if (Physics.Raycast(ray, out hit, maxDistance, layerMask))
{
var distance = hit.distance;
y = height - distance + y; // adjust
}
else
{
Debug.LogWarning("Terrain not hit, using default height !");
}
// place !
o.transform.position = new Vector3(x, y, z);
}
_extents = Extents;
_sphereCount = SphereCount;
_sphereSize = SphereSize;
}
}
答案 0 :(得分:1)
你所说的让我觉得当地的前锋完全错了(你的船模型已经转向)。或者你的前锋因为养育而变得更糟(可能很棘手)
也
不要使用Vector3.forward,如果你想要向前旅行。
oneChild.transform.position += oneChild.transform.forward * Time.deltaTime * moveSpeed;
是对的。
X
ship.eulerAngles = Vector3.Lerp(startAngle, endAngle, lerpSpeed);
应该是Slerp https://docs.unity3d.com/ScriptReference/Vector3.Slerp.html
这个和线性插值之间的区别(又名&#34; lerp&#34;)是矢量被视为方向而不是空间中的点。
或lerp角度: https://docs.unity3d.com/ScriptReference/Mathf.LerpAngle.html
X
targetAngles = child.transform.eulerAngles + 180f * Vector3.up;
我发现这最后一行有点抽象,不知道你打开了什么角度,再次使用vector3.up而不是child.transform.up 但我想这条线是颠倒你的船,或者让它向上和向下移动
希望它有所帮助。