2
votes

This is the script that save the selected gameobjects transforms information to json file. And also loading them back by Instantiated prefabs from a one selected prefab. And it should put the new Instantiated prefabs in the position,rotation,scale of the original selected gameobjects but it's not.

I can see that the new Instantiated prefabs have the same position as the original gameobjects in the inspector but still the new Instantiated prefabs are in other position/s in the scene not close to the original ones.

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;
    }
}

And editorwindow script for selecting a prefab selection gameobjects to get information and save load buttons :

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, "");
        }

    }
}

I tried also local in the position and rotation of the gameobjects transforms but it didn't help much if it's local or not.

1

1 Answers

1
votes

Just fyi in general: The position and rotation displayed in the Inspector is always the local one so relative to the parent


Then in your script you used position and rotation for storing the values

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

but later localPosition and localRotation when "loading"

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

or when using

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

it uses position and rotation again.

You should either use position and rotation or localPosition and localRotation in both cases - but consistently.


Second if using the local versions you should debug your code and make really sure that

savedTransforms[i].parent;

doesn't maybe return null. Otherwise all your objects are moved to the root level and might simply be positioned differently.

I'm pretty sure you can't use it like that and that UnityEngine.Transform isn't serializable. At least I know that e.g. GameObject is not. But I don't know how your JsonHelper works.


You know also that in the case of

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

you don't write anything to the loadedTransforms so it will return an array with only null entries.