[英]Why does the position of my prefab is changed when dropped in the scene?
I have a problem, I made a prefab of a cube that I want to place on a platform.我有一个问题,我制作了一个要放置在平台上的立方体的预制件。 The y value of my prefab is 1. However, when I try to place it on the platform the cube takes the y value of 0.5 which puts it inside of the ground.
我的预制件的 y 值为 1。但是,当我尝试将其放置在平台上时,立方体的 y 值为 0.5,将其放置在地面内。 I tried to reset the transform in the prefab, the ground and the cubes but none of that worked.
我试图重置预制件、地面和立方体中的变换,但这些都不起作用。
Screenshots of my unity window with both the prefab and how its value is changed.我的统一 window 的屏幕截图,其中包含预制件及其值的更改方式。
I'm assuming you're dragging the prefab into the Scene
window without using code or anything like that.我假设您将预制件拖入
Scene
window 而不使用代码或类似的东西。
The reason your cube is halfway into the ground likely is due to Unity trying to have it centered on the Y axis on the ground object you have in the scene since that's likely the object you're dragging your prefabs on.您的立方体位于地面一半的原因可能是由于 Unity 试图将其置于您在场景中的地面 object 的 Y 轴上,因为这很可能是您正在拖动预制件的 object。
If you wish to drag things into the Scene
window but wish to avoid the cubes going into the ground, one solution is to change the center position of the cubes.如果您希望将物体拖入
Scene
window 但希望避免立方体进入地面,一种解决方案是更改立方体的中心 position。 One way of doing that is by putting the cube into an empty GameObject
and modify the cube's position inside it and use this GameObject
as a prefab.这样做的一种方法是将立方体放入一个空的游戏对象中,并在其中修改立方体的
GameObject
并将此GameObject
对象用作预制件。 Here's a screenshot illustrating how your modified version of the prefab would look like:这是一个屏幕截图,说明了您修改后的预制件的外观:
If wish to move a cube into the scene without any position modifications, drag it into the Hierarchy
window instead.如果希望将立方体移动到场景中而不进行任何 position 修改,请将其拖动到
Hierarchy
window 中。
Create a custom script that modifies the Y position of your cube prefab instance.创建修改多维数据集预制实例的 Y position 的自定义脚本。
OnValidate()
may be something worth looking into for this solution. OnValidate()
可能是值得研究的解决方案。
You need to "freeze" the mesh (recalculate the vertices of the mesh) relative to the position of the transform so it fits your needs.您需要相对于变换的 position 来“冻结”网格(重新计算网格的顶点),以便满足您的需求。
This is usually done in the program that generated the mesh but you could also use a simple editor script inside Unity.这通常在生成网格的程序中完成,但您也可以在 Unity 中使用简单的编辑器脚本。 There are probably several very good ones if you google - but here is the code I use myself when I need to adjust or freeze a mesh.
如果你用谷歌搜索,可能有几个非常好的——但是当我需要调整或冻结网格时,这是我自己使用的代码。
In your case, you simply want to align the mesh at the bottom, so you can select "Min" for "Align y" (let the checkboxes beside x, y, and z be unchecked).在您的情况下,您只需要在底部对齐网格,因此您可以 select “Min” for “Align y”(取消选中 x、y 和 z 旁边的复选框)。 This will put all the mesh above the transform position.
这会将所有网格置于变换 position 之上。 (Align is a simple way of freezing without the need to first manually position the mesh as desired).
(对齐是一种简单的冻结方法,无需先根据需要手动 position 网格)。
Place the following two scripts in a folder with the name "Editor" (so it can be used as a Unity editor).将以下两个脚本放在一个名为“Editor”的文件夹中(这样它就可以用作 Unity 编辑器)。 You will then have a new menu option in Unity "Tools - Simple Mesh Editor".
然后,您将在 Unity“工具 - 简单网格编辑器”中拥有一个新的菜单选项。
SimpleMeshEditor.cs简单网格编辑器.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简单网格编辑器.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;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.