Jump to content
Unity Insider Forum

Größere Datenmengen speichern


Kojote

Recommended Posts

Grüße, da bin ich wieder! :D

Ich grübel nu schon seit zwei Tagen, wie ich mein Speichern- und Ladescript schreibe. Im Letzten Spiel, habe ich mir eine Ladestructur geschrieben, waren nur 12 Variablen und die dann über BinaryFormatter in eine Dat-Datei geschrieben. 6 mal Positionsdaten und noch bissl Krempelei. Bei diesem Spiel wird das Speichern und Laden etwas anspruchsvoller.

Im Spiel befindet sich ein Spieler und mehrere dutzend Gegner. Für jeden Gegner und auch für den Spieler an sich, muss ich die Position, die Rotation, Lebenspunkte, ect. speichern und dann irgendwann mal wieder laden.

Schnell kommt man auf die Idee einfach hier eine Speicherklasse zu schreiben, jeder Gegner bekommt dann ein GameObjkekt dieser Klasse, in das er seine Zustände schreibt.

Frage ist nun, wenn ich auf Speichern klicke, wie komme ich an alle Daten, wie sammel ich dir mir?

Und im umgekehrten Fall, wie entwirre ich den Haufen Variablen wieder beim Laden?

Grüße von Kojote

Link zu diesem Kommentar
Auf anderen Seiten teilen

Die Idee, dass jedes Objekt seine Daten hält, finde ich gut. Hierzu benötigt natürlich jedes Objekt seine eigene Guid oder ID oder was auch immer für die Zuweisung. Beim Speichern gäbe es verschiedene Wege. Du könntest alle Objekte mit https://docs.unity3d.com/ScriptReference/Object.FindObjectsOfType.html suchen (diese müssen zu der Zeit aktiv sein). Du könntest aber auch die Objekte bei dem Speicher-Manager registrieren und beim Request die Daten liefern (gibt aber eine bestimmte Abhängigkeit).

//deine datenstruktur
[Serializable]
public class PlayerData
{
  public int id;
  public posX, posY, posZ;
}

//deine mono behaviour
public PlayerData playerData = new PlayerData();

//speicher manager
var arr = FindObjectsOfType<DeineMonoBehaviourType>();
var savegameList = new List<PlayerData>();
  
foreach(var x in arr)
{
  savegameList.Add(x.playerData);
}
  
//save

Sowas in der Art.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Daran hab ich auch schon gedacht, aber würde das nicht zu viele Resourcen futtern, wenn ich im gesamten Spiel die Suche nach bestimmten Objekten starte?

Da kommt mir gerade eine Idee, der Speichermanager wäre denke ich das beste. Man müsste halte im Speichermanager eine List<> haben, Array würde dafür nicht gehen. Sobald ein Objekt bzw. Gegner erstellt wird, meldet er sich beim Speichermanager an, es folgt ein "Add" in die Liste. Wird der Gegener zerstört, "Delete" und meldet sich damit wieder ab.

Beim Speichern müsste man dann nur noch die List<> aberbeiten und die aktuellen Daten holen und diese dann speichern.

Beim Laden wäre es dann genau andersherum. Über den Speichermanager müsste alle Spieleobjekte neu instanzieren.

Wäre denke ich die beste Möglichkeit und dürfte auch wenig Resourcen futtern.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Du musst das Rad aber auch nicht neu erfinden. Gibt eingebaute Xml- oder sonst auch Json-Bilbiotheken, da musst du nur deine Datenklassen mit Attributen bestücken ("das hier soll bitte mitgespeichert werden") und dann knallst du dein Objekt in einen Serializer und der spuckt dir korrektes Xml oder Json oder wasauchimmer aus.

Das hier kann man z.B. benutzen, auch wenn ich gehört habe, dass es inzwischen einige neuere Pakete gibt. So oder so kannst du dir ja mal oben rechts auf der Seite ansehen, wie einfach das dann aussieht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Microsoft hat für .NET core 3 einen neuen JSON serializer Entwickelt https://docs.microsoft.com/en-us/dotnet/api/system.text.json?view=netcore-3.0 und soll in ASP.NET core 3 newtonsoft JSON ersetzen, ist schneller und weniger GC behaftet.

Wird mal Zeit dass .NET core in Unity einzughält, wäre auch um einiges schneller als Mono.

.NET 5 soll am ende eh Mono, .NET CORE vereinen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich wollt mir heute mal JSON ansehen und in ein Testprogramm einfügen. Version wäre Newtonsoft.Json-12.0.2 und bekomme den Error hier:

TCoBFL95.jpg

Habe nun Versucht noch Version 8-11 zu installieren, alles Fehlanzeigen und habe nun das hier gefunden:

https://assetstore.unity.com/packages/tools/input-management/json-net-for-unity-11347

Wäre nun das hier das richtige, oder?

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hab mich nun mal eine Weile mit JSON beschäftigt, sieht schonmal ganz gut aus:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using System.IO;


[System.Serializable]
public class Chracter{
    public int armor;
    public int power;
}

public class JSONTest : MonoBehaviour {

    private string fileName = "GameData.json";
    private string filePath;

    private static JSONTest instance;

    public Chracter chara;

    public JSONTest Instance {
        get {
            return instance;
        }
    }

    private void Awake() {
        filePath = Application.dataPath + "/Save/" + fileName;
    }

    void Start () {
        Chracter chara = new Chracter();
        chara.armor = 10;
        chara.power = 100;
        SaveGameData();
        LoadGameData();
    }

    public void SaveGameData() {
        string json = JsonUtility.ToJson(chara);
        if (!File.Exists(filePath)) {
            File.Create(filePath).Dispose();
        }
        File.WriteAllText(filePath, json);
    }

    public void LoadGameData() {
        string json;
        if (File.Exists(filePath)) {
            json = File.ReadAllText(filePath);
            chara = JsonUtility.FromJson<Chracter>(json);
        } else {
            Debug.Log("File is missing: " + filePath);
        }
        Debug.Log(chara.armor.ToString() + " " + chara.power.ToString());
    }
}

Frage wäre, wie speichere ich nun alles zusammen ab. Am besten eine Liste, wie ich es mir überlegt habe, wo dann alle Enemys enthalten sind?

Sagen wir, ich leg mir ne List an, mit GameObjects. Jetzt speichere ich ja nur ein GameObject, wie ist dass dann bei vielen?

Umgekehrt, wenn ich wieder lade. Wie erstelle ich dann die gesamten Objekte wieder? Mit Instanziate, sprich Prefab erstellen?

Ich habs mal so probiert:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using System.IO;

namespace JSONTest_2 {
    [System.Serializable]
    public class Charcter {
        public int armor = 0;
        public int power = 0;
    }

    [System.Serializable]
    public class Enemy {
        public int armor = 0;
        public int power = 0;
    }

    [System.Serializable]
    public class ObjectList {
        public List<Charcter> characterList = new List<Charcter>();
        public List<Enemy> enemyList = new List<Enemy>();
    }

    public class JSONTest_2 : MonoBehaviour {
        private string fileName = "GameData.json";
        private string filePath;

        public ObjectList objectList = new ObjectList();


        private void Awake() {
            filePath = Application.dataPath + "/Save/" + fileName;
        }

        void Start() {
            Charcter chara_1 = new Charcter();
            Charcter chara_2 = new Charcter();
            Charcter chara_3 = new Charcter();

            Charcter enemy_1 = new Charcter();
            Charcter enemy_2 = new Charcter();
            Charcter enemy_3 = new Charcter();

            objectList.characterList.Add(chara_1);
            objectList.characterList.Add(chara_2);
            objectList.characterList.Add(chara_3);

            objectList.characterList.Add(enemy_1);
            objectList.characterList.Add(enemy_2);
            objectList.characterList.Add(enemy_3);

            SaveGameData();
            LoadGameData();
        }

        public void SaveGameData() {
            string json = JsonUtility.ToJson(objectList);
            if (!File.Exists(filePath)) {
                File.Create(filePath).Dispose();
            }
            File.WriteAllText(filePath, json);
        }

        public void LoadGameData() {
            string json;
            if (File.Exists(filePath)) {
                json = File.ReadAllText(filePath);
                objectList = JsonUtility.FromJson<ObjectList>(json);
            } else {
                Debug.Log("File is missing: " + filePath);
            }
        }
    }
}

Wenn ich nach dem Laden wieder die vollständige List habe, könnte ich ja eine For-Schleife laufen lassen und abarbeiten. Dabei die Enemys nach und nach erstellen. Was haltet ihr davon?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich mach mal nen neuen Beitrag auf, sonst wirds unübersichtlich.

Also bisher siehts folgendermaßen aus.

Ich habe mir eine Enemy-Klasse:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


namespace Lions_Dream_SP {
    public enum enemyAnimalTyp : short {
        Deer = 1,
        Pig = 2
    }

    [System.Serializable]
    public class LD_SP_Data_Enemy {
        public int enemyID;
        public string enemyName;
        public int enemyVitaility;
        public int enemyMana;
        public Vector3 enemyPos;
        public Quaternion enymyRotation;
        public enemyAnimalTyp enemyAnimalTyp;


        public void EnemyUpdate() {
            LD_SP_Data_Object_Manager.Instance.EnemyUpdate(this);
        }
    }
}

Und eine Players-Klasse geschrieben:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;


namespace Lions_Dream_SP {
    public enum playerAnimalTyp : short {
        Lion = 1,
        Tiger = 2
    }

    [System.Serializable]
    public class Inventory {
        public string itemName;
        public int itemAmount;
        public Sprite itemSprite;
    }

    [System.Serializable]
    public class LD_SP_Data_Player {
        public playerAnimalTyp playerAnimalTyp;
        public int playerID;
        public string playerName;
        public string playTime;
        public int playerVitaility;
        public int playerMana;
        public int playerCoat;
        public int playerPattern;
        public int playerParts;
        public int playerAddition;
        public Vector3 playerPos;
        public Quaternion playerRotation;
        public List<Inventory> playerInventory;


        public void CharacterUpdate() {
            LD_SP_Data_Object_Manager.Instance.CharacterUpdate(this);
        }
    }
}

Speichern würde nun so aussehen:

        public void SaveSavegame() {
            string time = System.DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss");
            file = path + "/Savegame_" + selectedSavegame + ".json";

            // Display aktualisieren
            savegameStructur[selectedSavegame].savegamePlayerName = LD_SP_Data_Object_Manager.Instance.characterList[selectedSavegame].playerName;
            savegameStructur[selectedSavegame].savegamePlayTime = time;
            savegameStructur[selectedSavegame].savegameExists = true;
            savegameStructur[selectedSavegame].savegameSceneNr = SceneManager.GetActiveScene().buildIndex;

            // Savegamestructure aktualisieren
            WriteSavagameStructure();

            // Aktualisierung aller Daten der Chraktere und Enemys
            LD_SP_Data_Object_Manager.Instance.CharacterListUpdate();
            LD_SP_Data_Object_Manager.Instance.EnemyListUpdate();

            //Savegame schreiben
            string json = JsonUtility.ToJson(LD_SP_Data_Object_Manager.Instance);
            if (!File.Exists(file)) {
                File.Create(file).Dispose();
            }
            File.WriteAllText(file, json);
        }

Zur Erklärung, hab mir dazu folgendes gedacht.

Sobald ein Enemy erzeugt wird, meldet er sich mit der Methode "EnemyAdd" bei der Klasse "LD_SP_Data_Object_Manager" an. Falls mal zerstört, gibs hier dafür auch ne "EnemyDelete".

Wird nun gespeichert, werden die der Methoden der Klasse "LD_SP_Data_Object_Manager" "CharacterListUpdate" und "EnemyListUpdate" für alle Enemys und Charactere aktiv. Sie melden sie nun wiederrum bei "LD_SP_Data_Object_Manager" und führen da die Methode "CharacterUpdate" und "EnemyUpdate" aus, so hab ich von allen wieder die aktuellen Daten.

Danach wird alles in JSON gespeichert.

So weit sogut!

Frage 1: Wäre die Möglichkeit besser, als ständig alle Enemys über die Update-Methode dauerhaft zu aktualisieren? Alternativ, könnte es zu Laggs kommen, wenn sagen wir 50 Enemys ankommen und ihre Daten aktualisieren?

Frage 2: Laden ...

Bisher sieht Laden bei mir so aus:

        public void LoadSavegame() {
            Debug.Log("TODO: Das Laden der Daten muss noch implementiert werden.");
            LD_SP_Menue_Loadscreen.Instance.LoadScene(loadSceneNr);
        }

        private IEnumerator LoadSceneCoroutine(int scene) {
            yield return new WaitForSeconds(1.5f);
            async = SceneManager.LoadSceneAsync(scene, LoadSceneMode.Single);
            async.allowSceneActivation = false;
            do {
                float progress = Mathf.Clamp01(async.progress / 0.9f);
                sliderDisplay.value = progress;
                yield return null;
            } while (!async.isDone);
        }

An welcher Stelle werden nun meine Daten für die Enemys und Charaktere aktualisiert bzw. erzeugt? Ich muss ja irgendwo auf die Karte paar Prefabs mit den Werten der Liste werfen.

EDIT:

Ahja, heraus bekomm ich diesen wunderschönen Blödsinn:

{
  "characterList": [
    {
      "instanceID": -120502
    }
  ],
  "childList": [],
  "enemyList": [
    {
      "instanceID": -68196
    },
    {
      "instanceID": -66434
    },
    {
      "instanceID": -66156
    },
    {
      "instanceID": -65878
    },
    {
      "instanceID": -65154
    }
  ]
}

Müsste er nicht eigentlich alles weitere aufschreiben, wie Mana, Leben und Co und nicht -65154?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Alles in allem hab ich also heraus gefunden, dass er zwar speichert, aber Müll speichert.

"instanceID" und irgend ne Zahl is falsch. Dachte erst ist ne gepackte Info, aber nein, hier erkennt er so wie ich es verstanden habe die Typen nicht. 😕

EDIT:

Hehe, Unity du bist ne Zicke! :D Jetzt hats mich doch gewundert, warum das JSON Serilisieren und Deserilisieren denn beim JSON Test funktioniert hat und hier nicht. Ja, einziger blöder Unterschie war, die Speicherklassen "LD_SP_Data_Player", "LD_SP_Data_Child" und "LD_SP_Data_Enemy" haben von MonoBehavior geerbt. Es darf keine Vererbung zu dieser Basis-Klasse stattfinden, schon gehts.

So sieht das schon ne ganze Ecke besser aus:

{
	"characterList": [{
		"playerAnimalTyp": 0,
		"playerID": 0,
		"playerName": "",
		"playTime": "",
		"playerVitaility": 0,
		"playerMana": 0,
		"playerCoat": 0,
		"playerPattern": 0,
		"playerParts": 0,
		"playerAddition": 0,
		"playerPos": {
			"x": 0.0,
			"y": 0.0,
			"z": 0.0
		},
		"playerRotation": {
			"x": 0.0,
			"y": 0.0,
			"z": 0.0,
			"w": 0.0
		},
		"playerInventory": [],
		"sceneID": 0
	}],
	"childList": [],
	"enemyList": [{
		"enemyID": 0,
		"enemyName": "",
		"enemyVitaility": 0,
		"enemyMana": 0,
		"enemyPos": {
			"x": 0.0,
			"y": 0.0,
			"z": 0.0
		},
		"enymyRotation": {
			"x": 0.0,
			"y": 0.0,
			"z": 0.0,
			"w": 0.0
		},
		"enemyAnimalTyp": 0
	}, {
		"enemyID": 0,
		"enemyName": "",
		"enemyVitaility": 0,
		"enemyMana": 0,
		"enemyPos": {
			"x": 0.0,
			"y": 0.0,
			"z": 0.0
		},
		"enymyRotation": {
			"x": 0.0,
			"y": 0.0,
			"z": 0.0,
			"w": 0.0
		},
		"enemyAnimalTyp": 0
	}, {
		"enemyID": 0,
		"enemyName": "",
		"enemyVitaility": 0,
		"enemyMana": 0,
		"enemyPos": {
			"x": 0.0,
			"y": 0.0,
			"z": 0.0
		},
		"enymyRotation": {
			"x": 0.0,
			"y": 0.0,
			"z": 0.0,
			"w": 0.0
		},
		"enemyAnimalTyp": 0
	}, {
		"enemyID": 0,
		"enemyName": "",
		"enemyVitaility": 0,
		"enemyMana": 0,
		"enemyPos": {
			"x": 0.0,
			"y": 0.0,
			"z": 0.0
		},
		"enymyRotation": {
			"x": 0.0,
			"y": 0.0,
			"z": 0.0,
			"w": 0.0
		},
		"enemyAnimalTyp": 0
	}, {
		"enemyID": 0,
		"enemyName": "",
		"enemyVitaility": 0,
		"enemyMana": 0,
		"enemyPos": {
			"x": 0.0,
			"y": 0.0,
			"z": 0.0
		},
		"enymyRotation": {
			"x": 0.0,
			"y": 0.0,
			"z": 0.0,
			"w": 0.0
		},
		"enemyAnimalTyp": 0
	}]
}

Jetzt stellt sich nur noch die Frage wie ich das beim Laden machen, wie erstelle ich die gespeicherten GameObjects und wann.

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 1 month later...

So, nach dem es jetzt eine ganze weile funktionierte, funktionierts jetzt wieder net und bekomm nen Error:

Zitat

ArgumentException: Cannot deserialize JSON to new instances of type 'LD_SP_Save_Data_Object_Manager.'
UnityEngine.JsonUtility.FromJson (System.String json, System.Type type) (at C:/buildslave/unity/build/Modules/JSONSerialize/Public/JsonUtility.bindings.cs:48)
UnityEngine.JsonUtility.FromJson[LD_SP_Save_Data_Object_Manager] (System.String json) (at C:/buildslave/unity/build/Modules/JSONSerialize/Public/JsonUtility.bindings.cs:33)
Lions_Dream_SP.LD_SP_Menue_Load.SaveGameReadBasicData () (at Assets/Scripts/Menue/LD_SP_Menue_Load.cs:86)
Lions_Dream_SP.LD_SP_Menue_Load.Start () (at Assets/Scripts/Menue/LD_SP_Menue_Load.cs:62)

Genau betrifft das Diese Zeile:

D_SP_Save_Data_Object_Manager.BasicDataInstance = JsonUtility.FromJson<LD_SP_Save_Data_Object_Manager>(json);

Die Zeile kommt aus der Methode `SaveGameReadBasicData`, habe ich weiter unten eingefügt. Habt ihr ne Idee was er hat?

 

EDIT:

Schon hier hat er seine Probleme:

Debug.Log(JsonUtility.FromJson<LD_SP_Save_Data_Object_Manager>(json).characterList.Count);

Hier mal die JSON, sieht alles normal aus:

{"characterList":[{"playerName":"8678","playTime":"24.10.2019 10:47:01","playerVitaility":99.3298568725586,"playerGender":1,"playerBodyShape":[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],"playerBodyColor":[0.0,0.0,1.0],"playerEyeColor":[0.0,0.0,0.0],"playerNoseColor":[0.0,0.0,0.0],"playerBodyMaterial":0,"playerPos":{"x":0.0,"y":0.0,"z":0.0},"playerRotation":{"x":0.0,"y":0.0,"z":0.0,"w":0.0},"sceneID":2}],"childList":[],"buddyList":[]}

-------------------------------------

Hier mal zur Erklärung:

Ich speichere jeden Spielstand in einer seperaten JSON Datei, dies mache ich damit:

        public void SaveSavegame() {
            string time = System.DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss");
            file = path + "/Savegame_" + selectedSavegame + ".json";

            // Aktualisierung aller Daten der Chraktere und Enemys
            LD_SP_Save_Data_Object_Manager.Instance.CharacterListUpdate();
            LD_SP_Save_Data_Object_Manager.Instance.ChildListUpdate();
            LD_SP_Save_Data_Object_Manager.Instance.BuddyListUpdate();
            LD_SP_Save_Data_Object_Manager.Instance.characterList[0].playTime = time;
            LD_SP_Save_Data_Object_Manager.Instance.characterList[0].sceneID = SceneManager.GetActiveScene().buildIndex;

            // Savegame Structure aktualisieren
            savegameStructur[selectedSavegame -1].savegamePlayerName = LD_SP_Save_Data_Object_Manager.Instance.characterList[0].playerName;
            savegameStructur[selectedSavegame -1].savegamePlayTime = time;
            savegameStructur[selectedSavegame -1].savegameExists = true;
            savegameStructur[selectedSavegame -1].savegameSceneNr = SceneManager.GetActiveScene().buildIndex;

            // Display aktualisieren
            charcternameDisplay.text = LD_SP_Save_Data_Object_Manager.Instance.characterList[0].playerName;
            characterSavedOnDisplay.text = time;
            deleteButton.GetComponent<Button>().interactable = true;
            deleteButton.GetComponent<Image>().raycastTarget = true;
            StartCoroutine("RecordSavegamePicture");
            savegamePictureImage.sprite = savegamePictureSpriteArray[selectedSavegame];

            //Savegame schreiben
            string json = JsonUtility.ToJson(LD_SP_Save_Data_Object_Manager.Instance);
            if (!File.Exists(file)) {
                File.Create(file).Dispose();
            }
            File.WriteAllText(file, json);
        }

Klappt soweit und er speichert auch keinen Müll.

Damit ich nicht ständig die Daten aus einer Datei lesen muss, habe ich auch noch eine Struktur, wo alle Werte der 10 Spielstände hinterlegt sind:

    [System.Serializable]
    public class SavegameStructur {
        public string savegamePlayerName = "";
        public string savegamePlayTime = "";
        public bool savegameExists = false;
        public int savegameSceneNr = 0;
    }

Das Speichern klappt, sowohl in der Struktur, als auch in der Datei.

Starte ich nun das Spiel, lade ich mir schon einmal aus allen Speicherständen, sämtliche Werte in die Struktur und den Objektmanager des Spiels. In ihm befinden sich alle relevanten Daten, die im derzeitigen Spiel gebraucht werden.

        private void SaveGameReadBasicData() {
            for (int i = 0; i < savegameStructur.Length; i++) {
                string file = path + "/Savegame_" + (i + 1) + ".json";
                if (File.Exists(file)) {
                    string json = File.ReadAllText(file);

                    LD_SP_Save_Data_Object_Manager.BasicDataInstance.characterList = new List<LD_SP_Save_Data_Player>(JsonUtility.FromJson<LD_SP_Save_Data_Object_Manager>(json).characterList.Count);
                    LD_SP_Save_Data_Object_Manager.BasicDataInstance.childList = new List<LD_SP_Save_Data_Child>(JsonUtility.FromJson<LD_SP_Save_Data_Object_Manager>(json).childList.Count);
                    LD_SP_Save_Data_Object_Manager.BasicDataInstance.buddyList = new List<LD_SP_Save_Data_Buddy>(JsonUtility.FromJson<LD_SP_Save_Data_Object_Manager>(json).buddyList.Count);

                    LD_SP_Save_Data_Object_Manager.BasicDataInstance = JsonUtility.FromJson<LD_SP_Save_Data_Object_Manager>(json);

                    savegameStructur[i].savegamePlayerName = LD_SP_Save_Data_Object_Manager.BasicDataInstance.characterList[0].playerName;
                    savegameStructur[i].savegamePlayTime = LD_SP_Save_Data_Object_Manager.BasicDataInstance.characterList[0].playTime;
                    savegameStructur[i].savegameExists = true;
                    savegameStructur[i].savegameSceneNr = LD_SP_Save_Data_Object_Manager.BasicDataInstance.characterList[0].sceneID;
                } else {
                    savegameStructur[i].savegamePlayerName = "";
                    savegameStructur[i].savegamePlayTime = "";
                    savegameStructur[i].savegameExists = false;
                    savegameStructur[i].savegameSceneNr = 0;
                }
            }
        }

Das wäre der Manager des aktuekken Spiels:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;


namespace Lions_Dream_SP {
    [System.Serializable]
    public class LD_SP_Save_Data_Object_Manager : MonoBehaviour {

        public List<LD_SP_Save_Data_Player> characterList;
        public List<LD_SP_Save_Data_Child> childList;
        public List<LD_SP_Save_Data_Buddy> buddyList;

        public static LD_SP_Save_Data_Object_Manager instance;
        public static LD_SP_Save_Data_Object_Manager basicDataInstance;

        public static LD_SP_Save_Data_Object_Manager Instance {
            set {
                instance = Instance;
            }
            get {
                return instance;
            }
        }

        public static LD_SP_Save_Data_Object_Manager BasicDataInstance {
            set {
                basicDataInstance = BasicDataInstance;
            }
            get {
                return basicDataInstance;
            }
        }

        private void Awake() {
            if (instance != null) {
                return;
            }
            instance = this;
            basicDataInstance = this;
            DontDestroyOnLoad(this.gameObject);
        }

        /******************************** Aufruf zur Aktualisierung aller Chraktere und Enemys ********************************/

        public void CharacterListUpdate() {
            // Aktuelle Characterlist leeren
            characterList.Clear();

            // Objekte finden
            GameObject[] searchObjects = GameObject.FindGameObjectsWithTag("Player");

            // Objekte in Liste aufnehmen
            for (int i = 0; i < searchObjects.Length; i++) {
                LD_SP_Player_Controler playerController = searchObjects[i].GetComponent<LD_SP_Player_Controler>();
                characterList.Add(new LD_SP_Save_Data_Player(
                        playerController.playerName,
                        playerController.playTime,
                        playerController.animal.life,
                        playerController.gender,
                        playerController.bodyShape,
                        playerController.bodyColor,
                        playerController.eyeColor,
                        playerController.noseColor,
                        playerController.bodyMaterial,
                        playerController.pos,
                        playerController.rotation,
                        playerController.sceneID
                    ));
            }
        }

        public void ChildListUpdate() {
            // Aktuelle Childlist leeren
            childList.Clear();

            // Objekte finden
            GameObject[] searchObjects = GameObject.FindGameObjectsWithTag("Child");

            // Objekte in Liste aufnehmen
            for (int i = 0; i < searchObjects.Length; i++) {
                LD_SP_Child_Controler childController = searchObjects[i].GetComponent<LD_SP_Child_Controler>();
                childList.Add(new LD_SP_Save_Data_Child(
                        childController.childID,
                        childController.childName,
                        childController.animal.life,
                        childController.gender,
                        childController.bodyShape,
                        childController.bodyColor,
                        childController.eyeColor,
                        childController.noseColor,
                        childController.bodyMaterial,
                        childController.pos,
                        childController.rotation
                    ));
            }
        }

        public void BuddyListUpdate() {
            // Aktualle Buddylist leeren
            buddyList.Clear();

            // Objekte finden
            GameObject[] searchObjects = GameObject.FindGameObjectsWithTag("Buddy");

            // Objekte in Liste aufnehmen
            for (int i = 0; i < searchObjects.Length; i++) {
                LD_SP_Buddy_Controler buddyController = searchObjects[i].GetComponent<LD_SP_Buddy_Controler>();
                buddyList.Add(new LD_SP_Save_Data_Buddy(
                        buddyController.animalTyp,
                        buddyController.buddyID,
                        buddyController.buddyName,
                        buddyController.animal.life,
                        buddyController.pos,
                        buddyController.rotation
                    ));
            }
        }
    }

    [System.Serializable]
    public class LD_SP_Save_Data_Player {
        // Keinesfalls von Monobehavior erben lassen, dies zerstoert die JSON-Datei!
        public string playerName;
        public string playTime;
        public float playerVitaility;
        public int playerGender;
        public float[] playerBodyShape;
        public float[] playerBodyColor;
        public float[] playerEyeColor;
        public float[] playerNoseColor;
        public int playerBodyMaterial;
        public Vector3 playerPos;
        public Quaternion playerRotation;
        public int sceneID;


        public LD_SP_Save_Data_Player(string name, string time, float vit, int gender, float[] bodyShape, float[] bodyColor, float[] eyeColor, float[] noseColor, int bodyMaterial, Vector3 pos, Quaternion rot, int sceneID) {
            playerName = name;
            playTime = time;
            playerVitaility = vit;
            playerGender = gender; // 0 = Female | 1 = Male
            playerBodyShape = new float[bodyShape.Length];
            playerBodyColor = new float[bodyColor.Length];
            playerEyeColor = new float[eyeColor.Length];
            playerNoseColor = new float[noseColor.Length];
            Array.Copy(bodyShape, playerBodyShape, bodyShape.Length);
            Array.Copy(bodyColor, playerBodyColor, bodyColor.Length);
            Array.Copy(eyeColor, playerEyeColor, eyeColor.Length);
            Array.Copy(noseColor, playerNoseColor, noseColor.Length);
            playerBodyMaterial = bodyMaterial;
            playerPos = pos;
            playerRotation = rot;
            this.sceneID = sceneID;
        }
    }

    [System.Serializable]
    public class LD_SP_Save_Data_Child {
        // Keinesfalls von Monobehavior erben lassen, dies zerstoert die JSON-Datei!
        public int childID;
        public string childName;
        public float childVitaility;
        public int childGender; // 0 = Female | 1 = Male
        public float[] childBodyShape;
        public float[] childBodyColor;
        public float[] childEyeColor;
        public float[] childNoseColor;
        public int childBodyMaterial;
        public Vector3 childPos;
        public Quaternion childRotation;


        public LD_SP_Save_Data_Child(int id, string name, float vit, int gender, float[] bodyShape, float[] bodyColor, float[] eyeColor, float[] noseColor, int bodyMaterial, Vector3 pos, Quaternion rot) {
            childID = id;
            childName = name;
            childVitaility = vit;
            childGender = gender;
            childBodyShape = new float[bodyShape.Length];
            childBodyColor = new float[bodyColor.Length];
            childEyeColor = new float[eyeColor.Length];
            childNoseColor = new float[noseColor.Length];
            Array.Copy(bodyShape, childBodyShape, bodyShape.Length);
            Array.Copy(bodyColor, childBodyColor, bodyColor.Length);
            Array.Copy(eyeColor, childEyeColor, eyeColor.Length);
            Array.Copy(noseColor, childNoseColor, noseColor.Length);
            childBodyMaterial = bodyMaterial;
            childPos = pos;
            childRotation = rot;
        }
    }

    [System.Serializable]
    public class LD_SP_Save_Data_Buddy {
        // Keinesfalls von Monobehavior erben lassen, dies zerstoert die JSON-Datei!
        public animalTyp animalTyp;
        public int buddyID;
        public string buddyName;
        public float buddyVitaility;
        public Vector3 buddyPos;
        public Quaternion buddyRotation;


        public LD_SP_Save_Data_Buddy(animalTyp type, int id, string name, float vit, Vector3 pos, Quaternion rot) {
            animalTyp = type;
            buddyID = id;
            buddyName = name;
            buddyVitaility = vit;
            buddyPos = pos;
            buddyRotation = rot;
        }
    }

    public enum animalTyp : short {
        Lion = 1,
        Tiger = 2,
        Deer = 3,
        Pig = 4
    }
}


 

Link zu diesem Kommentar
Auf anderen Seiten teilen

OK, für die, die mal am selben Problem stehen, ist der Link interessant:

https://stackoverflow.com/questions/42904122/unity-deserialize-into-scriptable-object

Erste Antwort:

Zitat
 

Use ToJsonOverwrite instead!

Note that the JSON Serializer API supports MonoBehaviour and ScriptableObject subclasses as well as plain structs/classes. However, when deserializing JSON into subclasses of MonoBehaviour or ScriptableObject, you must use FromJsonOverwrite; FromJson is not supported and will throw an exception.

https://docs.unity3d.com/Manual/JSONSerialization.html

So for you that'd be


JsonUtility.FromJsonOverwrite(text, list);

Note that this is not an immutable method and will overwrite your object, but it seems like that was your intention anyway.

Also kurz un knapp, statt die Methode:

JsonUtility.FromJson

Diese Methode nutzen:

JsonUtility.FromJsonOverwrite

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...