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

如何判断世界空间点是否在由Transform定义的盒子范围内?

问题:判断世界空间点是否在Transform定义的虚拟盒子内

我有一个对象,其Transform的position、rotation、scale分别代表一个盒子的位置、旋转与缩放。需要判断一个Vector3类型的世界空间点是否处于该虚拟盒子的范围内。

可以通过给该对象挂载默认比例的Cube子物体,或使用以下Gizmo代码查看这个虚拟盒子:

private void OnDrawGizmos()
{
    Gizmos.color = Color.blue;
    Gizmos.matrix = Matrix4x4.TRS(transform.position, transform.rotation, transform.localScale);
    Gizmos.DrawWireCube(Vector3.zero, Vector3.one);
}

需要判断类似new Vector3(0.98f, 3.2f, 1.26f)这样的世界坐标点是否在Gizmo绘制的区域内。

已尝试的方法

  • 知道可以用碰撞体(如BoxCollider.ClosestPoint)轻松解决,但场景中会在运行时创建大量GameObject组成迷宫,不需要物理系统,碰撞体可能干扰游戏其他部分,因此不能使用。
  • 网格渲染的绘制网格或bounds可能与要测试的盒子不完全匹配,视觉表现和逻辑不一致,因此也无法使用。
  • 尝试使用thatObjectWithGizmo.InverseTransformPoint(myWorldPoint)将世界点转换为本地坐标,并用以下代码测试,但返回了错误结果:
public class ScriptToTestPoint : MonoBehaviour
{
    public Transform thatObjectWithGizmo;
    public Vector3 myWorldPoint;

    public void OnDrawGizmos()
    {
        Vector3 resultingPosition = thatObjectWithGizmo.InverseTransformPoint(myWorldPoint);
        bool isInside = new Bounds(thatObjectWithGizmo.position, thatObjectWithGizmo.lossyScale).Contains(resultingPosition);

        Gizmos.color = isInside ? Color.red : Color.white;
        Gizmos.DrawSphere(transform.position, 1f);
    }
}

正确的判断方法

你的核心思路(将世界点转换到本地空间)是对的,但错误在于创建Bounds时用了世界空间的参数来匹配本地坐标。正确的做法是:

  1. 将世界空间点转换为目标对象的本地空间坐标:使用InverseTransformPoint,这一步你已经做对了。
  2. 检查转换后的本地点是否在本地空间中以原点为中心、边长为1的立方体范围内——这正好对应Gizmo绘制的盒子。

可以用两种方式实现判断:

方式一:直接判断分量范围

因为本地空间的盒子中心在原点,边长为1,所以每个轴的范围是[-0.5, 0.5],直接判断转换后的点每个分量的绝对值是否≤0.5即可:

public class ScriptToTestPoint : MonoBehaviour
{
    public Transform thatObjectWithGizmo;
    public Vector3 myWorldPoint;

    public void OnDrawGizmos()
    {
        Vector3 localPoint = thatObjectWithGizmo.InverseTransformPoint(myWorldPoint);
        // 判断每个轴是否在[-0.5, 0.5]区间内
        bool isInside = Mathf.Abs(localPoint.x) <= 0.5f 
                     && Mathf.Abs(localPoint.y) <= 0.5f 
                     && Mathf.Abs(localPoint.z) <= 0.5f;

        Gizmos.color = isInside ? Color.red : Color.white;
        Gizmos.DrawSphere(myWorldPoint, 0.1f); // 直接在测试点绘制球体更直观
    }
}

方式二:使用Bounds判断

创建一个中心在Vector3.zero、大小为Vector3.one的Bounds,用它来检查转换后的本地点:

public class ScriptToTestPoint : MonoBehaviour
{
    public Transform thatObjectWithGizmo;
    public Vector3 myWorldPoint;
    // 可以提前创建Bounds,避免每次OnDrawGizmos都实例化
    private readonly Bounds _localBoxBounds = new Bounds(Vector3.zero, Vector3.one);

    public void OnDrawGizmos()
    {
        Vector3 localPoint = thatObjectWithGizmo.InverseTransformPoint(myWorldPoint);
        bool isInside = _localBoxBounds.Contains(localPoint);

        Gizmos.color = isInside ? Color.red : Color.white;
        Gizmos.DrawSphere(myWorldPoint, 0.1f);
    }
}

这两种方式都能准确匹配Gizmo绘制的虚拟盒子范围,且完全不需要依赖物理系统或网格组件。

内容的提问来源于stack exchange,提问作者E. Zacarias

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 02:18:12