为什么新的实例化预制件与原始所选游戏对象的位置不同?



这是将所选游戏对象转换信息保存到json文件的脚本。并且还通过一个选定的预制件实例化预制件将它们加载回去。它应该将新的实例化预制件放在原始所选游戏对象的位置、旋转和比例中,但事实并非如此。

我可以看到新的实例化预制件与检查器中的原始游戏对象具有相同的位置,但新的实例化预制件仍然位于场景中的其他位置,与原始预制件不接近。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine.SceneManagement;
public static class TransformSaver
{
[System.Serializable]
public class Transform
{
public string sceneName;
public string name;
public UnityEngine.Transform parent;
public Vector3 pos;
public Quaternion rot;
public Vector3 scale;
}
//Save Transform
public static void SaveTransform(UnityEngine.GameObject[] tranformToSave)
{
Transform[] trnfrm = new Transform[tranformToSave.Length];
for (int i = 0; i < trnfrm.Length; i++)
{
trnfrm[i] = new Transform();
trnfrm[i].sceneName = tranformToSave[i].gameObject.scene.name;
trnfrm[i].name = tranformToSave[i].name;
trnfrm[i].parent = tranformToSave[i].transform.parent;
trnfrm[i].pos = tranformToSave[i].transform.position;
trnfrm[i].rot = tranformToSave[i].transform.rotation;
trnfrm[i].scale = tranformToSave[i].transform.localScale;
}
string jsonTransform = JsonHelper.ToJson(trnfrm, true);
File.WriteAllText(@"e:jsonjson.txt", jsonTransform);
}
public static Transform[] LoadTransforms()
{
//string jsonTransform = PlayerPrefs.GetString("transform");
string jsonTransform = File.ReadAllText(@"e:jsonjson.txt");
if (jsonTransform == null)
{
return null;
}
Transform[] savedTransforms = JsonHelper.FromJson<Transform>(jsonTransform);
return savedTransforms;
}
//Load Transform
public static UnityEngine.Transform[] LoadTransform(bool usePrefab, GameObject prefab, bool useSceneName, string sceneName)
{
string jsonTransform = File.ReadAllText(@"e:jsonjson.txt");
if (jsonTransform == null)
{
return null;
}
Transform[] savedTransforms = JsonHelper.FromJson<Transform>(jsonTransform);
GameObject[] gameObjects = new GameObject[savedTransforms.Length];
UnityEngine.Transform[] loadedTransforms = new UnityEngine.Transform[savedTransforms.Length];
for (int i = 0; i < gameObjects.Length; i++)
{
try
{
if (useSceneName)
{
SceneManager.SetActiveScene(SceneManager.GetSceneByName(sceneName));
}
else
{
SceneManager.SetActiveScene(SceneManager.GetSceneByName(savedTransforms[i].sceneName));
}
}
catch
{
}
if (usePrefab == true && prefab != null)
{
UnityEngine.Object.Instantiate(prefab, savedTransforms[i].pos,
savedTransforms[i].rot, savedTransforms[i].parent);
}
else
{
gameObjects[i] = new GameObject();
loadedTransforms[i] = gameObjects[i].transform;
loadedTransforms[i].name = savedTransforms[i].name;
loadedTransforms[i].parent = savedTransforms[i].parent;
loadedTransforms[i].localPosition = savedTransforms[i].pos;
loadedTransforms[i].localRotation = savedTransforms[i].rot;
loadedTransforms[i].localScale = savedTransforms[i].scale;
}
}
return loadedTransforms;
}
}

和编辑器窗口脚本,用于选择预制件选择游戏对象以获取信息和保存加载按钮:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class SaveTransformsInfo : EditorWindow
{
public GameObject source;
[MenuItem("Tools/Save Transforms")]
private static void CreateReplaceWithPrefab()
{
const int width = 340;
const int height = 70;
var x = (Screen.currentResolution.width - width) / 2;
var y = (Screen.currentResolution.height - height) / 2;
GetWindow<SaveTransformsInfo>().position = new Rect(x, y, width, height);
}
private void OnGUI()
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Select Prefab", GUILayout.Width(80));
source = (GameObject)EditorGUILayout.ObjectField(source, typeof(GameObject), true, GUILayout.ExpandWidth(true));
EditorGUILayout.EndHorizontal();
GUILayout.Space(35);
if (GUILayout.Button("Save Transforms"))
{
TransformSaver.SaveTransform(Selection.gameObjects);
}
GUILayout.Space(2);
if (GUILayout.Button("Load Transforms"))
{
TransformSaver.LoadTransform(true, source, false, "");
}
}
}

我也尝试了游戏对象变换的位置和旋转,但无论它是否是本地的,都没有多大帮助。

仅供参考:检查器中显示的位置和旋转始终是本地位置和旋转,因此相对于父级


然后在脚本中使用positionrotation来存储值

trnfrm[i].pos = tranformToSave[i].transform.position;
trnfrm[i].rot = tranformToSave[i].transform.rotation;

但后来在"加载"时localPositionlocalRotation

loadedTransforms[i].localPosition = savedTransforms[i].pos;
loadedTransforms[i].localRotation = savedTransforms[i].rot;

或使用时

Instantiate(prefab, savedTransforms[i].pos, savedTransforms[i].rot, savedTransforms[i].parent);

它再次使用positionrotation

您应该使用positionrotation,或者在这两种情况下都使用localPositionlocalRotation- 但要保持一致。


其次,如果使用本地版本,您应该调试代码并真正确保

savedTransforms[i].parent;

也许不会返回null.否则,所有对象都将移动到根级别,并且可能只是以不同的方式定位。

我很确定你不能那样使用它,而且UnityEngine.Transform是不可序列化的。至少我知道,例如GameObject不是。但我不知道你的JsonHelper是如何运作的。


你也知道,在

UnityEngine.Object.Instantiate(prefab, savedTransforms[i].pos, savedTransforms[i].rot, savedTransforms[i].parent);

您不会向loadedTransforms写入任何内容,因此它将返回一个仅包含null条目的数组。

最新更新