【Unity】Unity 中根据长方体模型的尺寸添加碰撞盒 BoxCollider

前言:
给一个长方体模型添加碰撞盒 BoxCollider,即使手动拖拽也费不了多长时间,但手动拖动不仅显得 Low ,而且准确率也不高,对于重复的工作,除非实现不了的功能,否则坚决反对用手动这种方式。

文章目录

      • 操作一:给一般长方体模型添加 BoxCollider
      • 操作二:根据长方体一条对角线的两顶点,添加 BoxCollider

操作一:给一般长方体模型添加 BoxCollider

思路
根据模型的 Mesh ,我们可以知道模型的信息,获取到的信息可以赋值给碰撞盒的大小 size 和中心 center 。

举例说明
这里我以 Unity 自带的 Cube 为例,通过编辑器方式,给 Cube 加一个和其一样大小的 BoxCollider,先来看一下效果演示图

点击 A 按钮后,会以所选物体为父物体,添加一个 BoxCollider,实现代码如下所示

    /// 
    /// 给普通的长方体模型添加 BoxCollider
    /// 
    public void AddNormalBoxCollider()
    {
        // 所选对象
        var selectObj = Selection.activeGameObject;
        var bounds = selectObj.GetComponent<MeshFilter>().sharedMesh.bounds;

        // 获得模型原始尺寸的大小
        var sizeX  = bounds.size.x * selectObj.transform.localScale.x;
        var sizeY  = bounds.size.y * selectObj.transform.localScale.y;
        var scaleZ = bounds.size.z * selectObj.transform.localScale.z;

        // 添加碰撞盒,并设置大小及中心点
        var boxCollider = Undo.AddComponent<BoxCollider>(selectObj);
        boxCollider.size   = new Vector3(sizeX, sizeY,scaleZ);
        boxCollider.center = bounds.center;
    }

操作二:根据长方体一条对角线的两顶点,添加 BoxCollider

不过,操作一只适合长方体模型,复杂一点的模型就无法通过它来实现了。可有时候一个模型中,有一部分是长方体,除了用手拖的方式添加碰撞盒,有没有可以用代码实现的呢 ?

这就是我们下面需要说的操作二了。

思路
通过选取一条对角线的两顶点,根据这两个顶点我们可以知道其它 6 个顶点的信息,比较这 8 个顶点的位置信息,我们就可以给长方体添加一个指定大小的 BoxCollider 。

举例说明
我们先来看效果演示图

实现代码如下所示

 	// 通过点击获取到的顶点列表
    public List<Vector3> VertexList; 

    /// 
    /// 通过长方体的一条对角线两个顶点,确定一个 BoxCollider
    /// 
    public void VertexBox()
    {
        if (VertexList == null) VertexList = new List<Vector3>();
        VertexList.Add(Selection.activeGameObject.transform.position);
        if (VertexList.Count != 2) return;
        for (var i = 0; i < VertexList.Count; i++)
        {
            // 变换位置,从世界坐标到局部坐标。和 Transform.TransformPoint 相反
            VertexList[i] = Selection.activeTransform.InverseTransformPoint(VertexList[i]);
        }

        float xMin, xMax = xMin = VertexList[0].x;
        float yMin, yMax = yMin = VertexList[0].y;
        float zMin, zMax = zMin = VertexList[0].z;

        foreach (var vector in VertexList)
        {
            // 获取用于创建向量的最小值和最大值。
            xMin = (vector.x < xMin) ? vector.x : xMin;
            xMax = (vector.x > xMax) ? vector.x : xMax;
            yMin = (vector.y < yMin) ? vector.y : yMin;
            yMax = (vector.y > yMax) ? vector.y : yMax;
            zMin = (vector.z < zMin) ? vector.z : zMin;
            zMax = (vector.z > zMax) ? vector.z : zMax;
        }

        var maxVector = new Vector3(xMax, yMax, zMax);
        var minVector = new Vector3(xMin, yMin, zMin);
        var size      = maxVector - minVector;
        var center    = (maxVector + minVector) / 2;

        var boxCollider = Undo.AddComponent<BoxCollider>(Selection.activeGameObject);
        boxCollider.size   = size;
        boxCollider.center = center;
        VertexList.Clear();
    }

操作步骤

第一步
先开启 Shded Wireframe 视图模式,方便我们选取模型顶点位置。

关于如何开启顶点模式,这里有两个方法

  • 方法一:通过 Shift + V 快捷键 。
  • 方法二:先点一下物体的坐标轴,再按一下 V 键并不松掉,再拖拽物体即可,拖拽过程中鼠标经过的顶点处,都会被选择到,动态演示图中用到的就是方法二。

第二步
两次点击 B 按钮,是将点击的第一个和第二个顶点位置信息记录到 VertexList 列表中,根据这两个顶点的位置信息,然后调用上面函数即可。

需要特别说明的是,方法一是直接点击物体本身就可以,而方法二是在所选物体下又新建了一个空物体,通过拖拽空物体来记录顶点坐标。

总结

方法一适合整个模型就是一个长方体,选择物体点击一次就可以生成同大小的碰撞盒。

方法二的使用范围更广,算是方法一的进阶版,凡是方法一可以实现的,方法二也都可以实现。


结束语

如果这篇博客有幸帮到了您,欢迎点击下方链接,和更多志同道合的伙伴一起交流,一起进步。

Web开发者俱乐部
在这里插入图片描述

你可能感兴趣的:(Unity)