Сохранение созданного объекта

Общие вопросы о Unity3D

Сохранение созданного объекта

Сообщение Ded Extrimal 13 сен 2017, 11:32

Добрый день всем.
В определенный момент создается объект, как сохранить его на сцене, чтобы при следующем запуске он уже был на своем месте?
Просто сохранить какую-то переменную, типа int = 1, затем при запуске проверить, если равно 1, то инстантиейтим его?
Или есть еще какой-то способ?
Аватара пользователя
Ded Extrimal
UNец
 
Сообщения: 27
Зарегистрирован: 09 авг 2017, 21:20

Re: Сохранение созданного объекта

Сообщение Norman 13 сен 2017, 11:48

Можно не переменную, а ключик любого типа в PlayerPrefs. Если ключ существует - инстаншиэйтить.
Norman
UNIт
 
Сообщения: 111
Зарегистрирован: 31 мар 2017, 18:38

Re: Сохранение созданного объекта

Сообщение Tumbalalaika 13 сен 2017, 19:16

Вот нактдал небольшой пример.

Вспомогательные экстеншены

Синтаксис:
Используется csharp

using UnityEngine;

namespace SDS.Extensions
{
    public static class Extensions
    {
        public static T[] GetJaggedArrayItems<T>(this T[][] arr)
        {
            var items = new System.Collections.Generic.List<T>();

            for (int i = 0; i < arr.Length; i++)
            {
                for (int j = 0; j < arr[i].Length; j++)
                {
                    items.Add(arr[i][j]);
                }
            }

            return items.ToArray();
        }

        public static GameObject[][] GetAllSceneObjects(this UnityEngine.SceneManagement.Scene scene)
        {
            GameObject[] rootObjects = scene.GetRootGameObjects();
            GameObject[][] tree = new GameObject[rootObjects.Length][];

            for (int i = 0; i < rootObjects.Length; i++)
            {
                Transform[] children = rootObjects[i].GetComponentsInChildren<Transform>(true);
                GameObject[] branch = new GameObject[children.Length];
                for (int j = 0; j < children.Length; j++)
                    branch[j] = children[j].gameObject;
                tree[i] = branch;
            }

            return tree;
        }
    }
}
 


Эта хрень собирает инфу об объектах при старте сцены, и в нужный ммент находит объекты, создынные после запуска и сериализует их (толком не работает с иерархией чилдов).

Синтаксис:
Используется csharp

using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;

using SDS.Extensions;

namespace SDS
{
    [System.Serializable]
    class SceneDiffWrapper
    {
        public NewObjectsData[] Objects;
    }

    [System.Serializable]
    class NewObjectsData
    {
        public string Name;
        public string Parent; // Check

        public Vector3 Position;
        public Quaternion Rotation;

        private NewObjectsData() { }

        public static NewObjectsData Create(GameObject obj)
        {
            return new NewObjectsData()
            {
                Name = obj.name,
                Parent = obj.transform.parent ? obj.transform.parent.name : null,
                Position = obj.transform.position,
                Rotation = obj.transform.rotation
            };
        }
    }

    public class SceneDiffSerializer
    {
        private const string PPKEY = "last_scene_diff";

        private List<int> _dump;

        public static SceneDiffSerializer GetSerializer
        {
            get
            {
                return new SceneDiffSerializer()
                {

                    _dump = Dump(
                    SceneManager.GetActiveScene()
                    .GetAllSceneObjects()
                    .GetJaggedArrayItems()
                    )

                    .ToList()
                };
            }
        }

        public void Save()
        {
            GameObject[] objects = SceneManager.GetActiveScene().GetAllSceneObjects().GetJaggedArrayItems();

            var diff = new List<NewObjectsData>();

            for (int i = 0; i < objects.Length; i++)
            {
                if (!_dump.Contains(objects[i].GetInstanceID()))
                {
                    Debug.Log(objects[i]);
                    diff.Add(NewObjectsData.Create(objects[i]));
                }
            }

            var wrapper = new SceneDiffWrapper()
            {
                Objects = diff.ToArray()
            };

            PlayerPrefs.SetString(PPKEY, JsonUtility.ToJson(wrapper));
        }

        public void Recreate()
        {
            SceneDiffWrapper wrapper = JsonUtility.FromJson<SceneDiffWrapper>(PlayerPrefs.GetString(PPKEY));

            foreach (var obj in wrapper.Objects)
            {
                var newObj = GameObject.CreatePrimitive(PrimitiveType.Cube).transform;

                // try set parent
                if (obj.Parent != null)
                {
                    GameObject parent = GameObject.Find(obj.Parent);
                    if (parent) newObj.transform.SetParent(parent.transform);
                }

                newObj.name = obj.Name;
                newObj.position = obj.Position;
                newObj.rotation = obj.Rotation;
                Material mat = new Material(Shader.Find("Standard"));
                mat.color = new Color(0.5f, 0, 0, 1);
                newObj.GetComponent<MeshRenderer>().material = mat;
            }
        }

        public void Flush()
        {
            PlayerPrefs.DeleteKey(PPKEY);
        }

        private static int[] Dump(GameObject[] objects)
        {
            int[] ids = new int[objects.Length];
            for (int i = 0; i < objects.Length; i++)
                ids[i] = objects[i].GetInstanceID();
            return ids;
        }
    }
}
 


Отсюда упраляем

Синтаксис:
Используется csharp

using UnityEngine;

using SDS;

public class SDSTest : MonoBehaviour
{
    private SceneDiffSerializer _serializer;

    void Start()
    {
        _serializer = SceneDiffSerializer.GetSerializer;
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.S))
        {
            _serializer.Save();
        }

        if (Input.GetKeyDown(KeyCode.F))
        {
            _serializer.Flush();
        }

        if (Input.GetKeyDown(KeyCode.L))
        {
            _serializer.Recreate();
        }
    }
}
 


Код сырой кнч, так как пример, но можешь отсюда копать, впринципе инфа исчерпывающая по теме.
Tumbalalaika
UNец
 
Сообщения: 17
Зарегистрирован: 12 сен 2017, 19:01

Re: Сохранение созданного объекта

Сообщение Ded Extrimal 14 сен 2017, 09:21

Мне как раз работать с дочерними и родителями. А объектов всего 6. Так что я просто сохраняю активен он или нет. По сути я сохраняю имя объекта а потом создаю и все. Это надо всего один раз делать. Так что работает быстро.
Аватара пользователя
Ded Extrimal
UNец
 
Сообщения: 27
Зарегистрирован: 09 авг 2017, 21:20


Вернуться в Общие вопросы

Кто сейчас на конференции

Сейчас этот форум просматривают: GoGo.Ru [Bot] и гости: 11