Jump to content
Unity Insider Forum

Dynamic casting


Life Is Good

Recommended Posts

Hallooo !

Ich versuche gerade zum auslesen meiner gespeicherten Daten dynamisch zu casten...

 

Als erstes bin ich auf Convert.ChangeType gestoßen, allerdings habe ich auch Typen die nicht das IConvertible Interface einbinden.

 

Dann hab ich etwas gefunden dass durch Reflection und einer generischen Methode dynamisch casten soll (was auch funktioniert !)

So sieht das ganze aus :

 

Type type = fields[i].FieldType;
Debug.Log(type); // Typ InventoryItem !

object obj = listData[attribute.name]; // listData enthält objects !

MethodInfo castMethod = this.GetType().GetMethod("Cast").MakeGenericMethod(type);
object castedObject = castMethod.Invoke(null, new object[] { obj });

fields[i].SetValue (baseObj, castedObject);



public static T Cast<T>(object o)
{
Debug.Log(typeof (T)); // Gibt auch InventoryItem aus !
return (T)o;
}

 

komischer Weise bekomme ich aber die Meldung ausgegeben ich könnte nicht vom Source zum Ziel Typ casten, vielleicht jemand 'ne Idee woran das liegt ?

 

 

Edit:

Oh man, ich hab vergessen meine alte Binary zu löschen, das hat da wohl irgendwie rumgemuckt -.-

Die Meldung ist weg.

 

Jetzt bekomme ich beim speichern (in eine Binary Datei durch Serialisierung) allerdings die Meldung. dass mein Typ nicht mit serializable markiert wäre. Jup, müsste ja auch ausgegeben werden, würde ich einfach meinen Typen InventoryItem in die Binary speichern, abbbberrr, ich caste mein Item zum speichern in eine Liste vom Typ object, das sollte das Problem doch eigentlich lösen oder ?

Oder wird es irgendwie dennoch als InventoryItem behandelt ?

 

Edit 2:

Also noch mal genauer erklärt. Ich habe eine Liste<InventoryItem> und diese caste ich dann wiederum in ein Dictionary das als Key nen string und als Value ne Liste vom Typ object nimmt.

->>>

// baseObj ist die einzige Instanz meiner Klasse indem sich die Felder befinden.
// den Wert den mein object hier bekommt ist der meiner InventoryItem Liste.
object obj = fields[i].GetValue(baseObj)

// listData ist mein Dictionary. Dictionary<string, List<object>.
listData.Add(attribute.name, ((IEnumerable)obj).Cast<object>().ToList());

Link zu diesem Kommentar
Auf anderen Seiten teilen

Warum machst du es dir eigentlich so kompliziert? Nutze doch fertige Lösungen wie Json.Net ... bei den Unity-eigenen Klassen muss man zwar ein wenig nachhelfen oder nutzt eben das Json.Net for Unity aus dem AssetStore. Dann wird das ganze Gedönse dort zu einem OneLiner. etwa so als Beispiel:

 Inventory inv = JsonConver.Deserialize<Inventory>(jSonString);

Nutzt man die normale .Net Version sollte man beachten, dass Inventory ist kein MonoBehaviour ist und Typen wie GameObject anders behandelt werden müssen. Beispielsweise in dem man sich eine Klasse für die Save Dateien anlegt:

 

public class Player : MonoBehaviour
{
public Inventory MyInventory = new Inventory();

void Start()
{
string jsonString =   "Items": [
   {
  "SlotId": 0,
  "ItemId": 3,
  "ItemCount": 1
   }]";

// Load playerData
PlayerSaveData psd = JsonConvert.Deserialize<PlayerSaveData>(jsonString);
MyInventory= psd.Inventory;


// Save
psd.Inventory = MyInventory;
jsonString= JsonConvert.Serialize(psd);
// write a file here, use the jsonString
}
}

[system.Serializable]
public class Inventory
{
public List<int> Items = new List<int>(); // item ids --> needs a item database! load item by id
//..
}

[system.Serializable]
public class PlayerSaveData
{
public Inventory Inventory = new Inventory();
//..
}

 

...und vorallem ist das alles schön formatiert und lesbar. Wenn man möchte dann man vor dem deserialize und serialize noch irgendwas machen um den string zu verschlüsseln oä.

 

 

Die idee, dein Inventar als Dictionary zu nutzen ist ganz gut, allerdings würde ich als key ein int verwenden, den Slot im Inventar, als value nur die Id des Items. Spart Platz.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Habe ehrlich gesagt gerade zum ersten mal "JSON" gehört :)

 

Also das meiste was ich im Assetstore gerade finde kostet ja was, da finde ichs eigentlich nicht so tragisch ein paar Zeilen mehr zuschreiben...

 

Das Inventory ist übrigens (naja indirekt !) ein MonoBehaviour. Die items sind, nach Saschas kleinem Blogeintrag, ScriptableObjects.

 

Ich wollte damit jetzt auf ein allgemeines Speichersystem umsteigen, also auch nicht bloß für das Inventar.

Mein Gedanke war einfach solche Dinge wie die Elemente die man speichern muss in ein allgemeines Dictionary einzutragen (deshalb die Liste vom Typ object) also generisch, weiß im Endeffekt aber auch gar nicht, ob das klug ist oder nicht so das Speichern anzugehen :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

Siehste... dafür eignet sich das super!

Deine Inventory-Klasse baust du wie oben im Beispiel in deine Player Klasse ein und fertig.

Meine Items sind auch ScribtableObjects und ich habe mir das Teil auch nicht gekauft... der QuellCOde ist übrigens frei zugämglich, so das man auch selbst den ganzen Unity Kram einbauen könnte... da ich mir das Teil auch nicht gekauft habe (es aber mal tun sollte, weil ich keine Lust habe die wuelle anzupassen), habe ich mir eine Speicherklasse gebaut, die alles was Unity-eigenes Zeug ist in strings und floats umwandelt. Meine Speicherdatei enthält atm folgendes:

http://pastebin.com/VeNDdV26

Link zu diesem Kommentar
Auf anderen Seiten teilen

Also deine Items speicherst du dann gar nicht als Instanz deiner Item Klasse (also als ScriptableObject selbst) sondern als string (oder als ID) ab ?

Ich lasse soweit meine items, die aufgesammelt wurden, einfach in eine Liste vom Typ meiner Item Klasse eintragen und die wollte ich dann abspeichern.

Hört sich ja ganz Sinnvoll an, und erspart mir auch das mit dem dynamischen casten, aber ist das nicht wesentlich langsamer mit strings zu arbeiten ?

 

Ich nehme mal an mit dem Quellcode meinst du die SimpleJSON File ? Das hab ich jedenfalls jetzt auf die schnelle als erstes gefunden außerhalb des stores

Link zu diesem Kommentar
Auf anderen Seiten teilen

Also im Inventar sind schon Scriptables. Nur zum speichern nutze ich deren Id´s, den Slot im Inventar und die Anzahl der Items.

Also am besten fährst du echt mit Json.net, die Version für 3.5 spuckt einen Feher aus, daher nehme ich die für 2.0.

Wie gesagt, das gibt es so kostenlos. Das modifizierte für Unity kostet eben... aber das nutze ich auch nicht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Klingt blöd, aber irgendwie will das Framework bei mir nicht.

Suche schon die ganze Zeit rum aber nichts hats bei mir gelöst...

 

Ich hab, wie überall angewiesen, das Framework über NuGet installiert, toll, in Visual Studio läuft dann auch alles, bekomme den namespace usw. vorgegeben, Unity sagt mir aber es kenne Newtonsoft.Json nicht.

Dann hab ich versucht die dll manuell hinzuzufügen, auch nichts.

Dann hab ich gesehen, ok, es gibt verschiedene Versionen für die jeweiligen .Net Versionen, 7.0.1 sei für .Net 4.5, also manuell die dll für 4.5 gewählt, und wieder nichts.

Neues Projekt erstellt, wieder nichts.

 

Ich hab auch einfach mal das Projekt neugebuildet, keine Meldungen, nichtmal Warnungen, Unity will trotzdem nicht.

 

Was mach ich da denn falsch ???

 

 

Edit:

Nach reichlich suchen die Lösung gefunden :)

In Unity unter ->

Edit -> Project Settings -> Player -> Optimization -> API Compatibility Level

.Net 2.0 Subset zu .Net 2.0 ändern.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...