How to serialize and save a GameObject in Unity

前端 未结 3 645
再見小時候
再見小時候 2020-11-27 20:49

I have a game where the player picks up a weapon and it is then placed as the GameObject variable to my player called \"MainHandWeapon\" and I am trying to save that weapon

相关标签:
3条回答
  • 2020-11-27 21:06

    Unity won't let you do it because a Gameobject comprises of all the scripts attached to it. For instance mesh renderers, colliders etc..

    If you wanted to say serialize the Tranform, you could get around this you by making a new Vector3 position, Vector3 scale, Vector4 quaternion and serialize that out instead and then on deserialization feed this data into a new Transform (for instance).

    But attempting to serialize the actual mesh data which is associated with the mesh renderer would prove quite the complex task. Better off probably just serializing an int or something which represents a mesh ID and then transmuting this to the correct reference on load.

    0 讨论(0)
  • 2020-11-27 21:19

    Aftr hours of experiment, I came to conclusion that Unity cannot serialize GameObject with BinaryFormatter. Unity claims that is possible in their API documentation but it's not.

    If you want to remove the error without removing the _weapon GameObject, you should replace ...

    [SerializeField]
    private GameObject _weapon;
    

    with

    [NonSerialized]
    private GameObject _weapon;
    

    This will let the rest of your code run without throwing exception, but you can't deserialize _weapon GameObject. You can deserialize other fields.

    OR

    You can serialize GameObject as xml. This can serialize GameObject without any problem. It saves the data in human readable format. If you care about security or don't want players modifying scores on their own devices, you can encrypt, convert it into binary or Base-64 format before saving it to the disk.

    using UnityEngine;
    using System.Collections;
    using System.Runtime.Serialization.Formatters.Binary;
    using System.IO;
    using System;
    using System.Runtime.Serialization;
    using System.Xml.Linq;
    using System.Text;
    
    public class Player_Manager : MonoBehaviour
    {
    
        // The weapon the player has.
        public GameObject MainHandWeapon;
    
        void Start()
        {
            Save();
        }
    
        public void Save()
        {
            float test = 50;
    
            Debug.Log(Application.persistentDataPath);
    
            // Stream the file with a File Stream. (Note that File.Create() 'Creates' or 'Overwrites' a file.)
            FileStream file = File.Create(Application.persistentDataPath + "/PlayerData.dat");
            // Create a new Player_Data.
            Player_Data data = new Player_Data();
            //Save the data.
            data.weapon = MainHandWeapon;
            data.baseDamage = test;
            data.baseHealth = test;
            data.currentHealth = test;
            data.baseMana = test;
            data.currentMana = test;
            data.baseMoveSpeed = test;
    
            //Serialize to xml
            DataContractSerializer bf = new DataContractSerializer(data.GetType());
            MemoryStream streamer = new MemoryStream();
    
            //Serialize the file
            bf.WriteObject(streamer, data);
            streamer.Seek(0, SeekOrigin.Begin);
    
            //Save to disk
            file.Write(streamer.GetBuffer(), 0, streamer.GetBuffer().Length);
    
            // Close the file to prevent any corruptions
            file.Close();
    
            string result = XElement.Parse(Encoding.ASCII.GetString(streamer.GetBuffer()).Replace("\0", "")).ToString();
            Debug.Log("Serialized Result: " + result);
    
        }
    }
    
    
    [DataContract]
    class Player_Data
    {
        [DataMember]
        private GameObject _weapon;
    
        public GameObject weapon
        {
            get { return _weapon; }
            set { _weapon = value; }
        }
    
        [DataMember]
        public float baseDamage;
        [DataMember]
        public float baseHealth;
        [DataMember]
        public float currentHealth;
        [DataMember]
        public float baseMana;
        [DataMember]
        public float currentMana;
        [DataMember]
        public float baseMoveSpeed;
    }
    
    0 讨论(0)
  • 2020-11-27 21:28

    Ideally you should have an object which hold the weapon data (attack, durability, etc ...) and serialize this object, it makes your save games much smaller, and is more OOP, as you can inherit from that class.

    0 讨论(0)
提交回复
热议问题