系列文章目录
unity工具
文章目录
- 系列文章目录
- unity工具
- 👉前言
- 👉一、编辑器添加
- 👉二、代码动态添加的方法(第一种)
- 👉三、代码动态添加的方法(第二种)
- 👉四、重新设置模型的中心点
- 👉壁纸分享
- 👉总结
👉前言
大家好,我是心疼你的一切,不定时更新Unity开发技巧,觉得有用记得一键三连哦。
有时候我们需要用到不规则的物体,或者一大堆物体,又不想每一个物体都加上碰撞盒,所以这时候就需要把这些物体放在空物体里面,在空物体上添加根据子物体的网格生成自适应大小的碰撞盒
以下就是有编辑操作的,也可以代码生成之后操作的,具体使用看自己心情哦
提示:以下是本篇文章正文内容,下面案例可供参考
👉一、编辑器添加
1.一个空物体下面有若干个子物体,想要为空物体添加碰撞盒且碰撞盒还得要包裹所有子物体,手动拖动的话有点费时,费力,费眼,这时候有个工具是最好用的(如下图所示)
2.选中空物体点击(如下图所示)
3.点完之后的图(如下图所示)
点完之后就能看到一个全包围模型的碰撞盒,实现完成
实现如上效果需要一个编辑器脚本,脚本放在Editor文件夹下面
编辑器脚本如下
using UnityEngine;
using UnityEditor;
/// <summary>
/// 选择一个物体给当前物体添加自适应碰撞盒 编辑器脚本
/// </summary>
public class BoundsTool
{
[MenuItem("Tools/添加自适应碰撞盒")]
private static void AutoBoxCollider()
{
//如果未选中任何物体 返回
GameObject gameObject = Selection.activeGameObject;
if (gameObject == null) return;
//计算中心点
Vector3 center = Vector3.zero;
var renders = gameObject.GetComponentsInChildren<Renderer>();
for (int i = 0; i < renders.Length; i++)
{
center += renders[i].bounds.center;
}
center /= renders.Length;
//创建边界盒
Bounds bounds = new Bounds(center, Vector3.zero);
foreach (var render in renders)
{
bounds.Encapsulate(render.bounds);
}
//先判断当前是否有碰撞器 进行销毁
var currentCollider = gameObject.GetComponent<Collider>();
if (currentCollider != null) Object.DestroyImmediate(currentCollider);
//添加BoxCollider 设置中心点及大小
var boxCollider = gameObject.AddComponent<BoxCollider>();
boxCollider.center = bounds.center - gameObject.transform.position;
boxCollider.size = bounds.size;
}
}
👉二、代码动态添加的方法(第一种)
1.动态生成物体的时候,也是可以添加的
代码动态添加的第一种方法
/// <summary>
/// 自动调节碰撞盒的大小
/// </summary>
/// <param name="obj_"></param>
public void AutoBoxCollider(GameObject obj_)
{
//如果未选中任何物体 返回
GameObject gameObject = obj_;
if (gameObject == null) return;
//计算中心点
Vector3 center = Vector3.zero;
var renders = gameObject.GetComponentsInChildren<Renderer>();
for (int i = 0; i < renders.Length; i++)
{
center += renders[i].bounds.center;
}
center /= renders.Length;
//创建边界盒
Bounds bounds = new Bounds(center, Vector3.zero);
foreach (var render in renders)
{
bounds.Encapsulate(render.bounds);
}
//先判断当前是否有碰撞器 进行销毁
var currentCollider = gameObject.GetComponent<Collider>();
if (currentCollider != null) UnityEngine.Object.DestroyImmediate(currentCollider);
//添加BoxCollider 设置中心点及大小
var boxCollider = gameObject.AddComponent<BoxCollider>();
if (!gameObject.GetComponent<Highlighter>())
{
gameObject.AddComponent<Highlighter>();
}
boxCollider.center = bounds.center - gameObject.transform.position;
boxCollider.size = bounds.size;
}
结果就自行测试吧,我就不贴图片了
👉三、代码动态添加的方法(第二种)
调用方法如下
MeshTool.SpawnCollider(parents); //传一个父物体即可
代码如下
using UnityEngine;
public class MeshTool
{
public static Bounds SpawnCollider(Transform target)
{
Vector3 pMax = Vector3.zero;
Vector3 pMin = Vector3.zero;
Vector3 center = Vector3.zero;
Vector3 oldPos = target.transform.position;
Quaternion oldQua = target.transform.rotation;
Vector3 oldScale = target.transform.localScale;
target.transform.position = Vector3.zero;
target.transform.rotation = Quaternion.identity;
target.transform.localScale = Vector3.one;
Bounds bounds = CalcBounds(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;
target.transform.localScale = oldScale;
return bounds;
}
private static Bounds CalcBounds(Transform obj, ref Vector3 pMax, ref Vector3 pMin, ref Vector3 center)
{
Renderer meshRenderer = obj.GetComponent<Renderer>();
if (meshRenderer != null)
{
Bounds b = meshRenderer.bounds;
pMax = b.max;
pMin = b.min;
center = b.center;
}
RecursivelyCalcBounds(obj.transform, ref pMax, ref pMin);
CalculateCenter(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);
return bound;
}
private static void CalculateCenter(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);
}
private static void RecursivelyCalcBounds(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;
}
}
RecursivelyCalcBounds(item, ref pMax, ref pMin);
}
}
}
👉四、重新设置模型的中心点
有时候模型的轴向不准确,就需要重新设置模型的轴向了,
有时候有多个子物体的时候,想要把轴向设置到模型的中心点,这个时候就可以用了,反正只要能代码添加的,绝对不会手动添加的
能懒就懒,能不动就不动,哈哈哈…
代码方法如下
List<GameObject> ObjZ = new List<GameObject>();
Vector3 posZ = Vector3.zero;
/// <summary>
/// 设置模型的中心点,方便做模型的移动
/// </summary>
/// <param name="_trans"></param>
public void SetModelPos(Transform _trans)
{
yield return new WaitForSeconds(0.2f);
posZ = Vector3.zero;
ObjZ.Clear();
for (int i = 0; i < _trans.childCount; i++)
{
posZ += (_trans.GetChild(i).GetComponent<MeshCollider>().bounds.center);
ObjZ.Add(_trans.GetChild(i).gameObject);
}
posZ /= _trans.childCount;
for (int i = 0; i < ObjZ.Count; i++)
{
ObjZ[i].transform.parent = null;
}
_trans.position = posZ;
for (int i = 0; i < ObjZ.Count; i++)
{
ObjZ[i].transform.parent = _trans;
}
}
如果有需要会继续添加好用的小工具哦,谢谢
👉壁纸分享
👉总结
以上就是讲了如何设置碰撞盒的自适应大小,如能帮助到你,就帮忙点个三连吧,谢谢
不定时更新Unity开发技巧,觉得有用记得一键三连哦。么么哒