Skip to main content
Adding switchable behaviour when reaching the end of the road.
Source Link
DMGregory
  • 140.8k
  • 23
  • 257
  • 401
// Adding selectable behaviour at the end of the path,
// as requested from the comments.
public enum PathCompleteBehaviour {
    Stop,
    Loop,
    Reverse
}
public PathCompleteBehaviour completeBehaviour;

// Store parallel arrays for our movement parameters.
private float[] movementSpeeds;    // Randomized speed per object.
private int[] nextWaypointIndices; // Destination per object.

private void Start()
{
    // Changing terminology to be more standard.
    // - a "prefab" is a source asset you want to copy
    // - an "instance" is a copy of it that's been spawned in the scene
    instancesToMove = GameObject.FindGameObjectsWithTag("FrameLine");

    movementSpeeds = new float[instancesToMove.Length];
    nextWaypointIndices = new int[instancesToMove.Length];

    for(int i = 0; i < instancesToMove.Length; i++)
         movementSpeeds[i] = Random.Range(minSpeed, maxSpeed);
}

private void WaypointsAI()
{
    // We want to iterate over the instances, not over the waypoints.
    for (int i = 0; i < instancesToMove.Length; i++)
    {
        // Check to see if we reached the last waypoint.
        // If so, westop can/ stoploop here/ &turn skiparound aheadas needed.
        int waypointIndex = nextWaypointIndices[i];
        if(waypointIndex < 0 || waypointIndex >= waypoints.Length) {               
           switch(completeBehaviour) {
               case PathCompleteBehaviour.Stop: 
                   // Leave it where it is and skip to the next instance.
        if           continue;
               case PathCompleteBehaviour.Loop:
                   // Wrap front to back / back to front.
                   waypointIndex = (nextWaypointIndices[i]waypointIndex >=+ waypoints.Length) % waypoints.Length;
           continue;        break;
               case PathCompleteBehaviour.Reverse:
                   // YouBounce canback alsoto prunethe instancespoint thatbefore arelast.
 done to save processing               waypointIndex += (movementSpeeds[i] > 0f) ? -2 : 2;
                   // Reverse direction.
                   movementSpeeds[i] *= -1f;
                   break;
           }
           nextWaypointIndices[i] = waypointIndex;
        }
        

        // Look up the waypoint we want to move toward next.
        Vector3 waypoint = waypoints[nextWaypointIndices[i]]waypoints[waypointIndex].position;

        // Read this instance's speed,
        // to compute how far it should move in this frame.
        float travel = Mathf.Abs(movementSpeeds[i]) * Time.deltaTime;

        // Apply the motion.
        Vector3 position = instancesToMove[i].transform.position;
        position = Vector3.MoveTowards(position, waypoint, travel);
        instancesToMove[i].transform.position = position;

        // If we're within a configurable tolerance of the
        // destination waypoint, set our destination
        // to the next waypoint after it.
        if((position - waypoint).sqrMagnitude < 0.1f) {
            nextWaypointIndices[i]++;nextWaypointIndices[i] += (movementSpeeds[i] > 0f) ? 1 : -1;
        }
    }
}
// Store parallel arrays for our movement parameters.
private float[] movementSpeeds;    // Randomized speed per object.
private int[] nextWaypointIndices; // Destination per object.

private void Start()
{
    // Changing terminology to be more standard.
    // - a "prefab" is a source asset you want to copy
    // - an "instance" is a copy of it that's been spawned in the scene
    instancesToMove = GameObject.FindGameObjectsWithTag("FrameLine");

    movementSpeeds = new float[instancesToMove.Length];
    nextWaypointIndices = new int[instancesToMove.Length];

    for(int i = 0; i < instancesToMove.Length; i++)
         movementSpeeds[i] = Random.Range(minSpeed, maxSpeed);
}

private void WaypointsAI()
{
    // We want to iterate over the instances, not over the waypoints.
    for (int i = 0; i < instancesToMove.Length; i++)
    {
        // Check to see if we reached the last waypoint.
        // If so, we can stop here & skip ahead to the next instance.
        if(nextWaypointIndices[i] >= waypoints.Length)
           continue;
        // You can also prune instances that are done to save processing.


        // Look up the waypoint we want to move toward next.
        Vector3 waypoint = waypoints[nextWaypointIndices[i]].position;

        // Read this instance's speed,
        // to compute how far it should move in this frame.
        float travel = movementSpeeds[i] * Time.deltaTime;

        // Apply the motion.
        Vector3 position = instancesToMove[i].transform.position;
        position = Vector3.MoveTowards(position, waypoint, travel);
        instancesToMove[i].transform.position = position;

        // If we're within a configurable tolerance of the
        // destination waypoint, set our destination
        // to the next waypoint after it.
        if((position - waypoint).sqrMagnitude < 0.1f)
            nextWaypointIndices[i]++;
    }
}
// Adding selectable behaviour at the end of the path,
// as requested from the comments.
public enum PathCompleteBehaviour {
    Stop,
    Loop,
    Reverse
}
public PathCompleteBehaviour completeBehaviour;

// Store parallel arrays for our movement parameters.
private float[] movementSpeeds;    // Randomized speed per object.
private int[] nextWaypointIndices; // Destination per object.

private void Start()
{
    // Changing terminology to be more standard.
    // - a "prefab" is a source asset you want to copy
    // - an "instance" is a copy of it that's been spawned in the scene
    instancesToMove = GameObject.FindGameObjectsWithTag("FrameLine");

    movementSpeeds = new float[instancesToMove.Length];
    nextWaypointIndices = new int[instancesToMove.Length];

    for(int i = 0; i < instancesToMove.Length; i++)
         movementSpeeds[i] = Random.Range(minSpeed, maxSpeed);
}

private void WaypointsAI()
{
    // We want to iterate over the instances, not over the waypoints.
    for (int i = 0; i < instancesToMove.Length; i++)
    {
        // Check to see if we reached the last waypoint.
        // If so, stop / loop / turn around as needed.
        int waypointIndex = nextWaypointIndices[i];
        if(waypointIndex < 0 || waypointIndex >= waypoints.Length) {               
           switch(completeBehaviour) {
               case PathCompleteBehaviour.Stop: 
                   // Leave it where it is and skip to the next instance.
                   continue;
               case PathCompleteBehaviour.Loop:
                   // Wrap front to back / back to front.
                   waypointIndex = (waypointIndex + waypoints.Length) % waypoints.Length;
                   break;
               case PathCompleteBehaviour.Reverse:
                   // Bounce back to the point before last.
                   waypointIndex += (movementSpeeds[i] > 0f) ? -2 : 2;
                   // Reverse direction.
                   movementSpeeds[i] *= -1f;
                   break;
           }
           nextWaypointIndices[i] = waypointIndex;
        }
        

        // Look up the waypoint we want to move toward next.
        Vector3 waypoint = waypoints[waypointIndex].position;

        // Read this instance's speed,
        // to compute how far it should move in this frame.
        float travel = Mathf.Abs(movementSpeeds[i]) * Time.deltaTime;

        // Apply the motion.
        Vector3 position = instancesToMove[i].transform.position;
        position = Vector3.MoveTowards(position, waypoint, travel);
        instancesToMove[i].transform.position = position;

        // If we're within a configurable tolerance of the
        // destination waypoint, set our destination
        // to the next waypoint after it.
        if((position - waypoint).sqrMagnitude < 0.1f) {
            nextWaypointIndices[i] += (movementSpeeds[i] > 0f) ? 1 : -1;
        }
    }
}
Source Link
DMGregory
  • 140.8k
  • 23
  • 257
  • 401

Like I mentioned in the last answer, you can solve this by keeping a parallel array of data about how each instance should move. There, it was the object's speed. Here, we add the index of the waypoint it's supposed to drive toward. That way we can simulate object 1 on its way to waypoint 4 while object 5 is still working to reach waypoint 3, and they don't interfere with each other.

// Store parallel arrays for our movement parameters.
private float[] movementSpeeds;    // Randomized speed per object.
private int[] nextWaypointIndices; // Destination per object.

private void Start()
{
    // Changing terminology to be more standard.
    // - a "prefab" is a source asset you want to copy
    // - an "instance" is a copy of it that's been spawned in the scene
    instancesToMove = GameObject.FindGameObjectsWithTag("FrameLine");

    movementSpeeds = new float[instancesToMove.Length];
    nextWaypointIndices = new int[instancesToMove.Length];

    for(int i = 0; i < instancesToMove.Length; i++)
         movementSpeeds[i] = Random.Range(minSpeed, maxSpeed);
}

private void WaypointsAI()
{
    // We want to iterate over the instances, not over the waypoints.
    for (int i = 0; i < instancesToMove.Length; i++)
    {
        // Check to see if we reached the last waypoint.
        // If so, we can stop here & skip ahead to the next instance.
        if(nextWaypointIndices[i] >= waypoints.Length)
           continue;
        // You can also prune instances that are done to save processing.


        // Look up the waypoint we want to move toward next.
        Vector3 waypoint = waypoints[nextWaypointIndices[i]].position;

        // Read this instance's speed,
        // to compute how far it should move in this frame.
        float travel = movementSpeeds[i] * Time.deltaTime;

        // Apply the motion.
        Vector3 position = instancesToMove[i].transform.position;
        position = Vector3.MoveTowards(position, waypoint, travel);
        instancesToMove[i].transform.position = position;

        // If we're within a configurable tolerance of the
        // destination waypoint, set our destination
        // to the next waypoint after it.
        if((position - waypoint).sqrMagnitude < 0.1f)
            nextWaypointIndices[i]++;
    }
}