Почему новые Созданные префабы не находятся в тех же позициях, что и исходные выбранные игровые объекты? - PullRequest
2 голосов
/ 10 октября 2019

Это скрипт, который сохраняет выбранные игровые объекты и преобразует информацию в файл 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:\json\json.txt", jsonTransform);
    }

    public static Transform[] LoadTransforms()
    {
        //string jsonTransform = PlayerPrefs.GetString("transform");
        string jsonTransform = File.ReadAllText(@"e:\json\json.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:\json\json.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, "");
        }

    }
}

Я пробовал также локально в положении и поворотах преобразований игровых объектов, но это не сильно помогло, локально это или нет.

1 Ответ

1 голос
/ 10 октября 2019

В общем, к вашему сведению: Положение и поворот, отображаемые в Инспекторе, всегда равны локальному относительно родителя


Тогда в вашем скрипте вы использовали positionи rotation для хранения значений

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

, но позже localPosition и localRotation при «загрузке»

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

или при использовании

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

он снова использует position и rotation.

Вы должны использовать position и rotation или localPosition и localRotation в обоих случаях - но последовательно.


Во-вторых, если вы используете локальные версии, вы должны отладить ваш код и убедиться, что

savedTransforms[i].parent;

не может вернуть null. В противном случае все ваши объекты будут перемещены на корневой уровень и могут быть просто расположены по-другому.

Я почти уверен, что вы не можете использовать его таким образом, и что UnityEngine.Transform не сериализуем. По крайней мере, я знаю, что, например, GameObject нет. Но я не знаю, как работает ваш JsonHelper.


Вы также знаете, что в случае

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

вы ничего не пишете в loadedTransformsпоэтому он вернет массив только с null записями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...