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

Unity中如何检测与禁用碰撞体的碰撞?维度切换场景需求

解决方案:检测禁用维度物体以阻止切换

禁用的GameObject不会参与任何物理检测,所以Raycast确实无法命中它们。这里提供两种可行的解决思路:

方法1:控制组件激活而非禁用整个GameObject

把原来的SetActive逻辑改成单独控制物体的渲染器和碰撞体组件,这样GameObject始终处于激活状态,物体的碰撞体可以用于检测,只是在非当前维度时不可见、不可交互。

代码示例:

public List<GameObject> redObjects;
public List<GameObject> blueObjects;
private bool seeingRed = false;

private void Update()
{
    if (Input.GetKeyDown(KeyCode.F))
    {
        // 判断是否允许切换
        bool canSwitch = true;
        if (!seeingRed)
        {
            // 要切换到红维度,检查玩家是否与红维度物体重叠
            canSwitch = !IsPlayerOverlapping(redObjects);
        }
        else
        {
            // 要切换到蓝维度,检查玩家是否与蓝维度物体重叠
            canSwitch = !IsPlayerOverlapping(blueObjects);
        }

        if (canSwitch)
        {
            seeingRed = !seeingRed;
            if (seeingRed) SetRedDimension();
            else SetBlueDimension();
        }
    }
}

// 检测玩家是否与目标维度的物体重叠
private bool IsPlayerOverlapping(List<GameObject> targetObjects)
{
    Collider playerCollider = GetComponent<Collider>();
    foreach (var obj in targetObjects)
    {
        Collider objCollider = obj.GetComponent<Collider>();
        if (objCollider != null && playerCollider.bounds.Intersects(objCollider.bounds))
        {
            return true;
        }
    }
    return false;
}

// 切换到红维度
public void SetRedDimension()
{
    ToggleDimensionObjects(redObjects, true);
    ToggleDimensionObjects(blueObjects, false);
}

// 切换到蓝维度
public void SetBlueDimension()
{
    ToggleDimensionObjects(redObjects, false);
    ToggleDimensionObjects(blueObjects, true);
}

// 统一控制维度物体的渲染和碰撞
private void ToggleDimensionObjects(List<GameObject> objects, bool isActive)
{
    foreach (var obj in objects)
    {
        if (obj.TryGetComponent(out MeshRenderer renderer))
        {
            renderer.enabled = isActive;
        }
        if (obj.TryGetComponent(out Collider collider))
        {
            collider.enabled = isActive;
        }
    }
}

优点:物体移动时,碰撞体的Bounds会自动更新,检测结果始终准确;后续扩展维度功能更灵活。
缺点:需要确保所有维度物体都有MeshRenderer和Collider组件(可以用TryGetComponent避免空引用)。


方法2:预存禁用物体的碰撞范围

如果必须保持SetActive禁用整个GameObject的逻辑,可以在游戏启动时预存所有维度物体的碰撞范围(Bounds),切换前直接用玩家的Bounds和预存范围做重叠检测。

代码示例:

public List<GameObject> redObjects;
public List<GameObject> blueObjects;
private bool seeingRed = false;
private List<Bounds> redBounds = new List<Bounds>();
private List<Bounds> blueBounds = new List<Bounds>();

private void Start()
{
    // 预存红维度物体的碰撞范围
    foreach (var obj in redObjects)
    {
        if (obj.TryGetComponent(out Collider collider))
        {
            redBounds.Add(collider.bounds);
        }
    }
    // 预存蓝维度物体的碰撞范围
    foreach (var obj in blueObjects)
    {
        if (obj.TryGetComponent(out Collider collider))
        {
            blueBounds.Add(collider.bounds);
        }
    }
}

private void Update()
{
    if (Input.GetKeyDown(KeyCode.F))
    {
        bool canSwitch = true;
        Collider playerCollider = GetComponent<Collider>();
        
        if (!seeingRed)
        {
            // 检查玩家是否与红维度物体的预存范围重叠
            foreach (var bounds in redBounds)
            {
                if (playerCollider.bounds.Intersects(bounds))
                {
                    canSwitch = false;
                    break;
                }
            }
        }
        else
        {
            // 检查玩家是否与蓝维度物体的预存范围重叠
            foreach (var bounds in blueBounds)
            {
                if (playerCollider.bounds.Intersects(bounds))
                {
                    canSwitch = false;
                    break;
                }
            }
        }

        if (canSwitch)
        {
            seeingRed = !seeingRed;
            if (seeingRed) setRed();
            else setBlue();
        }
    }
}

// 保留原来的维度切换逻辑
public void setRed()
{
    redObjects.ForEach(obj => obj.SetActive(true));
    blueObjects.ForEach(obj => obj.SetActive(false));
}

public void setBlue()
{
    redObjects.ForEach(obj => obj.SetActive(false));
    blueObjects.ForEach(obj => obj.SetActive(true));
}

优点:不需要修改原来的SetActive切换逻辑;适合物体位置固定的场景。
缺点:如果维度物体会移动,需要在物体移动时实时更新对应的Bounds列表,否则检测结果会失效。

内容的提问来源于stack exchange,提问作者Adrian Soares

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 20:15:10