1. ホーム
  2. c#

[解決済み] UnityでGameObjectをシリアライズして保存する方法

2022-02-26 03:17:06

質問

私はプレイヤーが武器を拾うゲームを持っており、それは私のプレイヤーに"MainHandWeapon"というGameObject変数として配置され、私はシーン変更を通じてその武器を保存しようとしているので、私はそれを保存しようとしています。 私はこれをどのように処理するかは次のとおりです。

public class Player_Manager : Character, Can_Take_Damage {

    // The weapon the player has.
    public GameObject MainHandWeapon;

    public void Save()
    {
        // Create the Binary Formatter.
        BinaryFormatter bf = new BinaryFormatter();
        // 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 = BaseDamage;
        data.baseHealth = BaseHealth;
        data.currentHealth = CurrentHealth;
        data.baseMana = BaseMana;
        data.currentMana = CurrentMana;
        data.baseMoveSpeed = BaseMoveSpeed;
        // Serialize the file so the contents cannot be manipulated.
        bf.Serialize(file, data);
        // Close the file to prevent any corruptions
        file.Close();
    }
}

[Serializable]
class Player_Data
{
    [SerializeField]
    private GameObject _weapon;
    public GameObject weapon{
        get { return _weapon; }
        set { _weapon = value; }
    }

    public float baseDamage;
    public float baseHealth;
    public float currentHealth;
    public float baseMana;
    public float currentMana;
    public float baseMoveSpeed;
}

しかし、私はこのセットアップを持っていることから、このエラーが発生し続けます。

SerializationException: Type UnityEngine.GameObject is not marked as Serializable.

具体的に何が間違っているのでしょうか?

どうすればいいですか?

何時間にもわたる実験の結果、Unityは以下のような結論に達しました。 できない シリアライズ GameObjectBinaryFormatter . UnityはAPIドキュメントでそれが可能だと主張していますが、それは ではなく .

を削除したい場合は エラー Weapon GameObjectを削除せずに、...を置き換える必要があります。

[SerializeField]
private GameObject _weapon;

[NonSerialized]
private GameObject _weapon;

これにより、残りのコードは例外をスローすることなく実行されますが、あなたは はできません。 デシリアライズ _weapon GameObjectです。あなたは デシリアライズ 他のフィールド

または

GameObjectをシリアライズするには、次のようにします。 xml . これで問題なくGameObjectをシリアライズすることができる。これは人間が読めるフォーマットでデータを保存する。もし、セキュリティを気にしたり、プレイヤーに 修正 のスコアを自分のデバイスで表示させることができます。 エンクリプト に変換してください。 バイナリ または ベース64 の前にフォーマット セービング をディスクに保存します。

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