Blueprintinterfaces Grundlagen mit Beispielen

Grundlage für dieses Tutorial

Grundlage für dieses Tutorial ist in diesem Fall eine Hitresult, welches in meinem Beispiel im Playercharacter abgefragt wird. Dies kann natürlich bei anderen Projekten variieren.


Darum nicht "Cast To ..."

Es funktioniert zwar. Nehmen wir an, wir haben einen Actor, der beinhaltet wiederum ein Custom Event, welches wir auslösen wollen und im Player Controller greifen wir dann über "Cast To ..." auf das Event zu. Nehmen wir einen einfachen Actor und setzen in den Event Graph einfach ein Custom Event. Jetzt nehmen wir einfach mal an, dieser Actor ist eine Tür und benennen ihn in "BP_Interactor_Door". Das CustomEvent nennen wir einfach mal "CastToEvent". Und damit man den Actor im Level auch sehen kann, einfach einen Cube reinpacken.



Print String ist jetzt nur ein Beispiel für Code, der dann folgen könnte. Bei einer Tür wäre es dann wahrscheinlich die Animation, wo die Tür geöffnet wird und etwas knarrt oder so.

Im Playercharacter sieht es dann wie folgt aus.

Wenn man den Würfel nun im Level platziert, das Spiel startet, dann sollte jedes Mal, wenn man den Würfel anklickt, die Nachricht "Actor Door wurde geklickt" angezeigt werden. Also, funktioniert.


Aber ... Was ist jedoch, wenn wir mehrere Actoren haben, die unterschiedliche Ausführungen bei einer Interaction haben?


Kopieren wir den Testactor doch einfach noch zweimal und benennen eine Kopie in Button und einen in Window um. In den Kopien ändern wir natürlich auch die Textnachricht, einmal in Button geklickt, einmal Window. Jetzt platzieren wir die anderen beiden Actoren im Level und starten das Spiel wiederum. Wenn wir jetzt versuchen, die beiden anderen Würfel anzuklicken, passiert ... nichts.


Was müssten wir also auch noch ändern? Ganz klar, die Hitabfrage im Playercharakter.

Jetzt funktioniert es wieder. Allerdings. Jeder kann sich vorstellen. Wenn der Level so 10, 20 oder gar 100 interaktive Actoren hat, dann wird das sehr schnell unübersichtlich und vor allem fehleranfällig.


Die Lösung hierfür sind Blueprintinterfaces

Ein Interface erstellt man per Rechtsklick über das Submenü.

Am besten ist, und das gilt generell bei der Arbeit mit der Unreal Engine, man überlegt sich ein Namensumgebungskonzept für die Dateien. Zum Beispiel nehme ich für Blueprints immer das Kürzel BP_[Name]. Bei Blueprintinterfaces nehme ich die Bezeichnung BPI_[Name] In diesem Fall legen wir einfach mal ein Blueprintinterface an und benennen es BPI_Interaction.


Der Aufbau:

Wenn wir dieses Interface dann öffnen, erscheint eine Oberfläche, die man in 4 Teile aufteilen kann.

1: Hier gibt es den Button, um Funktionen hinzuzufügen, diese zu benennen und wo vorhandene Funktionen aufgelistet werden.

2: Hier können Angaben gemacht werden, um die Funktionen zu kategorisieren und weitere Informationen hinzuzufügen.

3: Wie bei gewöhnlichen Funktionen auch, können hier Inputs und Outputs hinzugefügt werden.

4: Hier wird die BP-Struktur der Funktion angezeigt, was hier aber relativ unwichtig ist, da es nur Read Only ist und man daran nichts ändern kann. (Jap, das gehört so)


Einfügen von Funktionen:

Benennen wir die erste Funktion, welche automatisch vorgegeben wurde (New Funktion), einfach mal um in "OnInteraction".

Das war es dann erstmal auch schon, für das Beispiel brauchen wir keine weiteren Inputs oder Outputs, somit können wir die BPI Compilieren, Speicher.

Integration in den Actor:

Weitermachen müssen wir nun bei den Actoren, welche die Interaktion empfangen sollen. In diesem Tutorial also Door, Window und Button.
Öffnen wir diese also und gehen oben in der Leiste des Actors auf "Calss Settings".

Unter Details habt ihr jetzt einen Kategoriepunkt namens Interfaces. In diesem gibt es ein Combomenü "Add". Hier könnt ihr dann euer Interface "BPI_Interaction" auswählen und fügt so das Interface dem Actor hinzu.


Solltet ihr alles richtig gemacht haben, findet ihr unter "My Blueprint", wo man sonst auch Variablen, Event Dispatcher usw. hinzufügen kann, eine zusätzliche Kategorie Interfaces und in der sollte auch die bereits angelegte Funktion "On Interaction" vorhanden sein.

Die Farbe des Symbols zeigt übrigens an, dass beim Einfügen in das BP des Actors diese Funktion als Event eingefügt wird. Es gibt noch Zuweisungsfunktionen, dies ist automatisch der Fall, wenn ihr im Interface eine Funktion mit Outputvariable erstellt.


Wechseln wir nun in den Event Graph und doppelklicken einfach auf "On Interraction". Jetzt wird automatisch ein Event in den Event Graph eingefügt. Hier gilt dasselbe wie beim Aufruf durch "Cast To". Hier wird dann der Code eingefügt, der zum Beispiel die Tür bewegen soll, was passieren soll, wenn das Fenster ausgewählt wird oder der Button gedrückt wird. In diesem Fall, einfach nur der Text über Print String "Actor ... wurde geklickt" wobei bei ... dann halt wieder steht, Door, Window oder Button, damit man es auch unterscheiden kann. An dem Symbol oben rechts in der Ecke des Events könnt ihr auch erkennen, dass es sich um ein Event aus einem Interface handelt.

Das Einfügen des Interfaces und des Events müsst ihr selbstverständlich in jedem Actor einfügen, mit welchem ihr interagieren wollt.


Aufrufen der Interfacefunktionen:

Jetzt müssen wir nur noch die Abfrage hinter dem "Hit Result" ändern.

Hierzu ziehen wir wieder aus dem "Hit Actor" raus und suchen nach "OnInteraction". Ihr solltet nun in der Liste unter der Kategorie "BPI_Interaction" folgenden Punkt finden.

An "(Message)" erkennt ihr auch den richtigen Eintrag. Am Ende sollte es wie folgt aussehen:


Das war es dann auch. Mehr ist nicht nötig. Oben rechts seht ihr einen Briefumschlag, das bedeutet, dass die Interfacefunktion aufgerufen wird. Wenn ihr das Programm jetzt startet, sollte alles genau so funktionieren, wie vorher auch mit den vielen "Cast To"


Fazit:

Noch einmal zum Vergleich Cast To gegen Interface:



Und vergesst nicht, in dem Beispiel sind nur drei Aktoren, mit denen man interagieren kann. Bei Cast To würde die Abfrage immer größer werden, mit jedem weiteren Actor, beim Interface bleibt es immer so. Auch wenn ihr weitere Actoren hinzufügt, Spawned oder was auch immer, ihr braucht nie wieder etwas ändern, es sei denn, ihr verändert etwas direkt im Interface, was hier abgerufen oder abgefragt werden muss.


Bedingte Interaction:

Ganz einfach kann man hier auch eine Interaktion realisieren, die an bestimmte Bedingungen geknüpft ist. Z, B. würde sich hier anbieten, dass eine bestimmte Quest erfüllt ist oder ähnliches. Hierzu müssen wir BPI_Interaction ein wenig erweitern, indem wir eine weitere Funktion hinzufügen. Diese nennen wir einfach mal "IsInteractable".

Bei dieser Funktion fügen wir nun ein Output vom Typ Boolean hinzu.


Das war es im BPI_Interaction auch schon wieder. Nicht das Compilieren und Speichern vergessen.


Die nächsten Änderungen finden im Actor statt. Hier hat sich unter der Kategorie "Interfaces" die neue Funktion hinzugefügt.

An der Färbung erkennt man hier, dass es sich nicht um ein Event handelt. Mit einem Doppelklick öffnen wir diese Funktion. Um diese etwas flexibler zu nutzen, legen wir noch eine Variable vom Typ Boolean an, nennen diese "CanInteracted" und machen diese sichtbar. Vorzugsweise würde ich die Variable auf default true stellen.

Diese Variable nutzen wir jetzt am Ausgang der neuen Funktion "IsInteractable".

Das war es. Auch hier nicht vergessen zu compilieren und zu speichern.


Als Nächstes müssen wir in diesem Fall tatsächlich etwas hinter dem Hit Result ändern. Wir müssen jetzt abfragen, ob der Actor Interactable ist oder nicht. Das geht wie folgt.

Wir ziehen wieder aus "Hit Actor" entsprechende Funktion heraus, genauso wie wir es bereits bei "OnInteraction" gemacht haben. Wichtig ist auch hier, dass ihr darauf achtet, dass es sich um die Funktion aus dem "BPI_Interaction" handelt inkl. (Message). Diese verbinden wir dann mit einem "Branch" und danach das "OnInteraction" auf die True-Verzweigung. Sieht am Ende so aus.


Wenn ihr nun alles richtig gemacht und compiliert habt, inkl. dass die Variable im Actor auf true gestellt ist, sollte die Interaktion nun wieder möglich sein.

Stellt ihr sie in den Detaileinstellungen auf false, sollte es jetzt nicht mehr interagieren.


Bitte denkt daran, dass jetzt jeder Actor mit diesem Interface diese Funktion auf true stellen muss, weil sonst passiert halt gar nichts.

Weitere Praxisbezogene Beispiele werden folgen:

Kommentare