效果展示:
-
根据子物体Mesh,一键计算父物体身上的碰撞器
-
当物体发生变化后,也能再次一键适配
-
这里运用到了Unity自带的Bounds,取所有子物体的临界边界给父物体
using UnityEngine;
using UnityEditor;
[RequireComponent(typeof(BoxCollider))]
public class TS_ChildrenColliderFit : MonoBehaviour
{
public bool fitColliderInEditorMode = false;
private void Start()
{
FitColliderToChildren();
}
#if UNITY_EDITOR
// 在编辑器模式下执行
private void OnValidate()
{
if (fitColliderInEditorMode)
{
FitColliderToChildren();
}
}
#endif
void FitColliderToChildren()
{
BoxCollider parentCollider = GetComponent<BoxCollider>();
if (parentCollider == null)
{
Debug.LogError("物体BoxCollider丢失");
return;
}
// 初始化父物体的边界为第一个子物体的边界
Bounds bounds = GetBoundsOfFirstChild();
// 遍历所有子物体,扩展边界以包含所有子物体的边界
foreach (Transform child in transform)
{
Bounds childBounds = GetBoundsRecursive(child);
bounds.Encapsulate(childBounds);
}
// 设置父物体的BoxCollider大小
parentCollider.center = bounds.center - transform.position;
parentCollider.size = bounds.size;
}
Bounds GetBoundsOfFirstChild()
{
Transform firstChild = transform.GetChild(0);
return GetBoundsRecursive(firstChild);
}
Bounds GetBoundsRecursive(Transform target)
{
Renderer renderer = target.GetComponent<Renderer>();
if (renderer != null)
{
return renderer.bounds;
}
// 如果没有Renderer组件,继续递归检查子物体
Bounds bounds = new Bounds(target.position, Vector3.zero);
foreach (Transform child in target)
{
bounds.Encapsulate(GetBoundsRecursive(child));
}
return bounds;
}
}
扩展思路:
以虚拟仿真项目为例,在开发项目中,可将上述脚本连同 语音读表、高亮插件、UI指引等一同封装起来,这样在开发过程中,通过交互物体ID读表查找所关联的语音、UI、动画名称等,每一步只用传入一个交互物体和触发结果,就能高效率的将流程走完。