Jump to content
Unity Insider Forum

GameObjects speichern


Kevin28

Recommended Posts

Hallo, 

ich habe eine App erstellet, die als Funktion Umsätze zusammenfassen soll. 

Ich habe ein Script erstellt welches GameObjects erstellt welche einen gewissen wert enthalten und diese bennent. Meine Frage lautet wie ich diese GameObjects speichern kann, so dass sie beim nächsten Öffnen des Programms immer noch vohanden sind. Gibt es eine einfache Möglichkeit dies in meinem Script hinzuzufügen oder etwas im Asset Store was dies ermöglicht?

Hier mein Script:

public void NeuesElement()
    {

        Element = Instantiate(Inhalt);
        Element.transform.SetParent(GameObject.Find("Panel1").transform);
        Element.GetComponentInChildren<Text>().text = Preis.text;
        Element.name = "Umsatz" + NächsteNummer;
        NächsteNummer++;

 

Vielen Dank

Mit freundlichen Grüßen

Link zu diesem Kommentar
Auf anderen Seiten teilen

Guten Morgen @Kevin28 - direkt zu Beginn: ICH BIN KEIN EXPERTE! Aber ich kann dich in die richtige Bahn lenken. Du musst dann jedoch selbst recherchieren :D

Ich denke, dass man hier mit dem System.IO Namespace an die Lösung kommen kann. System.IO gibt dir Zugriff auf verschiedene Klassen wie z.B File, DirectoryInfo, usw. die in C# Dateien, Ordner und Pfade auf dem Computer repräsentieren. Mein Lösungsansatz würde wie folgt aussehen:

Wenn du dein Spiel schließt (oder von mir aus auch direkt nach der Erstellung der besagten Objekte) erstellst du im persistentDataPath (das ist der Ordner des Programms im Verzeichnis %AppData%) z.B einen Ordner der "Objekte" heißt. Das wäre der erste Schritt, um zu garantieren, dass auch alle Objekte von einem Typen ihr eigenes Verzeichnis besitzen. Dann könntest du über die Childs von deinem "Panel1" drüber loopen und für jedes Objekt eine individuelle Datei mit einer von dir gewählten Endung (z.B .Objekt1.txt oder Objekt1.dat) in diesem Verzeichnis erstellen. All das ist Teil vom System.IO Namespace.

// Um ein Verzeichnis zu erstellen, benutz einfach die CreateDirectory-Funktion, die Teil der Klasse "Directory" ist.

Directory.CreateDirectory(Application.persistentDataPath + "/deinOrdnerName");

 // Und schon hast du einen Ordner erstellt.


// Angenommen, wir haben deine gewünschten Speicherobjekte in einem GameObject[] (Array) liegen.
GameObject[] alleObjekte = new GameObject[]{10}; // 10 Objekte
for(int i = 0; i < alleObjekte.Length ; i++) // erstelle 10 Dateien
{
  		string dateiPfad = Application.persistentDataPath + "/deinOrdnerName/"; // in diesem Ordner
  		FileStream neueDatei = File.Create(dateiPfad + alleObjekte[i].GetComponent<ObjektInfo>().objektName);  // mit diesem Namen
  
  // setzt aber voraus, dass das Objekt irgendwo ein public Field / eine Property namens "objektName" hat, das/die wir uns holen können, um die Datei im Order zu benennen.
}

Jetzt haben wir das Verzeichnis erstellt und für jedes Objekt eine eigene externe Datei angelegt. Problem ist nur, dass wir jetzt noch die Werte des Objektes in diese Datei schreiben müssen, da es ansonsten ja nur leere Dateien wären. Sprich wir springen nochmal zurück in den Loop. Da du offensichtlich nur mit Strings / Ints / Floats arbeitest, sollten wir in der Lage sein die Werte über einen sogenannten StreamWriter in die Datei zu schreiben, ohne einen BinaryFormatter oder ähnliches zu benutzen. Ein StreamWriter ist gewissermaßen ein Modul, dass wie eine (Achtung: Abstraktion) "Schreibmaschine" funktioniert. Alles, was der StreamWriter von dir verlangt ist ein FileStream. Und ein FileStream ist im Grunde nicht mehr, als eine Repräsentation der Datei, in die der Writer etwas hinein schreiben soll. Wobei genauer gesagt: das FileInfo Objekt ist eher die GENAUE Repräsentation der Datei, wo hingegen der Stream lediglich eine Art "Verbindungsstück" / "Überbrückung" ist, das die Daten empfängt und sie in kleinen Päckchen an den Writer / Reader weiterleitet. Schwierig zu beschreiben, sollte aber ausreichen :D

Jede Instanz vom StreamWriter hat Methoden, auf die du zugreifen kannst. Mit writer.WriteLine(string deinText) kannst du jetzt den von dir gewünschten Inhalt in die externe Datei schreiben, die wir davor noch erstellt haben. Das machst du dann für alle Werte des Objektes, die du später wieder laden möchtest. Müsste dann irgendwie so aussehen:

// wir sind wieder im Loop von eben!

for(int i = 0; i < alleObjekte.Length ; i++) // erstelle 10 Dateien
{
  		string dateiPfad = Application.persistentDataPath + "/deinOrdnerName/"; // in diesem Ordner
  		FileStream neueDatei = File.Create(dateiPfad + alleObjekte[i].GetComponent<ObjektInfo>().objektName);  // mit diesem Namen
  		// das ist der Stream, in den wir nun was schreiben wollen... lass uns also einen StreamWriter erstellen
		StreamWriter writer = new StreamWriter(neueDatei); // neueDatei geben wir als Stream an den Writer
  		writer.WriteLine("Dies ist ein Testtext, den ich in meine Datei schreibe."); // Jetzt haben wir in die Datei geschrieben.
		writer.Close(); // Und am Ende schließen wir den Writer noch. Gehört zur Prozedur dazu!

  
}

Nachdem wir all das gemacht haben, existieren nun mehrere Dateien im Verzeichnis - losgelöst von deiner Anwendung. Wir haben jetzt 10 Dateien erstellt und in jede Datei etwas hinein geschrieben.

Wenn du nun dein Spiel beendest und das Spiel neu lädst, werden die Daten jedoch nach wie vor verschwinden. Das ist dann der Punkt, an dem du vom StreamWriter zum StreamReader überspringen musst. Der StreamReader ermöglicht dir nämlich wie der Name schon sagt, Text aus Dateien auszulesen. Wichtig ist also, dass du nun in irgendeiner Start-Funktion in deinem Programm eine Funktion hast, die zunächst einmal prüft, ob das Verzeichnis für die Objekte existiert und ob innerhalb dieses Verzeichnisses auch Dateien (Objekte) liegen. Ich glaube in C# kannst du die Dateien in einem Ordner in einem FileInfo[] (Array) speichern. Folgendes Beispiel:

private void ErstelleGameobjekte()
{
  
// Referenz zum Pfad
string meinOrdner =  Application.persistentDataPath + "/deinOrdnerName";
  

// Prüfen, ob ein Ordner überhaupt existiert machst du so:
	if(Directory.Exists(meinOrder)
  	 {
             DirectoryInfo ordnerInfo = new DirectoryInfo(meinOrdner);
     	 // hier nun ein Array mit allen Files in diesem Ordner... beachte, dass wir eine Funktion vom DirectoryObject benutzen, die einen FileInfo Array returned.
			FileInfo[] alleDateien = ordnerInfo.GetFiles();
   	}
   
 }

Nachdem du das gemacht hast, hast du nun alle Dateien in diesem Ordner in deinem Array liegen. Sprich, wir loopen nun über diesen Array und erstellen für jede Datei in diesem Array eine Instanz deines Prefabs und synchronisieren die Daten von diesem Prefab (die wir uns mit GetComponent greifen) dann mit den Daten aus der externen Datei. Das machst du mit dem eben von mir erwähnten StreamReader, der dich nun die Zeilen aus der Datei lesen lässt. Ich glaube, dass wie beim Writer die Funktion dafür einfach Reader.ReadLine(); / Reader.ReadToEnd(); oder so ähnlich sein sollte. Das ist die Richtung in die du gehen kannst.

// Gleicher Code wie eben, nur weiter ausgeführt.

public GameObject deinPrefab;
public Transform irgendeinParent;

private void ErstelleGameobjekte()
{
  
// Referenz zum Pfad - dieses Mal als String
string meinOrdner =  Application.persistentDataPath + "/deinOrdnerName";
  
// Prüfen, ob ein Ordner überhaupt existiert machst du so:
	if(Directory.Exists(meinOrder) 
  	 {
       
     		 // hier nun ein Array mit allen Files in diesem Ordner... beachte, dass wir eine Funktion vom DirectoryObject benutzen, die einen FileInfo Array returned.
      		DirectoryInfo ordnerInfo = new DirectoryInfo(meinOrdner);
			FileInfo[] alleDateien = ordnerInfo.GetFiles();
       
      		 foreach(FileInfo info in alleDateien)
  				{
    				GameObject obj = Instantiate(deinPrefab, irgendeinParent);
    				ObjektInfo data  = obj.GetComponent<ObjektInfo>(); 
    
          FileStream stream = info.Open(FileMode.Open); // Du musst nun einen FileStream auf diese Art und Weise erstellen.
    	StreamReader reader = new StreamReader(stream); // ...und ihn auf diese Art und Weise an den Reader weitergeben!
		data.Name = reader.ReadToEnd();  
		reader.Close(); // Auch hier wieder den Reader schließen!
               
   			}
   
 }

 

Und im Grunde solltest du an dieser Stelle Informationen vom Computer in dein Spiel geladen haben.

Solltest du mit Datentypen arbeiten, die nicht primitiv sind, wird es komplizierter, da du dann BinaryFormatter benutzen musst, um Daten zu serializen, usw. Ein wichtiger Punkt, den ich nicht angemerkt habe ist: JSONUtility. Schau dir auf jeden Fall auch mal Beiträge zu JSON an, da du höchstwahrscheinlich früher oder später Sachen zu JSON konvertieren musst um von dort aus dann weiter zu arbeiten. 

Ich selbst arbeite z.B größtenteils nur mit Scriptable Objects, demnach weiß ich nicht wie du speziellen Zugriff auf Zeile 3 oder so in einer externen Datei kriegst, um irgendeiner Variable genau diesen Wert zuzuweisen. Aber auch das kannst du durch Recherche easy lösen! Beim Scriptable Object kann ich mir die Werte dann nämlich immer direkt aus den jeweiligen Feldern holen. Nochmals: ich bin kein Experte und wollte dir lediglich die Richtung vorgeben! :D

Sorry, dass ich am Ende etwas schlampig geworden bin. Ich hoffe, ich konnte dir dennoch etwas helfen!
LG, Maurice 🙂


 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Lädt...
×
×
  • Neu erstellen...