• Unity3d bounds包围盒 和collider碰撞器区别


    Bounds 外包围盒

    Bounds 叫作外包围盒、边界框、外扩矩形.是struct 结构体。而我们获得Bounds的主要途径有三种:Render,Collider,Mesh

    Render.bounds 世界坐标

    Collider.bounds 世界坐标

    Mesh.bounds  本地坐标

    1. var m= GetComponent().bounds;
    2. var c = GetComponent().bounds;
    3. var r = GetComponent().bounds;

    把 Mesh.bounds 本地坐标换算成世界坐标bounds 

    1. //把本地坐标换算成世界坐标
    2. var centerPoint = transform.TransformPoint(bounds.center);
    3. Bounds newBounds = new Bounds(centerPoint, bounds.size);

    碰撞器绿方框

    Bounds和碰撞器的绿方框(绿色线)的区别

    碰撞器的方框始终跟着模型旋转移动,缩放跟着模型的,只要模型不缩放它也不缩放

    Bounds 跟随模型移动,而不会跟模型着旋转,而是随着模型旋转而缩放变大变小,始终包裹模型.

    下面红色方框就是 Bounds 方框

    Bounds属性

    只读属性

    我们不能直接修改 Bounds 结构体里头的 center 和 size 属性都不能直接设置,而且 BoxCollider 的 bounds 属性也不能.

    .bounds.center;  //中心点坐标
    .bounds.size;        //盒子的总尺寸,xyz长度
    .bounds.min;            //最小点的位置:左下角
    .bounds.max;                //最大点的位置:右上角
    .bounds.center.x;            //中心点的X
    .bounds.center.y;                //中心点的Y

    Bounds 常用方法

    1. // 点point是否在这个包围盒内部
    2. public bool Contains(Vector3 point);
    3. // bounds会自动扩充大小(改变center和extens),来包含这个point
    4. public void Encapsulate(Vector3 point);
    5. // bounds会自动扩充大小(改变center和extens),把原本的bounds和传入的bounds都包含进来
    6. public void Encapsulate(Bounds bounds);
    7. // 这条射线是否与这个包围盒相交
    8. public bool IntersectRay(Ray ray);
    9. //包围盒最近的点
    10. public Vector3 ClosestPoint(Vector3 point);
    11. //设置边界框的最小最大值
    12. public void SetMinMax(Vector3 min, Vector3 max);

    多物体Bounds, Encapsulate方法

    计算多物体Bounds,则要遍历所有子物体,然后调用Encapsulate方法来计算。

    1. Bounds bounds;
    2. Renderer[] renderers = model.GetComponentsInChildren();
    3. for (int i = 0; i < renderers.Length; i++)
    4. {
    5.     bounds.Encapsulate(renderers[i].bounds);
    6. }


     

    计算包围盒的八个顶点

    1. center = bounds.center;
    2. ext = bounds.extents;
    3. float deltaX = Mathf.Abs(ext.x);
    4. float deltaY = Mathf.Abs(ext.y);
    5. float deltaZ = Mathf.Abs(ext.z);
    6. #region 获取AABB包围盒顶点
    7. points = new Vector3[8];
    8. points[0] = center + new Vector3(-deltaX, deltaY, -deltaZ); // 上前左(相对于中心点)
    9. points[1] = center + new Vector3(deltaX, deltaY, -deltaZ); // 上前右
    10. points[2] = center + new Vector3(deltaX, deltaY, deltaZ); // 上后右
    11. points[3] = center + new Vector3(-deltaX, deltaY, deltaZ); // 上后左
    12. points[4] = center + new Vector3(-deltaX, -deltaY, -deltaZ); // 下前左
    13. points[5] = center + new Vector3(deltaX, -deltaY, -deltaZ); // 下前右
    14. points[6] = center + new Vector3(deltaX, -deltaY, deltaZ); // 下后右
    15. points[7] = center + new Vector3(-deltaX, -deltaY, deltaZ); // 下后左
    16. #endregion

     

    绘制bounds方框

    1. ///
    2. /// 绘制Bounds方框
    3. ///
    4. ///
    5. ///
    6. ///
    7. ///
    8. public static void DrawBoundBoxLine(Bounds bounds, Color color = default(Color), float offsetSize = 1f, float duration = 0.1f)
    9. {
    10. //先计算出包围盒8个点
    11. Vector3[] points = new Vector3[8];
    12. var width_x = bounds.size.x * offsetSize;
    13. var hight_y = bounds.size.y * offsetSize;
    14. var length_z = bounds.size.z * offsetSize;
    15. var LeftBottomPoint = bounds.min;
    16. var rightUpPoint = bounds.max;
    17. var centerPoint = bounds.center;
    18. var topPoint = new Vector3(centerPoint.x, centerPoint.y + hight_y / 2, centerPoint.z);
    19. var bottomPoint = new Vector3(centerPoint.x, centerPoint.y - hight_y * 0.5f, centerPoint.z);
    20. points[0] = LeftBottomPoint + Vector3.right * width_x;
    21. points[1] = LeftBottomPoint + Vector3.up * hight_y;
    22. points[2] = LeftBottomPoint + Vector3.forward * length_z;
    23. points[3] = rightUpPoint - Vector3.right * width_x;
    24. points[4] = rightUpPoint - Vector3.up * hight_y;
    25. points[5] = rightUpPoint - Vector3.forward * length_z;
    26. points[6] = LeftBottomPoint;
    27. points[7] = rightUpPoint;
    28. Debug.DrawLine(LeftBottomPoint, points[0], color, duration);
    29. Debug.DrawLine(LeftBottomPoint, points[1], color, duration);
    30. Debug.DrawLine(LeftBottomPoint, points[2], color, duration);
    31. Debug.DrawLine(rightUpPoint, points[3], color, duration);
    32. Debug.DrawLine(rightUpPoint, points[4], color, duration);
    33. Debug.DrawLine(rightUpPoint, points[5], color, duration);
    34. Debug.DrawLine(points[1], points[3], color, duration);
    35. Debug.DrawLine(points[2], points[4], color, duration);
    36. Debug.DrawLine(points[0], points[5], color, duration);
    37. Debug.DrawLine(points[2], points[3], color, duration);
    38. Debug.DrawLine(points[0], points[4], color, duration);
    39. Debug.DrawLine(points[1], points[5], color, duration);
    40. }

    绘制碰撞器方框 -方法1

    1. ///
    2. /// 绘制boxCollider的绿色方框
    3. ///
    4. ///
    5. void DrawGizmosOnRunTime(Color color)
    6. {
    7. var boxCollider = GetComponent();
    8. Gizmos.color = color;
    9. Matrix4x4 rotationMatrix = Matrix4x4.TRS(boxCollider.transform.position, boxCollider.transform.rotation, boxCollider.transform.lossyScale);
    10. Gizmos.matrix = rotationMatrix;
    11. Gizmos.DrawWireCube(boxCollider.center, boxCollider.size);
    12. }
    13. void OnDrawGizmos()
    14. {
    15. DrawGizmosOnRunTime(Color.red);
    16. }

    绘制碰撞器方框 -方法2

    1. ///
    2. /// 绘制boxCollider的绿色方框
    3. ///
    4. ///
    5. ///
    6. ///
    7. public static void DrawOnGameViewRuntime(BoxCollider boxCollider, Color color = default(Color), float offsetSize = 1f)
    8. {
    9. float width = 0.1f;
    10. Vector3 rightDir = boxCollider.transform.right.normalized;
    11. Vector3 forwardDir = boxCollider.transform.forward.normalized;
    12. Vector3 upDir = boxCollider.transform.up.normalized;
    13. Vector3 center = boxCollider.transform.position + boxCollider.center;
    14. Vector3 size = boxCollider.size * offsetSize;
    15. size.x *= boxCollider.transform.lossyScale.x;
    16. size.y *= boxCollider.transform.lossyScale.y;
    17. size.z *= boxCollider.transform.lossyScale.z;
    18. Debug.DrawLine(center + upDir * size.y / 2f + rightDir * size.x / 2f + forwardDir * size.z / 2f, center + upDir * size.y / 2f - rightDir * size.x / 2f + forwardDir * size.z / 2f, color);
    19. Debug.DrawLine(center - upDir * size.y / 2f + rightDir * size.x / 2f + forwardDir * size.z / 2f, center - upDir * size.y / 2f - rightDir * size.x / 2f + forwardDir * size.z / 2f, color);
    20. Debug.DrawLine(center + upDir * size.y / 2f + rightDir * size.x / 2f + forwardDir * size.z / 2f, center - upDir * size.y / 2f + rightDir * size.x / 2f + forwardDir * size.z / 2f, color);
    21. Debug.DrawLine(center + upDir * size.y / 2f - rightDir * size.x / 2f + forwardDir * size.z / 2f, center - upDir * size.y / 2f - rightDir * size.x / 2f + forwardDir * size.z / 2f, color);
    22. Debug.DrawLine(center + upDir * size.y / 2f + rightDir * size.x / 2f - forwardDir * size.z / 2f, center + upDir * size.y / 2f - rightDir * size.x / 2f - forwardDir * size.z / 2f, color);
    23. Debug.DrawLine(center - upDir * size.y / 2f + rightDir * size.x / 2f - forwardDir * size.z / 2f, center - upDir * size.y / 2f - rightDir * size.x / 2f - forwardDir * size.z / 2f, color);
    24. Debug.DrawLine(center + upDir * size.y / 2f + rightDir * size.x / 2f - forwardDir * size.z / 2f, center - upDir * size.y / 2f + rightDir * size.x / 2f - forwardDir * size.z / 2f, color);
    25. Debug.DrawLine(center + upDir * size.y / 2f - rightDir * size.x / 2f - forwardDir * size.z / 2f, center - upDir * size.y / 2f - rightDir * size.x / 2f - forwardDir * size.z / 2f, color);
    26. Debug.DrawLine(center + upDir * size.y / 2f + rightDir * size.x / 2f + forwardDir * size.z / 2f, center + upDir * size.y / 2f + rightDir * size.x / 2f - forwardDir * size.z / 2f, color);
    27. Debug.DrawLine(center - upDir * size.y / 2f + rightDir * size.x / 2f + forwardDir * size.z / 2f, center - upDir * size.y / 2f + rightDir * size.x / 2f - forwardDir * size.z / 2f, color);
    28. Debug.DrawLine(center + upDir * size.y / 2f - rightDir * size.x / 2f + forwardDir * size.z / 2f, center + upDir * size.y / 2f - rightDir * size.x / 2f - forwardDir * size.z / 2f, color);
    29. Debug.DrawLine(center - upDir * size.y / 2f - rightDir * size.x / 2f + forwardDir * size.z / 2f, center - upDir * size.y / 2f - rightDir * size.x / 2f - forwardDir * size.z / 2f, color);
    30. }

    求两个包围盒之间的距离

    1. // Distance between two ClosestPointOnBounds
    2. // this is needed in cases where entites are really big. in those cases,
    3. // we can't just move to entity.transform.position, because it will be
    4. // unreachable. instead we have to go the closest point on the boundary.
    5. //
    6. // Vector3.Distance(a.transform.position, b.transform.position):
    7. // _____ _____
    8. // | | | |
    9. // | x==|======|==x |
    10. // |_____| |_____|
    11. //
    12. //
    13. // Utils.ClosestDistance(a.collider, b.collider):
    14. // _____ _____
    15. // | | | |
    16. // | |x====x| |
    17. // |_____| |_____|
    18. //
    19. public static float ClosestDistance(Collider a, Collider b)
    20. {
    21. return Vector3.Distance(a.ClosestPointOnBounds(b.transform.position),
    22. b.ClosestPointOnBounds(a.transform.position));
    23. }

     求点A到包围盒最近的点,ClosestPoint

     计算所有包围盒的中心点

    计算出多个Bounds的中心点

    1. [MenuItem ("MyMenu/Do Test")]
    2. static void Test ()
    3. {
    4. Transform parent = Selection.activeGameObject.transform;
    5. Vector3 postion = parent.position;
    6. Quaternion rotation = parent.rotation;
    7. Vector3 scale = parent.localScale;
    8. parent.position = Vector3.zero;
    9. parent.rotation = Quaternion.Euler(Vector3.zero);
    10. parent.localScale = Vector3.one;
    11. Vector3 center = Vector3.zero;
    12. Renderer[] renders = parent.GetComponentsInChildren();
    13. foreach (Renderer child in renders){
    14. center += child.bounds.center;
    15. }
    16. center /= parent.GetComponentsInChildren().Length;
    17. Bounds bounds = new Bounds(center,Vector3.zero);
    18. foreach (Renderer child in renders){
    19. bounds.Encapsulate(child.bounds);
    20. }
    21. parent.position = postion;
    22. parent.rotation = rotation;
    23. parent.localScale = scale;
    24. foreach(Transform t in parent){
    25. t.position = t.position - bounds.center;
    26. }
    27. parent.transform.position = bounds.center + parent.position;
    28. }

    参考 

      https://blog.csdn.net/sinat_25415095/article/details/104588989

    https://www.5axxw.com/questions/content/imitu9

  • 相关阅读:
    使用el-table的树状结构数据的勾选列,可以勾选第一层级,但是第二级之后的都不支持勾选
    跨域和同源
    CVE-2019-1388 UAC提权实战
    基于springboot会员制医疗预约服务管理信息系统设计与实现-计算机毕业设计源码和LW文档
    【LSTM回归预测】基于斑马算法优化卷积神经网络结合注意力机制的长短记忆网络ZOA-CNN-LSTM-Attention实现风电功率多输入单输出回归预测附matlab代码
    艾尔登法环约定之王拉塔恩打法
    lv7 嵌入式开发-网络编程开发 06 socket套接字及TCP的实现框架
    「从零单排canal 07」 parser模块源码解析
    【Vue3-Flask-BS架构Web应用】实践笔记1-使用一个bat脚本自动化完整部署环境
    Yonbuilder参考
  • 原文地址:https://blog.csdn.net/u013628121/article/details/128117992