Unity中OnMouseDown控制多物体移动:点击第二个物体时如何停止第一个的移动?
解决Unity多物体移动互斥问题
你的问题核心在于每个GameObject上的脚本都独立维护自己的activeUnit变量,点击第二个物体时只会激活它自己,但第一个物体的activeUnit仍然是true,所以两者会同时响应移动输入。要解决这个问题,需要让所有单位共享一个“当前激活单位”的全局状态,保证同一时间只有一个单位可移动。
方案一:用静态变量实现互斥(快速解决)
直接在你的移动脚本中添加一个静态变量,存储当前激活的单位实例,每次点击新单位时先关闭之前激活单位的移动权限:
public class UnitMovement : MonoBehaviour { private bool activeUnit = false; // 静态变量:所有该脚本实例共享这个激活状态 private static UnitMovement _currentActiveUnit; void OnMouseDown() { // 如果点击的是已激活的单位,切换它的激活状态 if (_currentActiveUnit == this) { activeUnit = !activeUnit; // 取消激活时清空全局记录 if (!activeUnit) { _currentActiveUnit = null; } return; } // 关闭之前激活单位的移动 if (_currentActiveUnit != null) { _currentActiveUnit.activeUnit = false; } // 激活当前单位并更新全局记录 activeUnit = true; _currentActiveUnit = this; } void Update() { Movement(); } void Movement() { if (activeUnit) { // 这里写你的移动逻辑,比如: float h = Input.GetAxis("Horizontal"); float v = Input.GetAxis("Vertical"); transform.Translate(new Vector3(h, v, 0) * Time.deltaTime * 5f); } } }
原理说明
静态变量_currentActiveUnit属于类而非单个实例,所有挂载该脚本的物体都会共用这个变量。每次点击新物体时,先检查是否有已激活的单位,若有则关闭它的activeUnit,再激活当前物体,确保同一时间只有一个单位响应移动输入。
方案二:用管理类统一控制(适合扩展)
如果后续要管理更多单位或添加额外逻辑,推荐用单例模式的管理类来统一处理激活状态:
- 创建一个空物体命名为
UnitManager,挂载以下脚本:
public class UnitManager : MonoBehaviour { // 单例实例,方便其他脚本调用 public static UnitManager Instance; private UnitMovement _currentActiveUnit; private void Awake() { Instance = this; } // 外部调用的激活方法 public void SetActiveUnit(UnitMovement targetUnit) { // 关闭之前激活的单位 if (_currentActiveUnit != null) { _currentActiveUnit.SetActiveState(false); } // 激活新单位(如果传入null则清空激活状态) _currentActiveUnit = targetUnit; if (targetUnit != null) { targetUnit.SetActiveState(true); } } }
- 修改你的移动脚本:
public class UnitMovement : MonoBehaviour { private bool activeUnit = false; void OnMouseDown() { // 如果当前是激活状态,取消激活 if (activeUnit) { UnitManager.Instance.SetActiveUnit(null); return; } // 否则激活当前单位 UnitManager.Instance.SetActiveUnit(this); } // 提供给管理类调用的状态设置方法 public void SetActiveState(bool isActive) { activeUnit = isActive; } void Update() { Movement(); } void Movement() { if (activeUnit) { // 你的移动逻辑 } } }
原理说明
通过单例UnitManager集中管理激活状态,所有单位的激活/取消操作都通过这个类处理,逻辑更清晰,也方便后续添加单位统计、选中高亮等扩展功能。
内容的提问来源于stack exchange,提问作者strazsa
相关产品推荐
相关产品推荐

