# Unity正交相机智能包围物体(组)方案 一、技术背景 今晚是双十一,祝大家剁手愉快啊明天还得做个快乐的打工人,哈哈_~ 进入正题,最近要做个小地图显示,网上也有许多相关文章或技术实现,主要是通
Unity正交相机智能包围物体(组)方案
一、技术背景
二、相关概念
三、解决方案
- 求得物体(组)的正交投影范围;
- 移动正交相机到物体组上方的中心位置,并自动调整Size。
/// <summary>
/// 获取物体包围盒
/// </summary>
/// <param name="obj">父物体</param>
/// <returns>返回该物体(组)的包围盒</returns>
private Bounds GetBoundPointsByObj(GameObject obj)
{
var bounds = new Bounds();
if (obj != null)
{//获得所有子物体的Render
var renders = obj.GetComponentsInChildren<Renderer>();
if (renders != null)
{
//计算包围盒的中心点
var boundscenter = Vector3.zero;
foreach (var item in renders)
{
boundscenter += item.bounds.center;
}
if (obj.transform.childCount > 0)
boundscenter /= obj.transform.childCount;
//新建一个包围盒
bounds = new Bounds(boundscenter,Vector3.zero);
foreach (var item in renders)
{//构建包围盒
bounds.Encapsulate(item.bounds);
}
}
}
return bounds;
}
3.2.1 正交相机位置计算
3.2.2 正交相机Size计算
public float ScreenScaleFactor;//占屏比例系数
/// <summary>
/// 设置正交相机的Size
/// </summary>
/// <param name="xmin">包围盒x方向最小值</param>
/// <param name="xmax">包围盒x方向最大值</param>
/// <param name="ymin">包围盒y方向最小值</param>
/// <param name="ymax">包围盒y方向最大值</param>
private void SetOrthCameraSize(float xmin,float xmax,float ymin,float ymax)
{
float xDis = xmax - xmin;//x方向包围盒尺寸
float yDis = ymax - ymin;//y方向包围盒尺寸
float sizeX = xDis / ScreenScaleFactor / 2 / SetCamera.aspect;
float sizeY = yDis / ScreenScaleFactor / 2;
if (sizeX >= sizeY)//从X或Y方向选择一个合适的相机Size
SetCamera.orthographicSize = sizeX;
else
SetCamera.orthographicSize = sizeY;
}
四、总结
public class Test : MonoBehaviour
{
public GameObject Obj;//要包围的物体
public Camera SetCamera;//正交相机
public float ScreenScaleFactor;//占屏比例系数
private void Start()
{
var bound = GetBoundPointsByObj(Obj);
var center = bound.center;
var extents = bound.extents;
SetCamera.transform.position = new Vector3(center.x,center.y,center.z - 10);
SetOrthCameraSize(center.x - extents.x,center.x + extents.x,center.y - extents.y,center.y + extents.y);
}
/// <summary>
/// 获取物体包围盒
/// </summary>
/// <param name="obj">父物体</param>
/// <returns>物体包围盒</returns>
private Bounds GetBoundPointsByObj(GameObject obj)
{
var bounds = new Bounds();
if (obj != null)
{
var renders = obj.GetComponentsInChildren<Renderer>();
if (renders != null)
{
var boundscenter = Vector3.zero;
foreach (var item in renders)
{
boundscenter += item.bounds.center;
}
if (obj.transform.childCount > 0)
boundscenter /= obj.transform.childCount;
bounds = new Bounds(boundscenter,Vector3.zero);
foreach (var item in renders)
{
bounds.Encapsulate(item.bounds);
}
}
}
return bounds;
}
/// <summary>
/// 设置正交相机的Size
/// </summary>
/// <param name="xmin">包围盒x方向最小值</param>
/// <param name="xmax">包围盒x方向最大值</param>
/// <param name="ymin">包围盒y方向最小值</param>
/// <param name="ymax">包围盒y方向最大值</param>
private void SetOrthCameraSize(float xmin,float ymax)
{
float xDis = xmax - xmin;
float yDis = ymax - ymin;
float sizeX = xDis / ScreenScaleFactor / 2 / SetCamera.aspect;
float sizeY = yDis / ScreenScaleFactor / 2;
if (sizeX >= sizeY)
SetCamera.orthographicSize = sizeX;
else
SetCamera.orthographicSize = sizeY;
}
}