Unity中模型动态添加贴合模型的BoxCollider,适用于多模型组合的,并且旋转后的模型

笔记记录,由于项目需求需要给模型动态添加或者更新贴合模型的BoxCollider,因为模型没有规范的,有些模型是旋转过的,有些是由多个模型组合成一个完整的模型,因此在网上找了很多介绍和动态添加贴合模型的BoxCollider的方法和脚本,要么只适用于单个模型的,不适用于多个模型组合而成的,要么适用了多个模型组合的,但是对旋转过的模型,又不适用因为模型旋转了再添加的BoxCollider后计算出来的碰撞盒是没旋转前的数据,导致不能和模型匹配而有问题。下面这个方法可以同时适用于多个模型组合而成的模型,并且适用于旋转过的模型,由于适用于多个模型组合的,因此可以在父节点上没有Mesh组件直接查找所有子物体创建一个贴合模型的BoxCollider,脚本如下:

using UnityEngine;

public class MeshTool
{
    public static Bounds SpownCollider(Transform target)
    {
        Vector3 pMax = Vector3.zero;
        Vector3 pMin = Vector3.zero;
        Vector3 center = Vector3.zero;

        Vector3 oldPos = target.transform.position;
        Quaternion oldQua = target.transform.rotation;

        target.transform.position = Vector3.zero;
        target.transform.rotation = Quaternion.identity;

        Bounds bounds = ClacBounds(target, ref pMax, ref pMin, ref center);

        BoxCollider collider = target.GetComponent<BoxCollider>();
        if (collider == null)
        {
            collider = target.gameObject.AddComponent<BoxCollider>();
        }
        collider.center = bounds.center;
        collider.size = bounds.size;

        target.transform.position = oldPos;
        target.transform.rotation = oldQua;

        return bounds;
    }

    /// <summary>
    /// 计算目标包围盒
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    private static Bounds ClacBounds(Transform obj, ref Vector3 pMax,ref Vector3 pMin, ref Vector3 center)
    {
        Renderer mesh = obj.GetComponent<Renderer>();

        if (mesh != null)
        {
            Bounds b = mesh.bounds;
            pMax = b.max;
            pMin = b.min;
            center = b.center;
        }


        RecursionClacBounds(obj.transform,ref pMax, ref pMin);

        ClacCenter(pMax, pMin, out center,ref pMax,ref pMin);

        Vector3 size = new Vector3(pMax.x - pMin.x, pMax.y - pMin.y, pMax.z - pMin.z);
        Bounds bound = new Bounds(center, size);
        bound.size = size;

        Debug.Log("size>" + size);
        bound.extents = size / 2f;

        return bound;
    }
    /// <summary>
    /// 计算包围盒中心坐标
    /// </summary>
    /// <param name="max"></param>
    /// <param name="min"></param>
    /// <param name="center"></param>
    private static void ClacCenter(Vector3 max, Vector3 min, out Vector3 center,ref Vector3 pMax,ref Vector3 pMin)
    {
        float xc = (pMax.x + pMin.x) / 2f;
        float yc = (pMax.y + pMin.y) / 2f;
        float zc = (pMax.z + pMin.z) / 2f;

        center = new Vector3(xc, yc, zc);
        Debug.Log("center>" + center);
    }
    /// <summary>
    /// 计算包围盒顶点
    /// </summary>
    /// <param name="obj"></param>
    private static void RecursionClacBounds(Transform obj, ref Vector3 pMax, ref Vector3 pMin)
    {
        if (obj.transform.childCount <= 0)
        {
            return;
        }

        foreach (Transform item in obj)
        {
            Renderer m = item.GetComponent<Renderer>();



            if (m != null)
            {
                Bounds b = m.bounds;
                if (pMax.Equals(Vector3.zero) && pMin.Equals(Vector3.zero))
                {
                    pMax = b.max;
                    pMin = b.min;
                }

                if (b.max.x > pMax.x)
                {
                    pMax.x = b.max.x;
                }

                if (b.max.y > pMax.y)
                {
                    pMax.y = b.max.y;
                }
                if (b.max.z > pMax.z)
                {
                    pMax.z = b.max.z;
                }
                if (b.min.x < pMin.x)
                {
                    pMin.x = b.min.x;
                }

                if (b.min.y < pMin.y)
                {
                    pMin.y = b.min.y;
                }
                if (b.min.z < pMin.z)
                {
                    pMin.z = b.min.z;
                }
            }
            RecursionClacBounds(item, ref pMax, ref pMin);
        }
    }
} 

使用时直接通过调用MeshTool.SpownCollider(targetTransform)方法即可,参数填写需要添加BoxCollider组件的对象的Transform。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TenderRain。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值