简体   繁体   中英

How can i use MoveTowards method in Unity for more than one object

I am planning to create GameObjects on random position and then slide to target position every frame.

I create one object onstart() manually and I used MoveTowards method in update() and it worked but i want to do same with many objects at the same time (about 10 objects): If i create more than one object it doesn't work.

This is what i have:

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);

Make a new script, let's call it Mover . Give it public Vector3 destination and public float rate fields and an Update method that edits its position with MoveTowards :

public class Mover: MonoBehaviour
{
    public Vector3 destination;
    public Vector3 rate;

    void Update()
    {
        transform.position = Vector3.MoveTowards(transform.position, destination, rate * Time.deltaTime);
    }
}

Attach a Mover to the M1 prefab.

Then, when you instantiate each M1 , set the destination and rate of its Mover component:

 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;

What you describe in the comments sounds like actually you have two tasks

  • add a new object every second
  • move all objects

Note: You can not use Collisions for detecting when an object reaches it's target! How do you know which collider belongs to which object? In other words: How would you make sure an object doesn't by accident collide with some other collider which was ment for another object? I'ld rather directly compare the positions instead.

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);
        }
    }
}

Didn't know how you generate your random positions but you could eg have something like

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)
        );
}

depending on your needs ofcourse.

Actually yes if you expect many objects (hundreds or thousands) to move parallel it is better to have only one component controlling them all in order to avoid overhead of Update calls. But for only 10 objects I would probably rather stick to Ruzihm's answer using one movement component for each object.


Note: typed on smartphone but I hope the idea gets clear

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM