Mesh.bounds is the axis-aligned bounding box of the mesh in its local space (that is, not affected by the transform). Note that the Renderer.bounds property is similar but returns the bounds in world space.
https://docs.unity3d.com/ScriptReference/Mesh-bounds.html
mesh.bounds返回本地坐标的bounds,不随旋转等变化,renderer/collider.bounds返回世界坐标bounds;
如果求多个物体集合的bounds,最好获取renderer的bounds,再encapsulate(https://answers.unity.com/questions/17968/finding-the-bounds-of-a-grouped-model.html);用mesh.bounds去encapsulate不准确(encapsulate不应该传入本地坐标,
// UnityEngine.Bounds
public void Encapsulate(Bounds bounds)
{
this.Encapsulate(bounds.center - bounds.extents);
this.Encapsulate(bounds.center + bounds.extents);
}
public void Encapsulate(Vector3 point)
{
this.SetMinMax(Vector3.Min(this.min, point), Vector3.Max(this.max, point));
}
public void SetMinMax(Vector3 min, Vector3 max)
{
this.extents = (max - min) * 0.5f;
this.center = min + this.extents;
}
)
renderer.bounds
mesh.bounds
private void CalculateLocalBounds()
{
Quaternion currentRotation = this.transform.rotation;
this.transform.rotation = Quaternion.Euler(0f,0f,0f); //先重置角度
Bounds bounds = new Bounds(this.transform.position, Vector3.zero);
foreach(Renderer renderer in GetComponentsInChildren<Renderer>())
{
bounds.Encapsulate(renderer.bounds);
}
Vector3 localCenter = bounds.center - this.transform.position;
bounds.center = localCenter;
Debug.Log("The local bounds of this model is " + bounds);
this.transform.rotation = currentRotation;//恢复旋转
}
可视化脚本:
using UnityEngine;
using System.Collections;
[ExecuteInEditMode()]
public class ShowMeshBounds : MonoBehaviour
{
public Color color = Color.green;
public bool _useMeshBounds = true;
private Vector3 v3FrontTopLeft;
private Vector3 v3FrontTopRight;
private Vector3 v3FrontBottomLeft;
private Vector3 v3FrontBottomRight;
private Vector3 v3BackTopLeft;
private Vector3 v3BackTopRight;
private Vector3 v3BackBottomLeft;
private Vector3 v3BackBottomRight;
void Update()
{
CalcPositons();
DrawBox();
}
void CalcPositons()
{
Bounds bounds;
if (_useMeshBounds)
{
//bounds = GetComponent<MeshFilter>().mesh.bounds;
//multi
if (GetComponent<MeshFilter>())
bounds = GetComponent<MeshFilter>().mesh.bounds;
else
bounds = new Bounds(transform.position, Vector3.zero);
MeshFilter[] _mfs = GetComponentsInChildren<MeshFilter>();
foreach(var m in _mfs)
{
if (m != GetComponent<MeshFilter>())
bounds.Encapsulate(m.mesh.bounds);
}
}
else
{
//bounds = GetComponent<MeshRenderer>().bounds;
//bounds = GetComponent<BoxCollider>().bounds;
//bounds = GetComponent<MeshCollider>().bounds;
if (GetComponent<MeshRenderer>())
bounds = GetComponent<MeshRenderer>().bounds;
else
bounds = new Bounds(transform.position, Vector3.zero);
MeshRenderer[] _mrs = GetComponentsInChildren<MeshRenderer>();
foreach (var m in _mrs)
{
if (m != GetComponent<MeshRenderer>())
bounds.Encapsulate(m.bounds);
}
}
//BoxCollider bc = GetComponent<BoxCollider>();
//if (bc != null)
// bounds = bc.bounds;
//else
//return;
Vector3 v3Center = bounds.center;
Vector3 v3Extents = bounds.extents;
v3FrontTopLeft = new Vector3(v3Center.x - v3Extents.x, v3Center.y + v3Extents.y, v3Center.z - v3Extents.z); // Front top left corner
v3FrontTopRight = new Vector3(v3Center.x + v3Extents.x, v3Center.y + v3Extents.y, v3Center.z - v3Extents.z); // Front top right corner
v3FrontBottomLeft = new Vector3(v3Center.x - v3Extents.x, v3Center.y - v3Extents.y, v3Center.z - v3Extents.z); // Front bottom left corner
v3FrontBottomRight = new Vector3(v3Center.x + v3Extents.x, v3Center.y - v3Extents.y, v3Center.z - v3Extents.z); // Front bottom right corner
v3BackTopLeft = new Vector3(v3Center.x - v3Extents.x, v3Center.y + v3Extents.y, v3Center.z + v3Extents.z); // Back top left corner
v3BackTopRight = new Vector3(v3Center.x + v3Extents.x, v3Center.y + v3Extents.y, v3Center.z + v3Extents.z); // Back top right corner
v3BackBottomLeft = new Vector3(v3Center.x - v3Extents.x, v3Center.y - v3Extents.y, v3Center.z + v3Extents.z); // Back bottom left corner
v3BackBottomRight = new Vector3(v3Center.x + v3Extents.x, v3Center.y - v3Extents.y, v3Center.z + v3Extents.z); // Back bottom right corner
if (_useMeshBounds)
{
v3FrontTopLeft = transform.TransformPoint(v3FrontTopLeft);
v3FrontTopRight = transform.TransformPoint(v3FrontTopRight);
v3FrontBottomLeft = transform.TransformPoint(v3FrontBottomLeft);
v3FrontBottomRight = transform.TransformPoint(v3FrontBottomRight);
v3BackTopLeft = transform.TransformPoint(v3BackTopLeft);
v3BackTopRight = transform.TransformPoint(v3BackTopRight);
v3BackBottomLeft = transform.TransformPoint(v3BackBottomLeft);
v3BackBottomRight = transform.TransformPoint(v3BackBottomRight);
}
}
void DrawBox()
{
//if (Input.GetKey (KeyCode.S)) {
Debug.DrawLine(v3FrontTopLeft, v3FrontTopRight, color);
Debug.DrawLine(v3FrontTopRight, v3FrontBottomRight, color);
Debug.DrawLine(v3FrontBottomRight, v3FrontBottomLeft, color);
Debug.DrawLine(v3FrontBottomLeft, v3FrontTopLeft, color);
Debug.DrawLine(v3BackTopLeft, v3BackTopRight, color);
Debug.DrawLine(v3BackTopRight, v3BackBottomRight, color);
Debug.DrawLine(v3BackBottomRight, v3BackBottomLeft, color);
Debug.DrawLine(v3BackBottomLeft, v3BackTopLeft, color);
Debug.DrawLine(v3FrontTopLeft, v3BackTopLeft, color);
Debug.DrawLine(v3FrontTopRight, v3BackTopRight, color);
Debug.DrawLine(v3FrontBottomRight, v3BackBottomRight, color);
Debug.DrawLine(v3FrontBottomLeft, v3BackBottomLeft, color);
//}
//local pivot position
Debug.DrawLine(transform.position, transform.position + transform.forward * 10, Color.blue);
//not bounds center?
if (transform.GetComponent<MeshFilter>())
{
#if UNITY_EDITOR
Vector3 _meshboundCenter = transform.GetComponent<MeshFilter>().sharedMesh.bounds.center;
Debug.DrawLine(_meshboundCenter, _meshboundCenter + transform.forward * 10, Color.magenta);
#else
Vector3 _meshboundCenter = transform.GetComponent<MeshFilter>().mesh.bounds.center;
Debug.DrawLine(_meshboundCenter, _meshboundCenter + transform.forward * 10, Color.magenta);
#endif
}
//local center position
if (transform.GetComponent<MeshRenderer>())
{
Vector3 _boundCenter = transform.GetComponent<MeshRenderer>().bounds.center;
Debug.DrawLine(_boundCenter, _boundCenter + transform.forward * 10, Color.black);
}//draw intsect ray
//Debug.DrawLine(v3FrontTopLeft, v3FrontTopLeft-transform.forward*10, Color.red);
//Debug.DrawLine(v3FrontTopRight, v3FrontTopRight- transform.forward * 10, Color.red);
//Debug.DrawLine(v3FrontBottomRight, v3FrontBottomRight+transform.right*10, Color.red);
//Debug.DrawLine(v3FrontBottomLeft, v3FrontBottomLeft-transform.right*10, Color.red);
//
//Debug.DrawLine(v3BackTopLeft, v3BackTopLeft+transform.forward*10, Color.red);
//Debug.DrawLine(v3BackTopRight, v3BackTopRight+transform.right*10, Color.red);
//Debug.DrawLine(v3BackBottomRight, v3BackBottomRight+transform.right*10, Color.red);
//Debug.DrawLine(v3BackBottomLeft, v3BackBottomLeft-transform.up*10, Color.red);
//if(Input.GetKeyDown(KeyCode.Space))
Detect(v3FrontTopRight, v3FrontBottomRight, v3BackBottomRight, v3BackTopRight, transform.right, 8,0.05f);
}
void Detect(Vector3 p1,Vector3 p2,Vector3 p3,Vector3 p4,Vector3 _direction,float _maxDectDis,float _step)
{
int _STEP1 = (int)(Vector3.Distance(p2, p1) / _step);
int _STEP2 = (int)(Vector3.Distance(p4, p1) / _step);
float _min=float.PositiveInfinity;
RaycastHit _hit;
Vector3 _validVec=Vector3.negativeInfinity;
for (int i = 0; i <= _STEP1; i++)
{
for(int j = 0; j <= _STEP2; j++)
{
Vector3 _tmp = p1 + (p2 - p1) / _STEP1 * i + (p4 - p1) / _STEP2 * j;
Ray _ray = new Ray(_tmp, _direction);
if(Physics.Raycast(_ray, out _hit, _maxDectDis))
{
float _tmpdis = Vector3.Distance(_hit.point, _tmp);
//_min = _min < _tmpdis ? _min : _tmpdis;
if (_min > _tmpdis)
{
_min = _tmpdis;
_validVec = _tmp;
}
}
//Debug.DrawLine(_tmp, _tmp + _direction * _maxDectDis, Color.yellow);
}
}
if (_min > 0)
{
Debug.DrawLine(_validVec, _validVec + _direction * _min, Color.yellow);
Debug.Log(_min);
}
//Debug.DrawLine(p1, p1 + _direction * _maxDectDis, Color.yellow);
//Debug.DrawLine(p2, p2 + _direction * _maxDectDis, Color.yellow);
//Debug.DrawLine(p3, p3 + _direction * _maxDectDis, Color.yellow);
//Debug.DrawLine(p4, p4 + _direction * _maxDectDis, Color.yellow);
//Vector3 _center = (p1 + p2 + p3 + p4) / 4;
//Debug.DrawLine(_center, _center + _direction*_maxDectDis, Color.yellow);
}
}