Jump to content
Unity Insider Forum

xmlSerialization Problem


Rokks

Recommended Posts

Moin moin zusammen.

 

ich wusle mich gerade ein wenig in xml speichern/laden Funktionen ein und komme über eine möglicherweise ganz banale Hürde nicht hinweg.

Mein Skript sucht alle "speicherbaren" Objekte in der Scene und hinterlegt entsprechende Werte in eine list<>.

Die dort abgelegten Einträge sollen dann als xml gespeichert werden.

 

Sobald das Skript jedoch an den Punkt des speicherns ankommt gibts den berühmten Finger.

InvalidOperationException: Building cannot be serialized because it does not have a default public constructor

 

Public? Hm, Brille auf und nachgesehen ... hm ... meines Erachtens als Public deklariert.

Hat jemand von Euch nen goldenen Tip für mich, kann berichten was ich verkehrt gar vergessen habe?

 

Gruß

Rokks

 

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

public class xmlSaveLoad : MonoBehaviour {
public string saveName;
public YourBase ListObjects; //Liste aller speicherbaren Objekte
//Helferlein
public GameObject[] bO; //buildingObject

void Start() {
 //nur zu Testzwecken bleibt der Speichername fest deklariert
 saveName = "save_1";
}

void Update () {
 //Spielstand speichern
 if(Input.GetKeyDown(GameState.Instance.GetComponent<GameStateKey>().sceneSave)){
  //Suche alle speicherbaren Gebäudedaten ...
  SearchSaveObjcts();
  //Speicheraufruf
  SaveGame();
 }
}

void SearchSaveObjcts() {
 //Sucht alle Objekte die als "speicherbar" notiert sind und legt diese ab
 bO = GameObject.FindGameObjectsWithTag("saveableBuilding");
 foreach(GameObject obj in bO) {
  ListObjects.buildingList.Add (new Building(obj.transform.GetComponent<BuildingFacts>().buildingID,
obj.transform.position,
obj.transform.eulerAngles,
obj.transform.GetComponent<BuildingFacts>().buildingActive,
obj.transform.GetComponent<BuildingFacts>().buildingBreath,
obj.transform.GetComponent<BuildingFacts>().buildingEnergy,
obj.transform.GetComponent<BuildingFacts>().buildingConstruction
  )
  );
 }
}

public void SaveGame() {
 XmlSerializer serializer = new XmlSerializer(typeof(YourBase));
 FileStream stream = new FileStream (Application.dataPath + "/Game/Saves/" + saveName + ".xml", FileMode.Create);
 serializer.Serialize (stream, ListObjects);
 stream.Close ();
}
}

/*
* Einträge für Basenbau
*/
[system.Serializable]
public class Building {
public string buildID;
public Vector3 position;
public Vector3 rotate;
public bool active;
public int breath;
public int energy;
public int construct;

public Building (string id, Vector3 pos, Vector3 rota, bool on, int air, int ener, int constru) {
 buildID = id;
 position = pos;
 rotate = rota;
 active = on;
 breath = air;
 energy = ener;
 construct = constru;
}

}
[system.Serializable]
public class YourBase {
[XmlArray("BuildBuildings")]
public List<Building> buildingList = new List<Building>();
}

Link zu diesem Kommentar
Auf anderen Seiten teilen

YourBase mag zwar den DefaultConstructor haben, weil du keinen anderen definiert hast.

Aber Building besitzt nur 1 Konstruktor und das ist kein defaultConstructor.

 

Nur zum Verständnis ein default Constructor ist das hier:

 

//Keine Parameter
public Klassenname()
{
]

Link zu diesem Kommentar
Auf anderen Seiten teilen

Um dem von oben noch etwas anzufügen:

Deine Klasse YourBase hat einen Default-Constructor, da du keinen Konstruktor der Klasse deklariert hast, also generiert das System einen Default für dich (ohne Parameter, mit leerem Rumpf).

 

Sobald du aber einen eigenen Konstruktor anlegst, der Parameter enthält, (wie im Fall der Klasse "Building") wird kein Default-Constructor mehr generiert und du musst den Default explizit selber angeben, ansonsten passiert genau das was du beschreibst.

Es könnte ja sein, dass du dann keine Instanz mehr ohne entsprechende Parameter erzeugen lassen möchtest.

 

Der Default-Konstruktor muss, wie Djeurissen geschrieben hat, Parameterlos sein, (Ansonsten ist er kein Default-Constructor) er darf aber übrigens durchaus Anweisungen im Rumpf haben.

Mein Tipp wäre immer sobald du einen Konstruktor anlegst, auch einen Default-Construktor anzulegen, egal ob der gerade gebraucht oder nicht, dann kommt man auf jeden Fall nicht in die Bredouille und so viel Aufwand ist das auch wieder nicht ^^

Kann man auch schön in eine Zeile schreiben (einfach die { } nebeneinander), dann fällt er nicht auf.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Mein Tipp wäre immer sobald du einen Konstruktor anlegst, auch einen Default-Construktor anzulegen, egal ob der gerade gebraucht oder nicht, dann kommt man auf jeden Fall nicht in die Bredouille und so viel Aufwand ist das auch wieder nicht ^^

Kann man auch schön in eine Zeile schreiben (einfach die { } nebeneinander), dann fällt er nicht auf.

Außer natürlich, du willst verhindern, dass ein Objekt ohne Parameter angelegt werden kann. Ist auch manchmal sinnvoll. Ich weiß nicht, ob der Default-Konstruktor für die Serializable-Funktionalität auch private sein kann, das wäre dann eine Lösung für diesen Fall.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...