我如何在 Unity 中对多个对象使用 MoveTowards 方法
How can i use MoveTowards method in Unity for more than one object
我打算在随机位置创建 GameObjects
,然后每帧滑动到目标位置。
我手动创建了一个对象 onstart()
,我在 update()
中使用了 MoveTowards
方法并且它起作用了,但我想同时对许多对象做同样的事情(大约 10 个对象): 如果我创建了多个对象,它就不起作用。
这是我的:
GameObject Go = Instantiate(M1, new Vector3(-5, 10, 0), Quaternion.Euler(0, 0, 0)) as GameObject;
Go.transform.position = Vector3.MoveTowards(Go.transform.position, new Vector3(10, -20, 0), 0.05f);
制作一个新脚本,我们称之为Mover
。给它 public Vector3 destination
和 public float rate
字段和一个 Update
方法,用 MoveTowards
:
编辑它的位置
public class Mover: MonoBehaviour
{
public Vector3 destination;
public Vector3 rate;
void Update()
{
transform.position = Vector3.MoveTowards(transform.position, destination, rate * Time.deltaTime);
}
}
将 Mover
附加到 M1
预制件。
然后,当您实例化每个 M1
时,设置其 Mover
组件的 destination
和 rate
:
GameObject Go = Instantiate(M1, new Vector3(-5, 10, 0), Quaternion.Euler(0, 0, 0)) as GameObject;
Mover goMover = Go.GetComponent<Mover>();
goMover.destination = new Vector3(10, -20, 0);
goMover.rate = 3f;
您在评论中描述的内容听起来像是您实际上有两个任务
- 每秒添加一个新对象
- 移动所有对象
注意:您可以不使用碰撞来检测对象何时到达目标!你怎么知道哪个对撞机属于哪个对象?换句话说:您如何确保一个物体不会意外地与为另一个物体准备的其他对撞机发生碰撞?我宁愿直接比较位置。
public class ObjectController : MonoBehaviour
{
// Here we will store all Transform references
// linked to the according target position
private Dictionary<Transform, Vector3> objects = new Dictionary<Transform, Vector3>();
public GameObject prefab;
// A simple timer for the spawning
private float timer;
// Here we will track objets that reached the Target and shall be destroyed
List<GameObject> objectsToDestroy = new List<GameObject>();
private void Update()
{
// Spawn a new object every second but only until maximum of 10 existing objects
if(objects.Keys.Length < 10)
{
timer += Time.deltaTime;
if(timer > 1f)
{
timer = 0;
// However you generate your random start Position
Vector3 startPos = GetRandomStartPosition();
// However you generate your random target position
Vector3 targetPos = GetRandomTargetPosition(startPos);
var obj = Instantiate(prefab, startPos, Quaternion.Identity).transform;
// Add this new transform and according target Position to the dictionary
objects.Add(obj, targetPos);
}
}
objectsToDestroy.Clear();
// Now go through the items in objects and move them all
foreach(var kvp in objects)
{
var obj = kvp.Key;
var targetPos = KVP.Value;
obj.MoveTowards(obj.position, targetPos, 0.05f * Time.deltaTime);
// Do NOT use collisions for detecting if the object reaches but directly this
if(obj.position == targetPos)
// this uses a proximity of 0.00001f if you really need 0 instead use
//if(Mathf.Approximately(Vector3.Distance(obj.position, targetPos), 0))
{
// mark this object for removal
objectsToDestroy.Add(obj);
}
}
// Finally remove all objects that reached from the dict and destroy them
foreach(var obj in objectsToDestroy)
{
objects.Remove(obj);
Destroy(obj);
}
}
}
不知道你是如何生成随机位置的,但你可以,例如有类似的东西
private Vector3 GetRandomStartPosition ()
{
return new Vector3(
Random.Range(-10f, 10f),
Random.Range(-10f, 10f),
Random.Range(-10f, 10f)
);
}
private Vector3 GetRandomTargetPosition(Vector3 startPos)
{
return startPos + new Vector3(
Random.Range(-1f, 1f),
Random.Range(-1f, 1f),
Random.Range(-1f, 1f)
);
}
当然取决于您的需要。
实际上是的,如果您希望许多对象(成百上千个)并行移动,最好只有一个组件控制它们,以避免 Update
调用的开销。但是对于只有 10 个对象,我可能宁愿坚持 对每个对象使用一个移动组件。
注意:在智能手机上打字,但我希望思路清晰
我打算在随机位置创建 GameObjects
,然后每帧滑动到目标位置。
我手动创建了一个对象 onstart()
,我在 update()
中使用了 MoveTowards
方法并且它起作用了,但我想同时对许多对象做同样的事情(大约 10 个对象): 如果我创建了多个对象,它就不起作用。
这是我的:
GameObject Go = Instantiate(M1, new Vector3(-5, 10, 0), Quaternion.Euler(0, 0, 0)) as GameObject;
Go.transform.position = Vector3.MoveTowards(Go.transform.position, new Vector3(10, -20, 0), 0.05f);
制作一个新脚本,我们称之为Mover
。给它 public Vector3 destination
和 public float rate
字段和一个 Update
方法,用 MoveTowards
:
public class Mover: MonoBehaviour
{
public Vector3 destination;
public Vector3 rate;
void Update()
{
transform.position = Vector3.MoveTowards(transform.position, destination, rate * Time.deltaTime);
}
}
将 Mover
附加到 M1
预制件。
然后,当您实例化每个 M1
时,设置其 Mover
组件的 destination
和 rate
:
GameObject Go = Instantiate(M1, new Vector3(-5, 10, 0), Quaternion.Euler(0, 0, 0)) as GameObject;
Mover goMover = Go.GetComponent<Mover>();
goMover.destination = new Vector3(10, -20, 0);
goMover.rate = 3f;
您在评论中描述的内容听起来像是您实际上有两个任务
- 每秒添加一个新对象
- 移动所有对象
注意:您可以不使用碰撞来检测对象何时到达目标!你怎么知道哪个对撞机属于哪个对象?换句话说:您如何确保一个物体不会意外地与为另一个物体准备的其他对撞机发生碰撞?我宁愿直接比较位置。
public class ObjectController : MonoBehaviour
{
// Here we will store all Transform references
// linked to the according target position
private Dictionary<Transform, Vector3> objects = new Dictionary<Transform, Vector3>();
public GameObject prefab;
// A simple timer for the spawning
private float timer;
// Here we will track objets that reached the Target and shall be destroyed
List<GameObject> objectsToDestroy = new List<GameObject>();
private void Update()
{
// Spawn a new object every second but only until maximum of 10 existing objects
if(objects.Keys.Length < 10)
{
timer += Time.deltaTime;
if(timer > 1f)
{
timer = 0;
// However you generate your random start Position
Vector3 startPos = GetRandomStartPosition();
// However you generate your random target position
Vector3 targetPos = GetRandomTargetPosition(startPos);
var obj = Instantiate(prefab, startPos, Quaternion.Identity).transform;
// Add this new transform and according target Position to the dictionary
objects.Add(obj, targetPos);
}
}
objectsToDestroy.Clear();
// Now go through the items in objects and move them all
foreach(var kvp in objects)
{
var obj = kvp.Key;
var targetPos = KVP.Value;
obj.MoveTowards(obj.position, targetPos, 0.05f * Time.deltaTime);
// Do NOT use collisions for detecting if the object reaches but directly this
if(obj.position == targetPos)
// this uses a proximity of 0.00001f if you really need 0 instead use
//if(Mathf.Approximately(Vector3.Distance(obj.position, targetPos), 0))
{
// mark this object for removal
objectsToDestroy.Add(obj);
}
}
// Finally remove all objects that reached from the dict and destroy them
foreach(var obj in objectsToDestroy)
{
objects.Remove(obj);
Destroy(obj);
}
}
}
不知道你是如何生成随机位置的,但你可以,例如有类似的东西
private Vector3 GetRandomStartPosition ()
{
return new Vector3(
Random.Range(-10f, 10f),
Random.Range(-10f, 10f),
Random.Range(-10f, 10f)
);
}
private Vector3 GetRandomTargetPosition(Vector3 startPos)
{
return startPos + new Vector3(
Random.Range(-1f, 1f),
Random.Range(-1f, 1f),
Random.Range(-1f, 1f)
);
}
当然取决于您的需要。
实际上是的,如果您希望许多对象(成百上千个)并行移动,最好只有一个组件控制它们,以避免 Update
调用的开销。但是对于只有 10 个对象,我可能宁愿坚持
注意:在智能手机上打字,但我希望思路清晰