Jump to content
Unity Insider Forum
Thariel

Lokales ref Objekt oder eine elegante Möglichkeit, wie zwei Script zeitgleich das selbe Objekt verwenden

Recommended Posts

Hi

Suche eine elegante Lösung für folgendes Problem (schwierig zu erklären):

  • Der Spieler kann viele verschiedene Strukturen bauen und jede Struktur hat ein eigenes Script mit einer eigenen Logik (AnimalTrap.cs, Campfire.cs, ...).
  • Jede Struktur hat auch ein passendes UI Fenster, das geöffnet wird, wenn der Spieler [E] drückt (WndAnimalTrap.cs, WndCampfire.cs, ...).
  • Die UI Fenster haben verschiedene Slots, in die der Spieler Items  vom Inventar setzen kann. Dies ist immer das selbe Script (SlotScript.cs).
  • Die Haupt-Scripte mit der Logik (AnimalTrap.cs, Campfire.cs, ...) nutzen diese Items.

Das Problem:

  • Wenn ein Spieler ein Item vom Inventar auf ein Slot zieht, enthält der Slot das Item.
  • Das Item wird also zerstört, wenn der Spieler das Fenster wieder schliesst, es muss aber vorhanden bleiben, weil das Haupt-Script mit der Logik (AnimalTrap.cs, Campfire.cs, ...) das Item verwendet (z.B. in AnimalTrap.cs wird ein Item als Köder benutzt), auch wenn das Fenster geschlossen wurde.
  • Das Item soll aber auch vom Haupt-Script verwendet werden, wenn das Fenster geöffnet ist.

Also:

  • AnimalTrap.cs existiert immer und liegt auf dem GameObject.
  • WndAnimalTrap.cs existiert nur, wenn das Fenster geöffnet ist.
  • SlotItem.cs ist ein child von WndAnimalTrap.cs und kann mit einem Item (Köder) beladen werden.

[AnimalTrap.cs] <--[Item baitItem]-->[WndAnimalTrap.cs]<--[Item baitItem]-->[SlotScript.cs]

AnimalTrap.cs und SlotItem.cs müssen aber gleichzeitig auf das Item (baitItem) zugreifen können. AnimalTrap.cs berechnet dauernd die Haltbarkeit des Köders und wie viel TIere gefangen werden, EGAL ob das Fenster geöffnet ist oder nicht.

Am einfachsten wäre es, wenn ich beim öffnen des Fenster einfach das Item mit ref übergeben könnte und SlotItem.cs ändert dann direkt das Item in AnimalTrap.cs, aber das geht ja leider nicht (.net v4.0 unterstützt das nicht).

Versteht jemand, was ich meine? Ist etwas schwer zu erklären und mir fällt wirklich keine "elegante" Lösung ein.

PS: Oder ganz einfach erklärt, SlotScript.cs soll eine variable in einem anderen Script manipulieren, ohne dass es dieses kennt. Erst beim erstellen kann dieses Scipt irgendwie übergeben werden.

Share this post


Link to post
Share on other sites

Hi

Da die Strukturen etwas gemeinsam haben (Slots) empfiehlt es sich ein Interface und/oder eine Basisklasse einzuführen, welche die Slot-Logik beschreibt, z.B.:

public interface IItemSlotContainer
{
  IEnumerable<string> GetSlots();
  IEnumerable<Item> GetItems();
  Item GetSlotItem(string slotName);
  void SetSlotItem(string slotName, Item item);
  void CopySlotItems(IItemSlotContainer targetContainer);
}

Das Fenster selber könnte genau das gleiche Interface auch implementieren, und dann die Methode CopySlotItems verwenden, um die Items in das Ziel (Struktur) zu übertragen oder die Items von der Struktur zu laden, wenn das Fenster geöffnet wird. Alles was dann noch benötigt wird ist eine Referenz im Fenster auf die entsprechende Struktur, z.B.:

public class WndAnimalTrap : MonoBehaviour, IItemSlotContainer
{
  public IItemSlotContainer targetContainer;

  void OnWindowShow()
  {
    targetContainer.CopySlotItems(this);
  }
  
  void OnWindowClosing()
  {
    CopySlotItems(targetContainer);
  }
}

Wichtig dabei ist, dass die Items nicht an ein GameObject gebunden sein sollten, das heisst einfach normale C#-Klassen verwenden oder von ScriptableObject erben. Natürlich braucht es für die Darstellung der Items im GUI GameObjects. Aber diese könnten ja wiederum auf ein Item-Objekt verweisen, welches unabhängig vom GameObject ist und nur im RAM gehalten wird.

Share this post


Link to post
Share on other sites

Ich vermute das das Item Objekt ist ein struct?  

Entweder du machst Item zu einem reference object, oder du musst dir ein anderes Konzept einfallen lassen.

Share this post


Link to post
Share on other sites

Danke für die Antworten.

Habe jetzt eine Lösung gefunden, die elegant genug ist und auch noch andere Vorteile bietet.

Habe das SlotScript.cs in UiSlotScript.cs umbenannt und ein neues Script SlotScript.cs erstellt, sowie alle public Variablen und das Item Objekt hinein verschoben und es liegt jetzt direkt auf dem GameObject neben AnimalTrap.cs, welche eine Referenz darauf hat. Jetzt kann ich also den Slot direkt im GameObject Einstellen und brauche jetzt nicht mal mehr für jede ähnliche Struktur ein neues UiWindow, weil ich alles in der Struktur selbst Einstelle. Beim öffnen des Fensters übergebe ich dann einfach das Script selbst (Wnd.Show(this)) und das UiSlotScript nutzt einfach die Variablen von SlotScript.cs.

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

×