Why the objects to move are moving to each other and not following each other by 3 seconds space delay?

Your objects merge, since you only have one index for the objects’ target position, meaning all objects move towards the same point, not each object towards it’s respective next point on the path. This results in a merge as soon as the first object turns around and runs backwards.

It would be best to split your logic into two classes, since otherwise you’d have to keep track of every object’s path separately, meaning you need an int[] indices for the current target position of each object, another array for the goForward bools and so on for every new property you introduce.

Controller:

public class MovementController : MonoBehaviour
{
    [SerializeField]
    private LineRenderer lineRenderer;
    [SerializeField]
    private float speed;
    [SerializeField]
    private bool moveToFirstPositionOnStart;

    public List<MoveOnCurvedLines> movingObjects = new List<MoveOnCurvedLines>();

    void Start()
    {
        Vector3[] positions = GetPositions();

        movingObjects = GameObject.FindGameObjectsWithTag("New Prefab").Select(go => go.GetComponent<MoveOnCurvedLines>().ToList();

        foreach (MoveOnCurvedLines obj in movingObjects)
        {
            obj.Init(positions, speed, moveToFirstPositionOnStart);
        }

        StartCoroutine(TriggerObjects(false));
    }

    Vector3[] GetPositions()
    {
        Vector3[] positions = new Vector3[lineRenderer.positionCount];
        //Get the positions which are shown in the inspector 
        lineRenderer.GetPositions(positions);
        return positions;
    }

    IEnumerator TriggerObjects(bool delayFirstObject)
    {
        WaitForSeconds waitThreeSeconds = new WaitForSeconds(3);

        if (delayFirstObject)
            yield return waitThreeSeconds;

        foreach (MoveOnCurvedLines obj in movingObjects)
        {
            obj.StartMoving();
            yield return waitThreeSeconds;
        }
    }
}

Movement logic:

public class MoveOnCurvedLines : MonoBehaviour
{
    private Transform myTransform;
    private bool initialized;

    private Vector3[] pos;
    private int posIndex = 0;
    private float speed;
    private bool goForward = true;
    private Coroutine moving;

    public void Init(Vector3[] positions, float speed, bool instantlyMoveToFirstPosition)
    {
        myTransform = transform;
        pos = positions;
        this.speed = speed;
        if (instantlyMoveToFirstPosition)
            myTransform.position = positions[0];
        initialized = true;
    }

    public void StartMoving()
    {
        if (initialized && moving == null)
            moving = StartCoroutine(Move());
    }

    public void StopMoving()
    {
        if (moving != null)
        {
            StopCoroutine(moving);
            moving = null;
        }
    }

    private IEnumerator Move()
    {
        while (true)
        {
            Vector3 newPos = myTransform.position;
            float distanceToTravel = speed * Time.deltaTime;

            bool stillTraveling = true;
            while (stillTraveling)
            {
                Vector3 oldPos = newPos;
                newPos = Vector3.MoveTowards(oldPos, pos[posIndex], distanceToTravel);
                distanceToTravel -= Vector3.Distance(newPos, oldPos);
                if (newPos == pos[posIndex]) // Vector3 comparison is approximate so this is ok
                {
                    // when you hit a waypoint:
                    if (goForward)
                    {
                        bool atLastOne = posIndex >= pos.Length - 1;
                        if (!atLastOne)
                        {
                            posIndex++;
                        }
                        else
                        {
                            posIndex--;
                            goForward = false;
                        }
                    }
                    else
                    { // going backwards:
                        bool atFirstOne = posIndex <= 0;
                        if (!atFirstOne)
                        {
                            posIndex--;
                        }
                        else
                        {
                            posIndex++; 
                            goForward = true;
                        }
                    }
                }
                else
                {
                    stillTraveling = false;
                }
            }

            myTransform.position = newPos;
        }
    }
}

MovementController only provides the necessary data, which all your objects share (e.g. the path), but every MoveOnCurvedLines object keeps track of it’s progress independently.

Optimizations:

  • I cached transform in myTransform, since Unity’s transform calls GetComponent<Transform>() every time producing unnecessary overhead.
  • Moving is done in a coroutine, not in Update, since checking n go bools every frame n objects do not move is unnecessary.
  • I changed your public fields to private ones getting serialized, since it’s best practice to restrict access as much as possible. If you need to access them from another script in your project just make them public again.

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top