简体   繁体   中英

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

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

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..

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