Home > database >  How can I make that each npc will start moving along the waypoints after 3 seconds of delay?
How can I make that each npc will start moving along the waypoints after 3 seconds of delay?

Time:11-30

This is the waypoints manager script attached to empty GameObject :

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class WaypointsManager : MonoBehaviour
{
    public GameObject npcPrefab;
    public int numberOfNpcs;
    public GameObject waypointsPrefab;
    public List<GameObject> waypoints = new List<GameObject>();
    public int numberOfWaypoints;
    public bool useWaypointsPrefab = false;

    private GameObject waypointObject;

    // Start is called before the first frame update
    void Awake()
    {
        for (int i = 0; i < numberOfWaypoints; i  )
        {
            if (useWaypointsPrefab)
            {
                waypointObject = Instantiate(npcPrefab, Vector3.zero, Quaternion.identity);
            }
            else
            {
                waypointObject = new GameObject();
            }
            waypointObject.tag = "Waypoint";
            waypointObject.name = "Waypoint";
            waypointObject.transform.position = new Vector3(Random.Range(0, 10), Random.Range(0, 10), Random.Range(0, 10));
            waypoints.Add(waypointObject);
        }

        for (int i = 0; i < numberOfNpcs; i  )
        {
            if (npcPrefab != null)
            {
               GameObject npc = Instantiate(npcPrefab, Vector3.zero, Quaternion.identity);
            }
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

And this script is attached to each npc :

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class Waypoints : MonoBehaviour
{
    public List<GameObject> waypoints = new List<GameObject>();
    public float movementSpeed;
    public float rotationSpeed;
    public bool reverse = false;
    public bool go = false;
    public int numberOfWaypoints;
    public int nextWaypointNumber;

    private int waypointIndex = 0;
    private GameObject nextWayPoint;

    // Start is called before the first frame update
    void Start()
    {
        waypoints = GameObject.FindGameObjectsWithTag("Waypoint").ToList();

        numberOfWaypoints = waypoints.Count;

        if (reverse)
        {
            waypointIndex = waypoints.Count - 1;
        }
        else
        {
            waypointIndex = 0;
        }

        StartCoroutine(MoveNpc());
    }

    // Update is called once per frame
    void Update()
    {
        if (go)
        {
            if (reverse && waypointIndex == 0)
            {
                waypointIndex = waypoints.Count - 1;
            }

            if (reverse == false && waypointIndex == waypoints.Count)
            {
                waypointIndex = 0;
            }

            nextWayPoint = waypoints[waypointIndex];
            nextWaypointNumber = waypointIndex;

            transform.position = Vector3.MoveTowards(transform.position,
            waypoints[waypointIndex].transform.position, Time.deltaTime * movementSpeed);

            float distance = Vector3.Distance(transform.position, waypoints[waypointIndex].transform.position);
            if (distance > 0f)
            {
                // Try to rotate to face the waypoint only if we're not on top of it.
                var rotation = Quaternion.LookRotation(nextWayPoint.transform.position - transform.position);
                transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * rotationSpeed);
            }
            else
            {
                numberOfWaypoints--;

                if (reverse)
                {
                    waypointIndex--;
                }
                else
                {
                    waypointIndex  ;
                }
            }
        }
    }

    private IEnumerator MoveNpc()
    {
        yield return new WaitForSeconds(3f);

        go = true;
    }

    private void OnDrawGizmos()
    {
        if (waypoints != null)
        {
            for (int i = 0; i < waypoints.Count; i  )
            {
                Gizmos.color = Color.green;
                Gizmos.DrawSphere(waypoints[i].transform.position, 0.1f);
            }
        }

        if (nextWayPoint != null)
        {
            Gizmos.color = Color.red;
            Gizmos.DrawLine(transform.position, nextWayPoint.transform.position);
        }
    }
}

In the Waypoints script I'm starting a coroutine with a 3 seconds delay but still all the npcs are moving at the same time like one npc. I want it to wait 3 seconds send npc wait 3 seconds send npc until all npcs are moving along the waypoints.

StartCoroutine(MoveNpc());

CodePudding user response:

ISSUE
All npcs are being spawned at the same time, each waits 3 seconds (all at the same time), and then start moving.

SOLUTION
You could create a function that takes the amount of time they need to wait, and use that delay time in your coroutine.

NPC

public void StartMovingAfterSeconds(float seconds) 
{
    StartCoroutine(MoveNPC(seconds));
}
private IEnumerator MoveNpc(float delayTimeSeconds)
{
    yield return new WaitForSeconds(delayTimeSeconds);

    go = true;
}

From your manager you will need to track the delay time as you spawn the npcs.

MANAGER

// Amount to delay movement by (can be exposed in the inspector)
//
var delayTime = 3f;

// Accumulated delay
//
var currentDelay = 0f;

if (npcPrefab != null)
{
    for (int i = 0; i < numberOfNpcs; i  )
    {
        var npc = Instantiate(npcPrefab, Vector3.zero, Quaternion.identity);
       
        npc.StartMovingAfterSeconds(currentDelay);
       
        currentDelay  = delayTime;
    }
}

We start with a delay of 0 (currentDelay) and add the amount we want to delay by (delayTime) in each iteration. The first delay is 0, next is 3, then 6, etc..

  • Related