欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【包围盒计算】计算某个对象所有子对象的包围盒

程序员文章站 2024-03-16 18:20:10
...

版权所有。转载请注明出处: IT_yanghui

     在游戏开发中,很多时候不需要知道对象下的子对象是什么,只想给该对象外部加一个物理碰撞或者Collider,或者在开发中需要动态获取该对象添加Collider,然而给每一个子对象分别加,明显不现实,浪费时间且影响帧率。

     此时我们需要计算该对象所有子对象的包围盒。其实很简单的计算方法,授之于渔。

     计算包围盒,需要拿到该对象下所有Renderer,即Renderer[]。通过Renderer去计算包围盒Bounds以及中心点center :

所有Renderer的bounds通过计算得出一个整体(外部)bounds,所有Renderer的中心点center计算得出整体的中心点,有中心点和包围盒,就OK了。

     修改一下,可以添加到Unity-Component下,给策划使用,更加方便。

     代码如下:看懂了再复制粘贴。

static public class BoundsCalculate
    {
        /// <summary>
        /// 获取模型包围盒
        /// </summary>
        public static Bounds BOUNDS(this Transform model)
        {
            Vector3 oldPos = model.position;
            model.position = Vector3.zero;
            Bounds resultBounds = new Bounds(model.CENTER(), Vector3.zero);
            CalculateBounds(model, ref resultBounds);
            model.position = oldPos;
            Vector3 scalueValue = ScaleValue(model);
            resultBounds.size = new Vector3(resultBounds.size.x / scalueValue.x, resultBounds.size.y / scalueValue.y, resultBounds.size.z / scalueValue.z);
            return resultBounds;
        }

        /// <summary>
        /// 获取模型包围盒的中心点
        /// </summary>
        public static Vector3 CENTER(this Transform model)
        {
            Vector3 result = Vector3.zero;
            int counter = 0;
            CalculateCenter(model, ref result, ref counter);
            if (counter == 0) return result;
            return result / counter;
        }
        
        /// <summary>
        /// 给模型包围盒添加Collider
        /// </summary>
        public static Bounds AddBoundsCollider(this Transform model)
        {
            Bounds bounds = model.BOUNDS();
            BoxCollider collider = model.gameObject.AddComponent<BoxCollider>();
            collider.center = bounds.center;
            collider.size = bounds.size;
            return bounds;
        }

        /// <summary>
        /// 计算模型包围盒
        /// </summary>
        private static void CalculateBounds(Transform model, ref Bounds bounds)
        {
            Renderer[] renders = model.GetComponentsInChildren<Renderer>();
            foreach (Renderer child in renders)
            {
                bounds.Encapsulate(child.bounds);
            }
        }
        
        /// <summary>
        /// 计算模型中心点
        /// </summary>
        private static void CalculateCenter(Transform model, ref Vector3 result, ref int counter)
        {
            Renderer[] renders = model.GetComponentsInChildren<Renderer>();
            foreach (Renderer child in renders)
            {
                result += child.bounds.center;
                counter++;
            }
        }

        /// <summary>
        /// 获取模型Scale值
        /// </summary>
        private static Vector3 ScaleValue(Transform model)
        {
            Vector3 result = model.localScale;
            return CalculateScale(model, ref result);
        }
        
        /// <summary>
        /// 计算模型Scale值
        /// </summary>
        private static Vector3 CalculateScale(Transform model, ref Vector3 value)
        {
            if (model.parent)
            {
                Vector3 scale = model.parent.localScale;
                value = new Vector3(value.x * scale.x, value.y * scale.y, value.z * scale.z);
                CalculateScale(model.parent, ref value);
            }
            return value;
        }
        
    }