在Unity3D中更改FBX模型的中心点(Unity3D/3DMax)

发表于2018-09-28
评论0 2.22w浏览
当我们将模型导入到Unity3D中时,经常会遇到模型的中心点与物体中心点出现偏离的情况,如下图所示:

这种情况通常会对我们的物体位置控制产生一些不利影响(当然这种设置也有其存在的好处……)

要解决模型的中心点与物体中心点偏离的问题,我们通常可以在Unity3D中进行设置。

1、设置一个空物体作为我们进行修改的模型的父物体,设置其坐标为(0,0,0),随后将我们需要修改的子物体拖动到与父物体坐标系原点相重合的位置这样便可实现我们预期的目标。

2、通过代码设置中心点
/// <summary>
/// 重置模型的中心点位置
/// </summary>
[MenuItem("Tool/ResetCenterPosition")]
public static void ResetCenterPosition()
{
    Transform transform = Selection.activeTransform;
    Bounds bounds = new Bounds(Vector3.zero, Vector3.zero);
    Vector3 center = Vector3.zero;
    //获取物体的Bound最终合成信息
    foreach (var item in transform.GetComponentsInChildren<MeshRenderer>())
    {
        bounds.Encapsulate(item.bounds);
    }
    center = bounds.center;
    //新建空物体,将原来中心点有问题的物体放置到该物体下作为子物体存在
    GameObject obj = new GameObject();
    obj.name = transform.name;
    obj.transform.position = center;
    obj.transform.rotation = Quaternion.identity;
    //获取原物体在模型中的路径
    string selectedObjPath = "";
    Transform currentSelectTransform = transform;
    while (currentSelectTransform.parent != null)
    {
        selectedObjPath = currentSelectTransform.parent.name + "/" + selectedObjPath;
        currentSelectTransform = currentSelectTransform.parent;
    }
    //设置空物体的层级,使之与原物体处于同一层级
    obj.transform.SetParent(GameObject.Find(selectedObjPath).transform);
    transform.SetParent(obj.transform);
}

该方法同样通过计算当前物体及子物体的Bounds的大小和位置,新建一个空物体,将空物体的位置放置在模型Bounds的中心点中,将原来的物体设置为空物体的子物体来实现坐标点的重置。该方法为单个物体进行重置,也可以通过修改代码,自动将整个模型中的所有物体进行重置,但是需要注意的是该种方法并没有改变原始物体MeshFilter的中心点位置,如果用户要对其MeshFilter进行操作,可能会有其他的情况发生。

如果需要对物体进行碰撞或者射线检测,然后在进行位置的操作,请先确定操作的物体是空物体还是有网格信息的物体。否则不会出现预期的效果。

3、通过将FBX文件重新导入到3DMax中进行设置来完成对Pivot的重置,该方法可以从本质上实现对模型中心点的设置。

将模型导入到3DMax中后,全选所有物体,选择右侧工具栏的层次->轴->仅影响轴->居中到对象。然后再将模型导出即可。

4、另一种方式可以通过重新计算MeshFilter的方式进行,该种方法暂时无法得到模型准确的中心点,需要借助Bounds来计算,但是无法通过MeshFilter中所有的点的平均位置来计算,因此暂时无法对不规则物体进行中心点重置,这种方法仅供参考,可以在此基础上深入研究。
[MenuItem("Tool/ResetCenterPositionWithMeshFilter")]
public static void ResetCenterPositionWithMeshFilter()
{
    Transform transform = Selection.activeTransform;
    //获取物体的Bound最终合成信息
    foreach (var item in transform.GetComponentsInChildren<MeshFilter>())
    {
        Vector3[] testVector = item.mesh.vertices;
        for (int i = 0; i < testVector.Length; i++)
        {
            testVector[i] += new Vector3(1, 1, 1);
        }
        item.mesh.vertices = testVector;
        item.mesh.RecalculateBounds();
        item.mesh.RecalculateNormals();
        item.mesh.RecalculateTangents();
    }
}
来自:https://blog.csdn.net/beihuanlihe130/article/details/76255965

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

标签: