【问题标题】:Unity - Mismatch between OverlapBox and GizmoUnity - OverlapBox 和 Gizmo 之间的不匹配
【发布时间】:2020-08-01 17:09:35
【问题描述】:

我想使用 OverlapBox 在车辆前面创建一个框,并能够按需检查碰撞。 我使用 draw gizmo 能够看到框的大小和位置,以确认大小和位置是否正确。

这是我的代码:

public class TestCollision : MonoBehaviour
{
[Header("Collision")]
public Vector3 m_DetectorOffset = Vector3.zero;
public Vector3 m_DetectorSize = Vector3.zero;

private LayerMask m_LayerMask;
private Renderer m_Renderer = null;

void Start()
{
    m_LayerMask = (1 << LayerMask.NameToLayer("Pedestrian")) | (1 << LayerMask.NameToLayer("Vehicle"));

    m_Renderer = GetComponent<Renderer>();
    m_Renderer.material.color = Color.green;
}

private void FixedUpdate()
{
    if (CheckForCollisions())
        m_Renderer.material.color = Color.red;
    else
        m_Renderer.material.color = Color.green;
}

public bool CheckForCollisions()
{
    Vector3 colliderPos = transform.position + m_DetectorOffset;

    Collider[] colliders = Physics.OverlapBox(colliderPos, m_DetectorSize, transform.rotation, m_LayerMask);

    if (colliders.Length == 1)
    {
        // Ignore collision with itself
        if (colliders[0].gameObject == gameObject)
            return false;

        return true;
    }

    if (colliders.Length > 0)
        return true;

    return false;
}

#if UNITY_EDITOR
protected virtual void OnDrawGizmos()
{
    Gizmos.color = Color.red;
    Gizmos.matrix = transform.localToWorldMatrix;
    Gizmos.DrawWireCube(m_DetectorOffset, m_DetectorSize * 2.0f);
}
#endif
}

如果我不旋转“车辆”,此脚本效果很好 - 在图片中,蓝色立方体是我要检测的对象,绿色/红色立方体是车辆,红色线框框是 OverlapBox 表示小发明:

当“车辆”旋转时会出现问题 - 在下图中,我将车辆沿 Y 轴旋转 90 度,Gizmo 表示盒子在正确的位置,但是 OverlapBox 逻辑忽略了这种旋转(即使当对象的旋转在函数中传递):

如何使 OverlapBox 在考虑到旋转的情况下正常工作并能够表示准确的 Gizmo。

非常感谢。

【问题讨论】:

    标签: c# unity3d collision-detection


    【解决方案1】:

    设法解决了这个问题,问题是重叠框的位置和旋转。我认为旋转将从游戏对象的位置应用(当然这没有任何意义),发生的事情是旋转应用到了 OverlapBox 本身。

    在我的例子中,由于 OverlapBox 仅在车辆的前部,我将 Vector3 偏移量替换为浮点 OffsetZ(仅在 Z 轴上,如车辆前部),并更改了位置的计算CheckForCollisions 函数中的 OverlapBox 如下:

    Vector3 colliderPos = transform.position + (transform.forward * m_DetectorOffsetZ);
    

    这是使 OverlapBox 正常工作并匹配 Gizmo 的表示的最终脚本:

    public class TestCollision : MonoBehaviour
    {
    [Header("Collision")]
    public Vector3 m_DetectorOffset = Vector3.zero;
    public Vector3 m_DetectorSize = Vector3.zero;
    public float m_DetectorOffsetZ = 0.0f;
    
    private LayerMask m_LayerMask;
    private Renderer m_Renderer = null;
    
    void Start()
    {
        m_LayerMask = (1 << LayerMask.NameToLayer("Pedestrian")) | (1 << LayerMask.NameToLayer("Vehicle"));
    
        m_Renderer = GetComponent<Renderer>();
        m_Renderer.material.color = Color.green;
    }
    
    private void FixedUpdate()
    {
        if (CheckForCollisions())
            m_Renderer.material.color = Color.red;
        else
            m_Renderer.material.color = Color.green;
    }
    
    public bool CheckForCollisions()
    {
        Vector3 colliderPos = transform.position + (transform.forward * m_DetectorOffsetZ);
    
        Collider[] colliders = Physics.OverlapBox(colliderPos, m_DetectorSize, transform.rotation, m_LayerMask);
    
        if (colliders.Length == 1)
        {
            // Ignore collision with itself
            if (colliders[0].gameObject == gameObject)
                return false;
    
            return true;
        }
    
        if (colliders.Length > 0)
            return true;
    
        return false;
    }
    
    #if UNITY_EDITOR
    protected virtual void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        Gizmos.matrix = transform.localToWorldMatrix;
        Vector3 pos = Vector3.zero;
        pos.z = m_DetectorOffsetZ;
        Gizmos.DrawWireCube(pos, m_DetectorSize * 2.0f);
    }
    #endif
    }
    

    感谢 xxmariofer 在 Unity 回答论坛中的回复,我将在此处发布以防万一您想使用 Vector3 作为偏移量而不是浮点数(仅用于一个轴):

    Vector3 colliderPos = transform.TransformPoint(m_DetectorOffset);
    

    这里是帖子的链接: https://answers.unity.com/questions/1757338/mismatch-between-overlapbox-and-gizmo.html

    【讨论】:

    • 作为transform.TransformPoint 的替代方案,它还考虑了比例,如果您想为偏移量保留世界空间比例,您可以使用transform.position + transform.rotation * m_DetectorOffset;
    【解决方案2】:

    为什么不使用带有is Trigger = true 标志的collider? 重叠有利于罕见的调用,但如果你想检查每一帧你最好使用触发器和 OnTriggerEnter 方法。

    【讨论】:

    • 如果我不能让它以这种方式工作,那么我将使用 OnTriggerEnter / CollisionEnter 等等,但是我想按需进行投射(并不总是我需要检查碰撞)然后我在过去发现在对撞机中管理多个实体可能很乏味(你需要跟踪它们,如果一个被禁用而不是离开不会触发 OnExit 等......至少这是我的经验几年前使用对撞机)。
    • 您尝试过 transform.forward 吗? docs.unity3d.com/ScriptReference/Transform-forward.html
    • 非常感谢您的评论,我明白了这个问题,将发布我的解决方案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-26
    • 2016-04-23
    • 1970-01-01
    相关资源
    最近更新 更多