Unity:实现MoveController支持运行时添加多个实例化预制体
问题描述
我有一套基于LeanTween的Unity脚本,可将预制体沿预设路径移动且运行正常。当前MoveController仅能绑定一个挂载Moveable脚本的对象,但我需要让运行时实例化的新预制体也能加入MoveController,跟随路径运动,求实现方法。
原代码
Moveable脚本(同时负责实例化预制体)
public class Moveable : MonoBehaviour { [SerializeField] private float _speedMetersPerSecond = 25f; private Vector3? _destination; private Vector3 _startPosition; private float _totalLerpDuration; private float _elapsedLerpDuration; private Action _onCompleteCallback; public GameObject Electron; // Update is called once per frame void Update() { if (Input.GetKeyDown(KeyCode.Space)) { var NextOnPath = Instantiate(Electron, transform.position, Quaternion.identity); NextOnPath.AddComponent<Moveable>(); } if (_destination.HasValue == false) return; if (_elapsedLerpDuration >= _totalLerpDuration && _totalLerpDuration > 0) return; _elapsedLerpDuration += Time.deltaTime; float percent = (_elapsedLerpDuration / _totalLerpDuration); Debug.Log($"{percent} = {_elapsedLerpDuration} / {_totalLerpDuration}"); transform.position = Vector3.Lerp(_startPosition, _destination.Value, percent); } public void MoveTo(Vector3 destination, Action onComplete = null) { var distanceToNextWaypoint = Vector3.Distance(transform.position, destination); _totalLerpDuration = distanceToNextWaypoint / _speedMetersPerSecond; _startPosition = transform.position; _destination = destination; _elapsedLerpDuration = 0f; _onCompleteCallback = onComplete; } }
MoveController脚本
using System.Linq; public class MoverController : MonoBehaviour { [SerializeField] private Moveable target; private List<Transform> _waypoints; private int _nextWaypointIndex; private void OnEnable() { _waypoints = GetComponentsInChildren<Transform>().ToList(); _waypoints.RemoveAt(0); MoveToNextWaypoint(); } private void MoveToNextWaypoint() { var targetWaypointTransform = _waypoints[_nextWaypointIndex]; target.MoveTo(targetWaypointTransform.position, MoveToNextWaypoint); target.transform.LookAt(_waypoints[_nextWaypointIndex].position); _nextWaypointIndex++; if (_nextWaypointIndex >= _waypoints.Count) _nextWaypointIndex = 0; } }
解决方案
修改后的Moveable脚本(关键部分)
public class Moveable : MonoBehaviour { [SerializeField] private float _speedMetersPerSecond = 25f; public List<Moveable> moveables = new List<Moveable>(); private Vector3? _destination; private Vector3 _startPosition; private float _totalLerpDuration; private float _elapsedLerpDuration; private Action _onCompleteCallback; public GameObject Electron; // Update is called once per frame void Update() { if (Input.GetKeyDown(KeyCode.Space)) { // 实例化并获取Moveable组件(建议预制体直接挂载Moveable,避免动态添加) Moveable NextOnPath = Instantiate(Electron, transform.position, Quaternion.identity).GetComponent<Moveable>(); moveables.Add(NextOnPath); // 通过单例将新对象加入控制器的目标列表 MoverController.instance.targets.Add(NextOnPath); } // 保留原Update中的移动逻辑,此处省略重复代码 } // 保留原MoveTo方法,此处省略重复代码 }
修改后的MoveController脚本(关键部分)
using System.Linq; using System.Collections.Generic; public class MoverController : MonoBehaviour { public List<Moveable> targets; [SerializeField] private Moveable initialTarget; private List<Transform> _waypoints; private int _nextWaypointIndex; public static MoverController instance; private void Awake() { // 实现单例模式,确保全局可访问 instance = this; // 初始化目标列表,加入初始绑定的对象 targets = new List<Moveable>(); if(initialTarget != null) targets.Add(initialTarget); } private void OnEnable() { _waypoints = GetComponentsInChildren<Transform>().ToList(); _waypoints.RemoveAt(0); MoveToNextWaypoint(); } private void MoveToNextWaypoint() { var targetWaypointTransform = _waypoints[_nextWaypointIndex]; // 遍历所有目标,同步发送移动指令 foreach(var moveable in targets) { moveable.MoveTo(targetWaypointTransform.position, MoveToNextWaypoint); moveable.transform.LookAt(targetWaypointTransform.position); } // 所有目标完成当前点移动后,再切换到下一个路径点 _nextWaypointIndex++; if (_nextWaypointIndex >= _waypoints.Count) _nextWaypointIndex = 0; } }
核心修改说明
- 将MoveController中单个目标改为
List<Moveable> targets,用于存储所有需要跟随路径的对象 - 给MoveController实现单例模式,让运行时实例化的对象能直接访问并加入目标列表
- 调整
MoveToNextWaypoint方法逻辑:先获取当前路径点,遍历所有目标发送移动指令后再递增路径索引,确保所有对象同步走同一个路径点(修复原方案中每个目标走不同路径点的bug) - 在Moveable的实例化逻辑中,将新创建的对象加入控制器的目标列表
内容的提问来源于stack exchange,提问作者SChen
相关产品推荐
相关产品推荐

