Diese Funktion befindet sich noch im experimentellen Zustand, sodass du sie ausprobieren, Feedback geben und sehen kannst, was wir planen. Du kannst derzeit kein Projekt veröffentlichen, das benutzerdefinierte Inventare und Gegenstände verwendet.
Beachte, dass wir für Assets, die mit dem Status „Experimentell“ erstellt wurden, keine Abwärtskompatibilität garantieren können, dass die APIs für diese Funktionen Änderungen unterliegen und dass wir uns vorbehalten, ganze experimentelle Funktionen oder bestimmte Funktionalität nach unserem Ermessen zu entfernen. Sieh dir die Liste bekannter Probleme an, bevor du mit der Funktion arbeitest.
In diesem Tutorial erfährst du, wie du eine benutzerdefinierte interaktionsfähige Komponente für die Gegenstandsaufnahme erstellst, mit der Spieler benutzerdefinierte Gegenstände aufheben können, und die den aufgenommenen Gegenstand dem Inventar des Spielers hinzufügt.
Bevor du anfängst
Du solltest mit UEFN, Scene Graph und Verse-Code vertraut sein, um dieses Tutorial erfolgreich abzuschließen.
Dein Projekt einrichten
Befolge diese Schritte, um dein Projekt einzurichten und benutzerdefiniertes Inventar und Gegenstände zu aktivieren.
Öffne UEFN und erstelle ein Projekt aus einer beliebigen Inselvorlage. In Inselvorlagen kannst du das Leer-Projekt verwenden, wenn du mit einem flachen Gebiet arbeiten möchtest. Benenne dein neues Projekt und klicke auf „Erstellen“, um es im Editor zu öffnen.
Klicke in der Symbolleiste auf Projekt und wähle Projekt-Einstellungen.
Scrolle nach unten zum Abschnitt Experimenteller Zugriff und aktiviere das Kontrollkästchen für Benutzerdefinierte Gegenstände und Inventar.
Schreiben von Verse-Code
Die interactable_component ist eine Scene-Graph-Komponente, die zur allgemeinen Interaktion verwendet wird. Standardmäßig können Spieler eine Eingabe drücken, um mit einer Entität zu interagieren, die die Komponente besitzt. Befolge diese Schritte, um diese Komponente anzupassen.
Eine interactable_component erfordert, dass eine Entität eine mesh_component besitzt, damit sie mit ihr interagieren kann. Das Objekt muss eine Kollision aufweisen, gegen die geprüft werden kann, wenn etwas versucht, mit der Entität zu interagieren.
Wähle die Entität aus, zu der du die benutzerdefinierte interaktive Komponente hinzufügen möchtest. Klicke im Details-Panel auf „+Komponente“ und wähle „Neue Verse-Komponente“ aus. Das Fenster „Verse-Komponente erstellen“ wird geöffnet.
Du kannst auch eine Verse-Komponente erstellen, indem du eine neue Verse-Datei mit dem Verse-Explorer hinzufügst.
Wähle unter Vorlage auswählen die Option Scene-Graph-Komponente aus.
Gib unten im Feld Komponentenname „item_interactable_component“ ein. Klicke anschließend auf „Erstellen“.
Klicke in der Menüleiste auf Verse > Verse-Explorer. Suche deine neue Verse-Komponente, klicke mit der rechten Maustaste darauf und wähle In Visual Studio Code öffnen.
Lösche in der neuen Verse-Datei den vorhandenen Code, da du in diesem Tutorial alles neu schreiben wirst. Füge zuerst die erforderlichen Module hinzu. Du kannst sie aus dem folgenden Ausschnitt kopieren und einfügen.
Verseusing { /Verse.org/Simulation } using { /Verse.org/SceneGraph } using { /UnrealEngine.com/Itemization }Füge als Nächstes eine Hilfsfunktion hinzu, um das Stamminventar eines bestimmten Spielers abzurufen.
VerseGetInventoryRoot(Agent:agent)<decides><transacts>:inventory_component = Inventory := (for (I : Agent.FindDescendantComponents(inventory_component)) { I })[0]Bevor du die neue benutzerdefinierte Komponente erstellst, musst du eine neue Nachrichtentyp-Konstante deklarieren, die außerhalb des Geltungsbereichs unserer Klasse liegt. Diese Meldung ist der Standardwert, wenn die Funktion keinen Namen aus der
item_details_componenteines Gegenstands abrufen kann. Normalerweise wird dieser Meldungstyp ganz unten in die Verse-Datei geschrieben.VerseDefaultInteractionMessage<localizes>:message = "Interact"Definiere einen neuen Scene Graph, der von
interactable_componenterbt. Dies ist dieitem_interactable_component.Verseitem_interactable_component := class(interactable_component) :Füge eine optionale
abbrechbareVariable hinzu. Diese benutzerdefinierte Komponente muss ein Event abonnieren, um zu wissen, wann ein Spieler mit dem Gegenstand interagiert. Diese Variable speichert einen Verweis auf dieses Abonnement und hebt es bei Bedarf auf.Versevar SucceededEventHandler : ?cancelable = falseSetze als Nächstes die Funktion
OnAddedToSceneaußer Kraft, sodass sie die optionale Variable setzt, wenn sich das Parent-Element der Entität, die diese Komponente besitzt, ändert (z. B. wenn sie in der Welt platziert wird). LegeSucceededEventHandlerfest, um die Abonnieren-Funktion aufSucceededEventaufzurufen. Dadurch wird auch die FunktionOnSucceededEventdefiniert, sodass sie ausgelöst wird, wenn eine Interaktion stattfindet.VerseOnAddedToScene<override>():void = if(not SucceededEventHandler?): set SucceededEventHandler = option{SucceededEvent.Subscribe(OnSucceededEvent)}Das
SucceededEvent-Abonnement muss bereinigt werden, sobald ein Gegenstand aufgehoben wurde, da es sonst anderen Code behindern könnte, sobald sich der Gegenstand im Inventar befindet. You – Du wirst mich lieben Hierfür kann die FunktionOnRemovingFromSceneüberschrieben werden. Diese wird aktiviert, wenn sich der Parent der Element-Entität ändert. Verwende es hier, umcancel()für das Event-Abonnement auszuführen. Wenn dies erfolgreich ist, wirdSucceededEventHandlerebenfalls ungültig.VerseOnRemovingFromScene<override>():void = if(SucceededEventHandler?.Cancel()): set SucceededEventHandler = falseIn Schritt 10 wird die Funktion
OnSucceededEventfürSucceededEventabonniert, aber sie existiert noch nicht im Code. Du musst also eine neue Funktion mit der gleichen Signatur schreiben. In Schritt 6 hast du die HilfsfunktionGetInventoryRoot[]verwendet, um das Stamminventar des interagierenden Spielers abzurufen. Rufe jetzt die FunktionAddItemDistribute()auf, um die Entität bereitzustellen, die diese Komponente besitzt.VerseOnSucceededEvent(Agent:agent):void = if(PickupInventory := GetInventoryRoot[Agent]): if(PickupInventory.AddItemDistribute(Entity).GetSuccess[]):Das letzte bisschen Code, das für diese Komponente benötigt wird, ist das Außerkraftsetzen der Funktion
InteractMessage[]. Diese gibt die Meldung zurück, die auf dem Bildschirm angezeigt wird, wenn ein Spieler sich den Gegenstand ansieht, bevor er ihn aufhebt. Dadurch wird die Entität, die diese Komponente besitzt, überprüft, um zu sehen, ob sie auch eineitem_details_componenthat. Ist dies der Fall, wird der Name des Gegenstands abgerufen. Wenn die Entität andernfalls keineitem_details_componenthatte oder sie aus irgendwelchen Gründen entfernt wurde, wird dieDefaultInteractionMessageverwendet, die wir zuvor deklariert haben.VerseInteractMessage<override>(Agent:agent)<reads><decides>:message = if(Details := Entity.GetComponent[item_details_component]): Details.Name else: DefaultInteractionMessage
Einrichten des Prefab
Nachdem du nun deine item_interactable_component geschrieben hast, kannst du einen Beispielgegenstand erstellen, um sie zu präsentieren. Befolge diese Schritte, um ein Scene Graph-Prefab zu erstellen und die neue Komponente anzuhängen.
Klicke mit der rechten Maustaste im Inhaltsbrowser und wähle im Kontextmenü Entität-Prefab-Definition aus. Nenne das neue Prefab Item_Cube.
Öffne das neue Prefab und füge die folgenden Komponenten hinzu, indem du im Details-Panel auf +Komponente klickst.
item_componentitem_details_component: Fülle die Felder dieser Komponente aus:Name
Beschreibung
Kurze Beschreibung
mesh_component: Wähle den Würfel-Grundkörper oder einen anderen Würfel aus.item_interactable_component
Das folgende Video zeigt die item_interactable_component in Aktion. Wenn der Spieler mit dem von dir erstellten Item_Cube-Prefab interagiert, wird der Gegenstand dem Inventar des Spielers hinzugefügt.
Hier findest du das komplette Script für dieses Tutorial.
using { /Verse.org/Simulation }
using { /Verse.org/SceneGraph }
using { /UnrealEngine.com/Itemization }
# This function returns the first subentity with an inventory_component. Use this to get the root inventory of an agent.
GetInventoryRoot(Agent:agent)<decides><transacts>:inventory_component =
Inventory := (for (I : Agent.FindDescendantComponents(inventory_component)) { I })[0]