Jump to content
Unity Insider Forum
aurelsmarc

Objekte Speichern und über Instanz neu erstellen/platzieren.

Recommended Posts

Hallo, vielen Dank schonmal im Voraus für die Hilfe. 

Ich habe eine kleine Szene in Unity erstellt, in der ich 3D-Objekte (Prefabs) mit einem Script auf einer "Plane" platzieren kann. Leider fehlt mir die Möglichkeit diese zu speichern.

Ich möchte beim Neustart des Spiels, durch einen ObjectManager der sich diese Objekte gemerkt hat, diese wieder an gleicher Position platzieren lassen (über Instanzen).

Kann mir dort jemand helfen. Über PlayerPrefs kann ich leider keine Objekte speichern. Gespeichert werden muss die Position/Rotation und die Art des Objekt und ein weiterer Float-Wert (den brauche ich später), für mehre Objekte. Wie viele Objekte in einer Szene sind, ist unterschiedlich, je nachdem wie viele der Spieler erstellt hat. irgendwelche Ideen?

Update: Eine meiner ursprünglichen Ideen war es, für jedes Objekt eine PlayerPref von Typ String anzulegen. Etwa so "objectID,objectType,objectPosX,objectPosY,objectPosZ,objectRotX,objectRotY,objectRotZ,value" und das dann immer an den "," wieder aufzusplitten. Mein Problem, da ich nicht weiß, wie viele Objekte es gibt, kann ich nicht einfach alle möglichen IDs durchgehen.

Vielen Dank.

Share this post


Link to post
Share on other sites

Ich denke, das du ab diesem Moment die Playerprefs nicht mehr nutzen solltest. Playerprefs snd zwar nicht schlecht, wenn man ein paar Daten speichern will, aber für deine Bedürfnisse sind Playerprefs nicht gut.
Ich würde dir empfehlen das Ganze mit Hilfe von JSON oder einer anderen Art als Textfile zu speichern.
Gespeichert würde dann eine Object ID oder Objektname, die deinem Instanzierer sagt um welches Objekt es sich handelt und die Variablen Informationen, wie die 3 Positionsangaben, die 3 Richtungsangaben(wenn nötig) und interne Werte, wenn es von einem Objekttyp unterschiedliche Varianzen gäbe, wie zB. der Füllgrad einer Trinkflasche.

JSON speichert die Daten immer so ab, dass zuerst ein Variablenname kommt und danach der Wert der Variable. Getrennt wird dann über ein Komma.
So z.B.:
{"ObjectName":"Stein",ObjectGewicht":0.5,"ObjectX":15.4,"ObjectY":0,"ObjectZ:4.2}

Da jeder VariablenName nur einmal in der Datei vorhanden sein kann, setzt du einfach eine Zahl hinten dran. Du vergibst ja selber die Variablennamen und außerdem liest du die ja aus einem Dictionary, einer Liste oder einem Array aus. Dabei ergibt sich eh eine Zahl aufgrund der Position in der Liste/Dictionary/Array oder eines Zählers.

Somit lauten deine Variablen dann "ObjectName1","ObjectGewicht1", "ObjectName2", "ObjectGewicht2" usw.
Das Ganze übergibst du dann JSON (und das geht dann eben solange, bis du am Ende der Liste bist) und daraus wird dann ein String serialisiert, wie oben gezeigt, erzeugt. Den speicherst du als Textfile ab. Je nach Anzahl der Einträgewird dann deine Textdatei länger oder eben kürzer.


Hier ein Beispiel wo die Variable objektdaten ein erzeugter JSON String wäre.

 StreamWriter osw = new StreamWriter(Application.persistentDataPath +"/"+saveName+"_objekte.txt");  // objekte
 //zeile schrieben
 osw.WriteLine(objektdaten);
 osw.Flush();
 osw.Close();  //damit schliessen wir den StreamWriter



Einlesen geht dann genau rückwärts. Textfile wird eingelesen und der String wird über JSON deserialisiert und den Listen oder Dictionarys übergeben. Mittels dieser Werte instanzierst du dann später dein gewünschtes Objekt und übergibst ihm dann seine Positionswerte und Interna.

Hier ein Beispiel wir ich mit miniJSON die Objektdaten eingelesen hatte und sie einem Dictionary übergeben habe:
 

StreamReader osr =new StreamReader(Application.persistentDataPath +"/"+saveName+"_objekte.txt");
var jsonStringObjekte=osr.ReadLine();
osr.Close(); //damit schließen wir unseren StreamReader
            
odict.Clear();
odict=Json.Deserialize(jsonStringObjekte) as Dictionary<string,object>;

 

JSON ist seit einiger Zeit in Unity mit drin, man braucht also eigentlich keine JSON Plugins mehr nutzen.
Schau mal hier:
https://docs.unity3d.com/Manual/JSONSerialization.html

Share this post


Link to post
Share on other sites

Oh, Dankeschön. Da ich mich mit JSON noch gar keine Erfahrungen habe, werde ich mich dort erstmal ordentlich einlesen. Danke für den Tipp.

Share this post


Link to post
Share on other sites

könnte man das n icht auch mit ScriptableObjects lösen? einfach für jedes erstellte GameObject dessen Daten in eine Instanz des ScriptableObjects speichern. diese sind dann im Asset gespeichert. 

Ich fuchs mich grad selbst in das Thema ScriptableObjects hinein und für diese Aufgabe sollte es machbar sein, oder?

Share this post


Link to post
Share on other sites

ScriptableObjects haben nichts zum Speichern während der Laufzeit. Die werden im idR. Editor erstellt und damm im Build deserialisiert. Damit aber Spielstände oder so zu speichern hat keinen Vorteil.

Share this post


Link to post
Share on other sites
Am 5.6.2018 um 11:20 schrieb malzbie:

JSON speichert die Daten immer so ab, dass zuerst ein Variablenname kommt und danach der Wert der Variable. Getrennt wird dann über ein Komma.
So z.B.:
{"ObjectName":"Stein",ObjectGewicht":0.5,"ObjectX":15.4,"ObjectY":0,"ObjectZ:4.2}

Da jeder VariablenName nur einmal in der Datei vorhanden sein kann, setzt du einfach eine Zahl hinten dran. Du vergibst ja selber die Variablennamen und außerdem liest du die ja aus einem Dictionary, einer Liste oder einem Array aus. Dabei ergibt sich eh eine Zahl aufgrund der Position in der Liste/Dictionary/Array oder eines Zählers.

Ich muss hier mal Korrigieren, Variablename in JSON können pro Datei durchaus mehrfach vorkommen, solange sie nicht in der selben Ebene sind.

JSON unterstützt auch Arrays und verschachtelungen

[
  {
    "objectName": "Object1"
    "position": {
      "x": 14.78,
      "y": 45.785,
      "z": 10.01
    }
  },
  {
    "objectName": "Object2"
    "position": {
      "x": 16.78,
      "y": 44.785,
      "z": 12.01
    }
  }
]

 

Share this post


Link to post
Share on other sites

Ja gut, das kann sein. Ich habe immer nur mit miniJSON gearbeitet und da ist es nur eine Ebene (soviel ich weiß...). Es gibt außerdem noch andere kleinere Nachteile. Dafür istes schön klein und einfach einzubinden. :)

Ich muss mir unbedingt mal angucken wie das JSON von Unity arbeitet.


 

Share this post


Link to post
Share on other sites

Ich habe in einem projekt beide varianten genutzt. Für Accessoires für den Spieler gibt es ScriptableObjects die bei Generierung per TimeStamp eine ID erzeugen und diese Speichern, dann speichere ich diese Strings mit Trennern und cutte den String dann beim laden und suche nach den IDs. Ebenfalls lade ich Aufgaben und Spieldaten per JSON von einem Server und speichere diese Dann lokal zwischen um beim nächsten Update nur das nötigste zu laden. Für JSON nutze ich das Unity eigene und JSON.Net für Unity.

Share this post


Link to post
Share on other sites

Warum nutzt du JSON.Net und das Unityeigene?
Hat eines von denen etwas, was das andere nicht hat?

Share this post


Link to post
Share on other sites

JSON.Net kann z.B. Daten upgraden, bei Unity überschreibt das FromJsonOverwrite alle Daten, also auch wenn ich kein update vom server habe und somit ein JSON String null ist. Das kann man bei JSON.Net auskoppeln, sodass er alle null Einträge ignoriert und nicht versucht, diese zu ersetzen. Unitys eigenes hatte ich vorher genutzt und läuft jetzt nur als Scriptleiche mit für einfache Daten, bei denen auf jeden Fall alles überschrieben werden soll, wie PlayerDaten Lokal.

  • Like 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×