Unity中如何通过Bool值触发事件控制玩家样条移动启停?
解决方案
先修正现有代码的核心问题
当前代码存在逻辑漏洞,先调整才能正常工作:
事件需传递Bool状态
原Action不带参数,无法区分“启动”和“停止”,改成带Bool参数的Action<bool>,一个事件即可处理两种状态:// GameController 中修改事件定义 public event Action<bool> OnRaceStateChanged; public void SetRaceState(bool isStarted) { OnRaceStateChanged?.Invoke(isStarted); }修复协程启停逻辑
直接用StopCoroutine(PlayerSpeed())可能失效,Unity需要匹配协程引用才能正确停止;同时原订阅逻辑错误(未添加订阅就取消),调整响应脚本:private Coroutine _playerSpeedCoroutine; // 保存协程引用,确保能正确停止 void Start() { // 订阅带状态的事件 GameController.Instance.OnRaceStateChanged += HandleRaceStateChange; } // 统一处理启停 private void HandleRaceStateChange(bool isRaceActive) { if (isRaceActive) { // 避免重复启动协程 if (_playerSpeedCoroutine == null) { _playerSpeedCoroutine = StartCoroutine(PlayerSpeed()); } } else { // 通过引用停止协程 if (_playerSpeedCoroutine != null) { StopCoroutine(_playerSpeedCoroutine); _playerSpeedCoroutine = null; } // 立即重置速度 Player1Speed = 0; Player2Speed = 0; Player1Follow.GetComponent<PlayerFollow>().speed = 0; Player2Follow.GetComponent<PlayerFollow>().speed = 0; } } public IEnumerator PlayerSpeed() { // 用单例获取GameController,避免重复GetComponent while (GameController.Instance.raceStarted) { Player1Follow.GetComponent<PlayerFollow>().speed = Player1Speed / SpeedAdjustmentRatio; Player2Follow.GetComponent<PlayerFollow>().speed = Player2Speed / SpeedAdjustmentRatio; yield return new WaitForSeconds(0.1f); } // 协程结束后清空引用 _playerSpeedCoroutine = null; }确保单例正确初始化
在GameController的Awake方法里初始化单例,避免空引用:public static GameController Instance; void Awake() { Instance = this; }
添加Inspector可见的Bool触发器
有两种简单实现方式:
方式1:在GameController中加公开Bool变量+OnValidate
直接在GameController中添加公开Bool变量,利用Unity的OnValidate方法监听编辑器中的变量变化,自动触发事件:
public class GameController : MonoBehaviour { public static GameController Instance; public event Action<bool> OnRaceStateChanged; // 这个变量会显示在Inspector面板 public bool raceStarted; void Awake() { Instance = this; } // 编辑器中变量修改时自动调用 void OnValidate() { SetRaceState(raceStarted); } public void SetRaceState(bool isStarted) { raceStarted = isStarted; // 同步变量值 OnRaceStateChanged?.Invoke(isStarted); } }
现在你在Inspector里勾选/取消raceStarted,就能直接触发启停逻辑。
方式2:单独写调试控制脚本
如果不想污染GameController的逻辑,可以写一个独立的调试脚本,挂在任意物体上:
using UnityEngine; public class RaceDebugTool : MonoBehaviour { [Header("Race Control")] [SerializeField] private bool startRace; [SerializeField] private bool stopRace; void OnValidate() { if (startRace) { GameController.Instance.SetRaceState(true); startRace = false; // 重置状态,避免重复触发 } if (stopRace) { GameController.Instance.SetRaceState(false); stopRace = false; } } }
挂好后,Inspector里会出现两个Bool选项,勾选startRace启动比赛,勾选stopRace停止,勾选后自动重置,方便重复操作。
额外优化建议
- 把
Player1Follow和Player2Follow在Inspector里直接赋值,不要每次用GetComponent,提升性能和稳定性。 - 确保场景中只有一个GameController实例,避免单例冲突。
内容的提问来源于stack exchange,提问作者greyBow
相关产品推荐
相关产品推荐

