Jump to content
Unity Insider Forum

Item und Invetory


Singular

Recommended Posts

Guten Abend zusammen,

ich bin gerade dabei mein erstes Invetarsystem für mein Spiel zu entwerfen. Habe mir auch dazu ein Paar YouTube Videos angeschaut, auch wenn das alles nicht so ganz nach meinem Geschmack war. Ich versuche es nun nach meinem eigenem Verständnis von C#. Entweder übersehe ich hier etwas oder es ist der zusammenhang zwischen MonoBehaviour und meiner eigenen Klasse. Lange Rede, gar kein Sinn.

Folgendes habe ich gemacht:

Ich habe ein Script geschrieben und die Vererbung von MonoBehaviour rausgenommen und eine eigene neue Klasse namens "Item" erstellt.

Dazu habe ich einen enum ItemType, der verschiedene (Wer hätte es gedacht?) Item Typen speichert. (Wobei ich nicht weiß ob der überhaupt notwendig ist.)

Damit ich nicht nur ein Item, sondern auch schon einen Benutzbaren Gegenstand habe, habe ich eine weitere Klasse "Weapon" erstellt und diese von "Item" erben lassen.

 

Soweit so gut. Jetzt möchte ich aber erst einmal überhaupt testen was ich gemacht habe und habe ein einfaches Script geschrieben, dass nur den Konstruktor aufruft, ein Objekt (Ich glaube Objekt ist hier das falsche Wort aber ihr wisst was ich meine) von meiner Klasse erstellt und dieses Objekt in einer Liste speichert. Die Klasse wird ohne Probleme erstellt und ich kann auch darauf zugreifen. Was allerdings nicht funktioniert ist, dass meine Klasse nicht in der Liste gespeichert wird. (Egal ob die Liste nun eine List<Weapon>() oder eine List<Item>() ist). Die Liste Taucht bei mir noch nicht einmal im Inspector auf.

Da ich nicht genau weiß was ich euch geben soll hier einfach mal das Script um meine Klasse zu erstellen und sie abzuspeichern und die Werte auslesen:

 

[CreateAssetMenu(fileName = "ItemDatabase", menuName = "ScriptableObject/Item/ItemDatabase")]
public class ItemDatabase : ScriptableObject
{
    public List<Item> Database = new List<Item>(1);

    public Item it;


    public void GenerateNewWeapon()
    {
        Item weaponTest = new Item();

        Debug.Log(weaponTest.health);  // Wird wie gewünscht aufgerufen

        Database[0] = weaponTest;

        Debug.Log(Database[0].health); // Wird nicht aufgerufen

        /*System.ThrowHelper.ThrowArgumentOutOfRangeException () (at <eae584ce26bc40229c1b1aa476bfa589>:0)
		System.Collections.Generic.List`1[T].set_Item (System.Int32 index, T value) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
		ItemDatabase.GenerateNewWeapon () (at Assets/Scripts/Inventar/ItemDatabase.cs:29)
		Test.Start () (at Assets/Scripts/Inventar/Test.cs:11) */
    }
}

Wenn ihr noch irgendwelche Script sehen wollt. Fragt einfach ;)

Danke schon mal im voraus.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Listen haben keine feste Größe. Wenn du da eine 1 reinschiebst, dann wird damit die Kapazität auf 1 gesetzt, aber die Liste hat immer noch eine Länge von 0. Deshalb kannst du auch nicht auf Database[0] zugreifen. Um einer Liste ein Element hinzuzufügen, einfach Add(item) benutzen.

Die Liste taucht nur im Inspektor auf, wenn der Typ der Liste (hier "Item") serialisierbar ist. Serialisierbar sind:

  • Primitive Datentypen wie int oder float
  • UnityEngine.Objects (wie GameObject, Component oder ScriptableObject)
  • Klassen und Structs, die als serialisierbar markiert sind

Letzteres geht so:

[System.Serializable]
public class Item
{

Bei den primitiven Datentypen kommt einfach ein Eingabefeld, bei UnityEngine.Objects kommt ein Feld zum Reinziehen und bei als serialierbar markierten Klassen und Structs kommt so ein Foldout-Pfeil, den man ausklappen kann und dann werden die serialisierbaren Eigenschaften des Objekts angezeigt. In diesem Fall ist das Objekt für den Serializer Teil des Besitzer-Objekts und kann nicht null sein. Ob das für Inventar-Items sinnvoll ist, kommt natürlich wieder darauf an, was das Gamedesign so vorsieht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Mhhh... jetzt hätte ich doch nochmal eine kleine Frage zu dem Thema. Meine Gegenstände erben alle von der Klasse "Item" egal ob es ein Waffe, eine Rüstung oder sonst irgendetwas.

Problem ist jetzt allerdings dass ich keine Liste (List<Item> invetory) erstellen kann, in der Items jeder Art ablegen kann. Zwar geht meine Waffe da hinein aber zum einen bekomme ich nur die Grundwerte für Items angezeigt und wenn ich sie heraus nehme können sie nicht in z.B Waffe abgespeichert werden weil es ja nur ein Item ist.

Wenn ich eine Liste (List<Weapon> inventory) erstelle, kann ich logischerweise nur Klassen des Typs Weapon ablegen.

Gibt es nun eine Möglichkeit der Liste zu sagen sie soll Items und alle Klassen, die von Item geerbt haben abspeichern?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Da hast du tatsächlich einen Schwachpunkt an Unitys Serializer gefunden. Er kann tatsächlich keine Subtypen serialisieren. Wenn du eine List<T> oder ein Array T[] hast, dann werden da x Objekte vom Typ T serialisiert. Kann sein, dass der Odin Serializer das besser macht, aber ob man da eine Dependency aufbauen möchte, ist halt Geschmackssache.

Wenn du Vererbung in serialisierten Objekten haben willst, dann müssen das UnityEngine.Objects sein, weil diese dann vom Serializer nicht als Teil eines anderen Objekts gewertet werden, sondern als eigene Instanz. Und die haben dann eine Info, von welcher Klasse sie Instanzen sind. Dann kannst du Referenzen darauf auch ganz normal in eine Kollektion ihrer Superklasse serialisieren lassen, aber sie "leben" dann eigenständig und nicht in der Liste. Ist alles ein bisschen nervig, gar keine Frage.

Was du machen kannst ist z.B. ScriptableObjects zu erstellen. Das würde schon reichen. Wenn du die aber nicht in den Assets rumfliegen haben willst, dann kannst du sie einem anderen ScriptableObject unterordnen. Das geht mit AssetDatabase.AddObjectToAsset. Ist initial ein bisschen Fummelkram. Dann kann man halt die untergeordneten Assets selektieren und der Inspektor zeigt die an. Man kann dann bestimmt auch mit PropertyDrawer-Magie machen, dass die Listenelemente direkt unterschiedlich aussehen. Wird aber ein bisschen wild, alles.

Falls dir das alles Kopfschmerzen bereitet... herzlich Willkommen in der Welt der professionellen Entwicklung mit Unity. Du hast das Einsteiger- und das Fortgeschrittenen-Level mit diesem Thema definitiv hinter dir gelassen und die damit verbundenen Schmerzen sind normal :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Singular reached Level 3!

okay, dann hab ich sogar soweit alles richtig gemacht. Weil ich keinen Weg gefunden habe, habe ich jetzt mehrere Listen erstellt wollte aber nochmal nachhaken ob es einen einfacheren Weg gibt. Über SO habe ich auch nachgedacht aber wenn du sagst, dass das auch Fummelarbeit ist (ist meins auch keine Frage) dann liegt die Wahl irgendwo zwischen Pest und Corona...

Danke dir 😊

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...