为什么我的预制件在放入场景时会改变位置?

问题描述

我有一个问题,我制作了一个立方体的预制件,我想把它放在一个平台上。 我的预制件的 y 值为 1。但是,当我尝试将其放置在平台上时,立方体的 y 值为 0.5,从而将其置于地面内部。 我尝试重置预制件、地面和立方体中的变换,但都没有奏效。

带有预制件及其值如何更改的统一窗口的屏幕截图。

解决方法

我假设您将预制件拖入 Scene 窗口而不使用代码或类似的东西。

为什么要修改位置

你的立方体进入地面一半的原因可能是因为 Unity 试图让它以你在场景中的地面对象的 Y 轴为中心,因为这很可能是你拖动预制件的对象。

>

解决方案 1

如果您希望将东西拖入 Scene 窗口,但又希望避免立方体落入地面,一种解决方案是更改立方体的中心位置。一种方法是将立方体放入一个空的 GameObject 并修改立方体在其中的位置,并将此 GameObject 用作预制件。这是一张屏幕截图,说明了预制件的修改版本的外观:
enter image description here

解决方案 2

如果希望将立方体移动到场景中而不进行任何位置修改,请将其拖到 Hierarchy 窗口中。

解决方案 3

创建一个自定义脚本来修改您的立方体预制实例的 Y 位置。 OnValidate() 可能值得为此解决方案研究。

,

您需要相对于变换的位置“冻结”网格(重新计算网格的顶点),使其符合您的需求。

这通常在生成网格的程序中完成,但您也可以在 Unity 中使用一个简单的编辑器脚本。如果你用谷歌搜索,可能有几个非常好的代码 - 但这是我需要调整或冻结网格时我自己使用的代码。

enter image description here

在您的情况下,您只想在底部对齐网格,因此您可以为“对齐 y”选择“最小”(取消选中 x、y 和 z 旁边的复选框)。这会将所有网格置于变换位置上方。 (对齐是一种简单的冻结方式,无需先根据需要手动定位网格)。

将以下两个脚本放在名为“Editor”的文件夹中(这样它就可以用作 Unity 编辑器)。然后,您将在 Unity 中拥有一个新的菜单选项“工具 - 简单网格编辑器”。

SimpleMeshEditor.cs

using UnityEditor;
using UnityEngine;

namespace com.andulfgames
{
    public class SimpleMeshEditor : EditorWindow
    {
        [MenuItem("Tools/Simple Mesh Editor")]
        public static void ShowWindow()
        {
            GetWindow<SimpleMeshEditor>(false,"Simple Mesh Editor",true);
        }

        bool freezeRotation = true;

        SimpleMeshTools.MeshAlign alignX;
        SimpleMeshTools.MeshAlign alignY;
        SimpleMeshTools.MeshAlign alignZ;

        bool freezeX = false;
        bool freezeY = false;
        bool freezeZ = false;

        bool adjustColliders = true;

        void OnGUI()
        {
            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Freeze",EditorStyles.boldLabel);
            freezeRotation = EditorGUILayout.Toggle("Rotation",freezeRotation); 
            freezeX = EditorGUILayout.Toggle("x",freezeX );
            freezeY = EditorGUILayout.Toggle("y",freezeY);
            freezeZ = EditorGUILayout.Toggle("z",freezeZ);
            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Align",EditorStyles.boldLabel);
            alignX = (SimpleMeshTools.MeshAlign)EditorGUILayout.EnumPopup("Align x",alignX);
            alignY = (SimpleMeshTools.MeshAlign)EditorGUILayout.EnumPopup("Align y",alignY);
            alignZ = (SimpleMeshTools.MeshAlign)EditorGUILayout.EnumPopup("Align z",alignZ);

            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Colliders",EditorStyles.boldLabel);
            adjustColliders = EditorGUILayout.Toggle("Adjust colliders",adjustColliders);

            if (GUILayout.Button("UpdateMesh"))
            {
                UpdateMesh();
            }
        }


        private void UpdateMesh()
        {
            foreach (GameObject obj in Selection.gameObjects)
            {
                MeshFilter meshFilter = obj.GetComponent<MeshFilter>(); //6

                if (meshFilter != null)
                {
                    SimpleMeshTools.FreezeTransformation(obj,freezeRotation,freezeX,alignX,freezeY,alignY,freezeZ,alignZ,adjustColliders);
                }
            }
        }
    }
}

SimpleMeshEditor.cs

using UnityEditor;
using UnityEngine;
using System.Collections.Generic;

namespace com.andulfgames
{
    public static class SimpleMeshTools
    {
        public static void FreezeTransformation(GameObject gameObject,bool freezeRotation,bool freezeX,MeshAlign meshPositionX,bool freezeY,MeshAlign meshPositionY,bool freezeZ,MeshAlign meshPositionZ,bool adjustColliders)
        {
            MeshFilter meshFilter = gameObject.GetComponent<MeshFilter>();
            Mesh newMesh = GameObject.Instantiate<Mesh>(meshFilter.sharedMesh);
            Quaternion originalRotation = meshFilter.transform.rotation;
            // If we should not freeze the rotation we have to temporarly turn the mesh
            // back to it's identity rotation before we freeze the vertizes.
            if (!freezeRotation)
                meshFilter.transform.rotation = Quaternion.identity;


            Vector3[] vertices = newMesh.vertices;

            Vector3 freeze = new Vector3(
                freezeX ? 0 : gameObject.transform.position.x,freezeY ? 0 : gameObject.transform.position.y,freezeZ ? 0 : gameObject.transform.position.z);
            Debug.Log("Freeze: " + freeze.ToString());
            Vector3 diff = gameObject.transform.position - freeze;

            Vector3 alignMin = newMesh.bounds.min;
            Vector3 alignCenter = newMesh.bounds.center;
            Vector3 alignMax = newMesh.bounds.max;

            Vector3 align = new Vector3(
                meshPositionX == MeshAlign.KeepCurrent ? 0 :
                (meshPositionX == MeshAlign.Min ? alignMin.x :
                (meshPositionX == MeshAlign.Center ? alignCenter.x : alignMax.x)),meshPositionY == MeshAlign.KeepCurrent ? 0 :
                (meshPositionY == MeshAlign.Min ? alignMin.y :
                (meshPositionY == MeshAlign.Center ? alignCenter.y : alignMax.y)),meshPositionZ == MeshAlign.KeepCurrent ? 0 :
                (meshPositionZ == MeshAlign.Min ? alignMin.z :
                (meshPositionZ == MeshAlign.Center ? alignCenter.z : alignMax.z)));

            Debug.Log("Freeze by " + diff.ToString() + " and align by " + align.ToString() + ",in total " + (diff + align).ToString());

            Debug.Log("Adjust: " + align.ToString());

            for (int i = 0; i < vertices.Length; i++)
                vertices[i] = gameObject.transform.TransformPoint(newMesh.vertices[i]) - freeze - align;

            newMesh.vertices = vertices;

            // Note that we can't rotate box- or sphere colliders

            BoxCollider boxCollider = adjustColliders ? gameObject.GetComponent<BoxCollider>() : null;
            SphereCollider sphereCollider = adjustColliders ? gameObject.GetComponent<SphereCollider>() : null;
            CapsuleCollider capsuleCollider = adjustColliders ? gameObject.GetComponent<CapsuleCollider>() : null;

            if (adjustColliders && diff + align != Vector3.zero)
            {
                Debug.Log("Adjusting colliders by " + (diff + align).ToString());
                if (boxCollider != null)
                    boxCollider.center += diff + align;
                if (sphereCollider != null)
                    sphereCollider.center += diff + align;
                if (capsuleCollider != null)
                    capsuleCollider.center += diff + align;
            }

            if (freezeRotation && gameObject.transform.rotation != Quaternion.identity)
            {
                Debug.Log("Freezing current rotation which is " + gameObject.transform.rotation.ToString());
                if (boxCollider != null)
                    Debug.LogWarning("Can't rotate box-colliders. They are fixed with the transform.");
                if (sphereCollider != null)
                    Debug.LogWarning("Can't rotate sphere-colliders. They are fixed with the transform.");
                if (capsuleCollider != null)
                    Debug.LogWarning("Can't rotate capsule-colliders. They are fixed with the transform.");

                Vector3[] normals = newMesh.normals;
                if (normals != null)
                {
                    for (int i = 0; i < normals.Length; i++)
                        normals[i] = gameObject.transform.rotation * newMesh.normals[i];
                    newMesh.normals = normals;
                }
            }

            newMesh.RecalculateBounds();
            newMesh.RecalculateNormals();

            Mesh savedMesh = SaveMesh(newMesh,gameObject.name);
            if (savedMesh != null)
                meshFilter.sharedMesh = savedMesh;

            if (freezeRotation)
                meshFilter.transform.rotation = Quaternion.identity;
            else
                meshFilter.transform.rotation = originalRotation; // Restore

            meshFilter.transform.localScale = new Vector3(1,1,1);
            meshFilter.transform.position -= diff - align;
        }
    }
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...