Unity实现NPC间隔3秒依次沿路径点移动的问题求助
实现NPC间隔3秒依次启动移动的方案
你当前的问题原因是所有NPC的Start生命周期函数几乎同时执行,每个NPC都各自等待3秒后启动移动,所以最终还是会同时触发移动逻辑。你可以选择以下两种方案实现间隔启动效果:
方案1:由WaypointsManager统一控制启动(推荐)
该方案逻辑更清晰,后续修改启动间隔、调整启动顺序都更方便。
第一步 修改WaypointsManager脚本
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; // 新增:NPC启动间隔 public float npcActivateInterval = 3f; private GameObject waypointObject; // 新增:存储生成的所有NPC的移动脚本 private List<Waypoints> spawnedNpcs = new List<Waypoints>(); void Awake() { for (int i = 0; i < numberOfWaypoints; i++) { if (useWaypointsPrefab) { // 注意:你原代码这里写的是Instantiate(npcPrefab),属于笔误,已修正 waypointObject = Instantiate(waypointsPrefab, 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); Waypoints npcMoveScript = npc.GetComponent<Waypoints>(); // 直接给NPC赋值路径点,避免每个NPC全局查找标签优化性能 npcMoveScript.waypoints = waypoints; spawnedNpcs.Add(npcMoveScript); } } } private void Start() { // 启动依次激活NPC的协程 StartCoroutine(ActivateNpcsInOrder()); } private IEnumerator ActivateNpcsInOrder() { foreach (var npc in spawnedNpcs) { npc.StartMove(); yield return new WaitForSeconds(npcActivateInterval); } } }
第二步 修改Waypoints脚本
删除原Start方法里的StartCoroutine(MoveNpc());调用,新增公共启动方法,同时可以删除原路径点查找逻辑:
// 原Start方法修改后 void Start() { // 下面这行查找路径点的代码可以删掉,路径点已经由管理器直接赋值 // waypoints = GameObject.FindGameObjectsWithTag("Waypoint").ToList(); numberOfWaypoints = waypoints.Count; if (reverse) { waypointIndex = waypoints.Count - 1; } else { waypointIndex = 0; } // 删掉原来的StartCoroutine(MoveNpc()); } // 新增公共启动方法 public void StartMove() { go = true; // 如果你需要每个NPC启动时再额外等待3秒,就把上面的go=true换成下面的协程调用 // StartCoroutine(MoveNpc()); } // 其他原有代码保持不变
方案2:仅修改NPC脚本实现(无需改动管理器)
如果不想改动管理器代码,可以用静态变量记录累计延迟时间,实现每个NPC的延迟依次叠加:
public class Waypoints : MonoBehaviour { // 新增静态变量,累计所有NPC的延迟时间 private static float totalActivateDelay = 0f; // 其他原有变量保持不变... void Start() { waypoints = GameObject.FindGameObjectsWithTag("Waypoint").ToList(); numberOfWaypoints = waypoints.Count; if (reverse) { waypointIndex = waypoints.Count - 1; } else { waypointIndex = 0; } StartCoroutine(MoveNpc()); } private IEnumerator MoveNpc() { // 每个NPC的等待时间依次叠加3秒 float currentDelay = totalActivateDelay; totalActivateDelay += 3f; yield return new WaitForSeconds(currentDelay); go = true; } // 其他原有方法保持不变... }
注意:该方案的静态变量会在场景重载、二次进入场景时保留累计值,导致延迟计算错误,你可以在场景卸载时手动重置
totalActivateDelay = 0f避免该问题。
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

