You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,再激活当前物体,确保同一时间只有一个单位响应移动输入。

方案二:用管理类统一控制(适合扩展)

如果后续要管理更多单位或添加额外逻辑,推荐用单例模式的管理类来统一处理激活状态:

  1. 创建一个空物体命名为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);
        }
    }
}
  1. 修改你的移动脚本:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 18:25:27