
image.png

image.png

image.png
邏輯原理:
- 遍歷所有的子Transform
- 查找?guī)enderer的取Renderer的世界位置的Bound中心值,不帶Renderer的看是否只有一個(gè)Transform或者沒有子物體的取世界坐標(biāo)每次計(jì)算xyz分量的最大和最小值
- 最后把最大和最小的取中
上代碼:
using UnityEditor;
using UnityEngine;
public class TransformCenterOnChildren : Editor
{
[MenuItem("Tools/坐標(biāo)歸到子物體中心點(diǎn)位置")]
static void Start()
{
GameObject[] seGO = Selection.gameObjects;
if (seGO.Length == 0)
{
return;
}
for (int i = 0; i < seGO.Length; i++)
{
Transform curTr = seGO[i].transform;
Vector3 curPos = curTr.position;
Vector3 cenPos = Center(curTr);
int childCount = curTr.childCount;
for (int k = 0; k < childCount; k++)
{
Vector3 offset = cenPos - curPos;
curTr.GetChild(k).position -= offset;
}
Undo.RecordObject(curTr, "變換當(dāng)前位置");
curTr.position = cenPos;
}
}
/// <summary>
/// 計(jì)算子層級的物體中心點(diǎn)
/// </summary>
/// <param name="parentTransform">當(dāng)前的 Transform</param>
/// <returns>返回子物體的中心點(diǎn)</returns>
static Vector3 Center(Transform parentTransform)
{
// 獲取當(dāng)前 Transform 的所有子物體
Transform[] allTrans = parentTransform.GetComponentsInChildren<Transform>(true);
if (allTrans.Length == 1)
{
return parentTransform.position;
}
//初始化初始值
float xMax = allTrans[1].position.x,
yMax = allTrans[1].position.y,
zMax = allTrans[1].position.z,
xMin = allTrans[1].position.x,
yMin = allTrans[1].position.y,
zMin = allTrans[1].position.z;
foreach (var tran in allTrans)
{
if (tran.TryGetComponent(out Renderer renderer))
{
// 獲取子物體包圍盒中心點(diǎn)(在世界坐標(biāo)系中)
Vector3 childBoundsCenter = renderer.bounds.center;
// 計(jì)算所有子物體中心點(diǎn)的最大最小值
xMax = Mathf.Max(childBoundsCenter.x, xMax);
yMax = Mathf.Max(childBoundsCenter.y, yMax);
zMax = Mathf.Max(childBoundsCenter.z, zMax);
xMin = Mathf.Min(childBoundsCenter.x, xMin);
yMin = Mathf.Min(childBoundsCenter.y, yMin);
zMin = Mathf.Min(childBoundsCenter.z, zMin);
}
else if (tran.GetComponents<Component>().Length > 1 || tran.childCount == 0)
{
// 如果當(dāng)前物體的 Component 數(shù)量除了 Transform 以外還有其他 Component ,或者子物體是空的,也考慮在內(nèi)
xMax = Mathf.Max(tran.position.x, xMax);
yMax = Mathf.Max(tran.position.y, yMax);
zMax = Mathf.Max(tran.position.z, zMax);
xMin = Mathf.Min(tran.position.x, xMin);
yMin = Mathf.Min(tran.position.y, yMin);
zMin = Mathf.Min(tran.position.z, zMin);
}
}
// 組合大小值
Vector3 min = new Vector3(xMin, yMin, zMin);
Vector3 max = new Vector3(xMax, yMax, zMax);
// 計(jì)算中心點(diǎn)
Vector3 averageBoundsCenter = (min + max) / 2;
return averageBoundsCenter;
}
}
使用方法:
在任何一個(gè)路徑下帶有Editor文件夾的里面創(chuàng)建一個(gè)C#腳本,命名交TransformCenterOnChildren,把代碼完整復(fù)制進(jìn)去。
等Unity編譯完成在上方有一個(gè)Tools的菜單,選中要調(diào)整的父層級Gameobject,點(diǎn)擊坐標(biāo)歸到子物體中心點(diǎn)位置。

image.png