立即从 3D 管道访问 2D 框的 Unity 功能?

Posted

技术标签:

【中文标题】立即从 3D 管道访问 2D 框的 Unity 功能?【英文标题】:Unity function to access the 2D box immediately from the 3D pipeline? 【发布时间】:2018-08-18 06:29:49 【问题描述】:

在 Unity 中,假设您有一个 3D 对象,

当然,获得AABB是微不足道的,Unity有直接的功能,

(您可能必须以通常的方式“将渲染器的所有边界框相加”,没问题。)

所以 Unity 确实有一个直接功能,可以立即为您提供 3D AABB 盒子,而不是每帧的内部网格/渲染管道。

现在,对于有问题的相机,AABB 确实覆盖了某个 2D 边界框...

事实上......有没有某种内置的直接方法可以在 Unity 中找到橙色的 2D 框??

问题 - Unity 是否有一个功能可以立即从管道中提供 2D 截锥体?

(请注意,要手动执行此操作,您只需为 AABB 的 8 个点制作光线(或使用世界到屏幕空间,就像 Draco 提到的那样);将它们封装在 2D 中以制作橙色框。)

我不需要手动解决方案,我问的是引擎是否在每一帧都以某种方式从管道中给出这个?

有电话吗?

(确实,有这个会更好……)

我的感觉是其中的一个或全部

尤其是遮挡系统 着色器 渲染器

肯定会知道橙色框,甚至可能知道管道内的蓝色框,就在显卡旁边,就像它知道给定网格的 AABB 一样。

我们知道 Unity 可以让您在给定网格的每一帧立即点击 AABB 3D 框:事实上,Unity 是否提供了此处所示的“2D 视锥体边界”?

【问题讨论】:

这是一个有趣的问题... @Programmer 我想是的。 我也是。很明显,(1) 整体渲染引擎和/或 (2) 着色器和/或 (3) 遮挡系统,实际上必须立即知道此信息 在每个对象的每一帧内。 ( @Hristo - 该算法实际上不起作用!想一想物体何时旋转。您将立即面临扩展/收缩侧面以包含局部截头体部分断裂的主要工作。A非常困难的问题。) 最后只是 FWIW,@Lotan - 我们想要的是 AABB 的“平板相机盒”。即“橙色方块”。使用 8 个极端手动(正如我解释的那样)相对容易。问题是统一是否内置(可能在金属上)。 (我关于 blue 框的附录完全不同;但谁知道呢,也许 Unity 也提供了。) 【参考方案1】:

据我所知,没有内置为此。

但是,自己找到极端确实非常容易。获取网格的边界框(屏幕截图中显示的长方体)就是这样做的,您只是在转换后的空间中进行。

    遍历网格的所有顶点,执行以下操作: Transform 从本地空间到世界空间的点(处理缩放和旋转) Transform从世界空间到屏幕空间的点 确定新点的 X 和 Y 是否高于/低于存储的最小值/最大值,如果是,则使用新值更新存储的最小值/最大值 循环遍历所有顶点后,您将获得 4 个值:min-X、min-Y、max-X 和 max-Y。现在您可以构建边界矩形了

您可能还希望首先执行模型的Gift Wrapping,并且只处理生成的凸包(因为不属于凸包的任何点都不会超出凸包的边界)。如果您打算在模型在屏幕上移动、缩放或旋转时绘制此屏幕空间矩形,并且必须重新计算边界框,那么您需要这样做并缓存结果。

请注意,如果模型动画(例如,如果您的类人机器人站起来并跳起千斤顶),这起作用。解决动画案例要困难得多,因为您必须将每个动画的每一帧都视为原始网格的一部分,以便进行凸包求解(以确保您的任何动画都不会移动网格的一部分在凸包之外),将复杂度增加一个幂。

【讨论】:

嘿 Draco,游戏引擎在芯片组上计算这些东西是(如问题中所解释的)三个过程的一部分 - 渲染、着色器、遮挡。事实上,我们知道 Unity 公开了 AABB 计算(因此自己计算会很疯狂,对吧?:))。这里的问题是截锥体 是否在 Unity 中暴露(就像 AABB 流一样,每一帧)。 我已经删除了我自己的 cmets 并编辑了答案。 它看到“据我所知,没有内置的。”实际上是正确 - 就是这样!【参考方案2】:

3D 边界框

    获取给定的 GameObject 3D 边界框的中心和大小 计算 8 个角 将位置转换为 GUI 空间(屏幕空间)

函数GUI3dRectWithObject将返回屏幕上给定游戏对象的3D边界框。

二维边界框

    遍历给定游戏对象中的每个顶点 将每个顶点的位置转换为世界空间,并转换为 GUI 空间(屏幕空间) 求4个角值:x1,x2,y1,y2

函数GUI2dRectWithObject 将返回屏幕上给定游戏对象的二维边界框。

代码

public static Rect GUI3dRectWithObject(GameObject go)


    Vector3 cen = go.GetComponent<Renderer>().bounds.center;
    Vector3 ext = go.GetComponent<Renderer>().bounds.extents;
    Vector2[] extentPoints = new Vector2[8]
    
            WorldToGUIPoint(new Vector3(cen.x-ext.x, cen.y-ext.y, cen.z-ext.z)),
            WorldToGUIPoint(new Vector3(cen.x+ext.x, cen.y-ext.y, cen.z-ext.z)),
            WorldToGUIPoint(new Vector3(cen.x-ext.x, cen.y-ext.y, cen.z+ext.z)),
            WorldToGUIPoint(new Vector3(cen.x+ext.x, cen.y-ext.y, cen.z+ext.z)),
            WorldToGUIPoint(new Vector3(cen.x-ext.x, cen.y+ext.y, cen.z-ext.z)),
            WorldToGUIPoint(new Vector3(cen.x+ext.x, cen.y+ext.y, cen.z-ext.z)),
            WorldToGUIPoint(new Vector3(cen.x-ext.x, cen.y+ext.y, cen.z+ext.z)),
            WorldToGUIPoint(new Vector3(cen.x+ext.x, cen.y+ext.y, cen.z+ext.z))
    ;
    Vector2 min = extentPoints[0];
    Vector2 max = extentPoints[0];
    foreach (Vector2 v in extentPoints)
    
        min = Vector2.Min(min, v);
        max = Vector2.Max(max, v);
    
    return new Rect(min.x, min.y, max.x - min.x, max.y - min.y);


public static Rect GUI2dRectWithObject(GameObject go)

    Vector3[] vertices = go.GetComponent<MeshFilter>().mesh.vertices;

    float x1 = float.MaxValue, y1 = float.MaxValue, x2 = 0.0f, y2 = 0.0f;

    foreach (Vector3 vert in vertices)
    
        Vector2 tmp = WorldToGUIPoint(go.transform.TransformPoint(vert));

        if (tmp.x < x1) x1 = tmp.x;
        if (tmp.x > x2) x2 = tmp.x;
        if (tmp.y < y1) y1 = tmp.y;
        if (tmp.y > y2) y2 = tmp.y;
    

    Rect bbox = new Rect(x1, y1, x2 - x1, y2 - y1);
    Debug.Log(bbox);
    return bbox;


public static Vector2 WorldToGUIPoint(Vector3 world)

    Vector2 screenPoint = Camera.main.WorldToScreenPoint(world);
    screenPoint.y = (float)Screen.height - screenPoint.y;
    return screenPoint;

参考:Is there an easy way to get on-screen render size (bounds)?

【讨论】:

以上是关于立即从 3D 管道访问 2D 框的 Unity 功能?的主要内容,如果未能解决你的问题,请参考以下文章

《Unity3D/2D游戏开发从0到1》正式出版发行

unity 怎么计算资源加载时间

unity3d开发2d游戏中Assetbundle有啥作用

关于《Unity3D/2D游戏开发从0到1》书籍再版说明

cocos2d转unity3d小结

如何在 Unity 中从 3D 对象中获取 2D 视图/纹理