Scene Graph bietet mehrere Möglichkeiten, um durch die vielen verschiedenen Interaktionen zwischen Entitäten und Komponenten ein flexibles und dynamisches Gameplay zu erstellen. Diese Vorlage zeigt einige Möglichkeiten, wie du Entitäten zur Laufzeit manipulieren kannst, indem du Entitäten spawnst und entfernst, und wie du Komponente-Events und Abfragen nutzen kannst, um eine Kommunikation zwischen Entitäten herzustellen und wiederverwendbare Gameplay-Elemente zu erstellen.
Erstellen und Entfernen von Prefabs
Sieh dir zum Beispiel die interaktive Fläche in der zweiten Diele an. Wenn der Spieler auf die Fläche tritt, wird eine Prefab-Laterne zur Szene hinzugefügt und entfernt, wenn der Spieler die Fläche verlässt.
Öffne SpawnPrefabDevice.verse, um zu sehen, wie dieser Code funktioniert. Dies ist ein Kreativmodus-Gerät, das ein Volumen-Gerät verwendet, um zu wissen, wann ein Spieler es betritt. Es erzeugt dann ein Prefab und entfernt es, wenn der Spieler den Trigger verlässt. Anfang der SpawnPrefabDevice-Klassendefinition verweist ein bearbeitbares TriggerVolume auf das Triggervolumen im Level.
SpawnPrefabDevice := class(creative_device):
@editable
TriggerVolume:volume_device = volume_device{}Wenn das Spiel beginnt, definiert das Gerät ein neues Lichtpfosten-Prefab, das gespawnt werden soll, sowie die Position, an der es spawnen soll.
OnBegin<override>()<suspends>:void =
PrefabToSpawn:entity = LightPost.P_LightPost{}
SpawnTransform:transform = transform:
Translation := vector3:
Left := -9084.0
Up := -8.0
Forward := -919.0Es holt dann die simulation entity ab und erzeugt eine Reihe von Fehlerkontexten, in denen es arbeiten kann. Zuerst wird eine Schleife verwendet, um den Code darin wiederholt auszuführen, dann folgt ein Race-Ausdruck zwischen zwei Block-Anweisungen.
if:
SimulationEntity := GetSimulationEntity[]
then:
loop:
race:
block:
TriggerVolume.AgentEntersEvent.Await()
SimulationEntity.AddEntities(array{ PrefabToSpawn })
PrefabToSpawn.SetGlobalTransform(SpawnTransform)
Die erste Block-Anweisung wartet darauf, dass ein Agent das Bereich-Gerät betritt. Wenn das der Fall ist, wird das Laternen-Prefab mit AddEntities() zur Szene hinzugefügt und mit SetGlobalTransform() korrekt positioniert. Der zweite Block wartet darauf, dass der Agent das Volumen verlässt und das Prefab aus seinem Parent, in diesem Fall der simulation entity, entfernt.
Da diese Blöcke in einer Schleife gegeneinander antreten, läuft jeder von ihnen immer, sodass der Spieler das Volumen betreten und verlassen kann, um den Lichtpfahl beliebig oft zu respawnen!
Vollständiges Script
Im Folgenden findest du die Schritte zum Hinzufügen und Entfernen einer Entität aus der Szene.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/SceneGraph }
using { /Verse.org/SpatialMath }
using { /UnrealEngine.com/Temporary/Diagnostics }
SpawnPrefabDevice := class(creative_device):
Entitätsüberschneidungen
Der zweite Raum hat ebenfalls eine Reihe von Beispielen, die einige der verschiedenen Möglichkeiten zeigen, mit denen Entitäten interagieren können. Beispielsweise können Entitäten mit einer Mesh-Komponente durch das EntityEnteredEvent und EntityExitedEvent der Mesh-Komponente alarmiert werden, wenn sie sich mit einer anderen Entität überschneiden. Schaut euch das UFO-Beispiel im zweiten Raum an, um diese Funktionalität in Aktion zu sehen.
Wenn das Spiel beginnt, spielt die Kuh eine Animation ab, um sich aufzuheben, als würde sie vom UFO entführt. Die Kuh nutzt das EntityEnteredEvent der Mesh-Komponente, um zu wissen, wann sie sich mit dem UFO überlappt, und macht sich dann unsichtbar, um zu erscheinen, als wäre sie entführt worden.
Der Code für dieses Beispiel ist in EntityEnteredExampleComponent.verse definiert. Öffne diese Datei aus dem Verse-Explorer.
Die Klasse entities_entered_example_component definiert zunächst ein bearbeitbares Keyframes-Array, aus dem die Kuhentführung-Animation erstellt werden soll. Sie definiert auch eine StartTransform-Variable, um die Startposition der Kuh in der Szene anzugeben.
entity_entered_example_component<public> := class<final_super>(component):
@editable
Keyframes:[]keyframed_movement_delta = array{}
var StartTransform:transform = transform{}In OnBeginSimulation(), beginnt das Script mit dem Abrufen des fort_round_manager. Dies ist ein Interface zum Fortnite-Rundenmanager, mit dem du Events für den Beginn und das Ende einer Runde abonnieren kannst. In diesem Beispiel abonniert das Script die Funktion OnRoundStarted() für den Start der Runde mit SubscribeRoundStarted(), was bedeutet, dass die Funktion nur ausgeführt wird, wenn das Spiel beginnt, und nicht, wenn die Entität mit der Simulation beginnt.
OnBeginSimulation<override>():void =
(super:)OnBeginSimulation()
if:
FortRoundManager := Entity.GetFortRoundManager[]
then:
FortRoundManager.SubscribeRoundStarted(OnRoundStarted)Dann beginnt das Script in OnRoundStarted() mit dem Setzen von StartTransform auf die globale Transformation der Entität und dem Abonnieren des EntityEnteredEvent der Mesh-Komponente für eine neue Funktion OnEntityEntered(), die ausgelöst wird, wenn ein anderes Mesh sich mit der Entität überschneidet. Es spawnt dann eine PlayCowAbductionAnimation()-Funktion, um mit dem Aufheben der Kuh zu beginnen.
OnRoundStarted():void =
set StartTransform = Entity.GetGlobalTransform()
if:
Mesh := Entity.GetComponent[mesh_component]
then:
Mesh.EntityEnteredEvent.Subscribe(OnEntityEntered)
spawn { PlayCowAbdcutionAnimation() }Die Funktion PlayCowAbductionAnimation() setzt einfach die globale Transformieren der Kuh auf ihre Starttransformation und wartet einen kurzen Zeitraum. Es holt dann die Mesh- und Keyframe-Komponenten von der Entität, aktiviert das Mesh, um die Kuh sichtbar zu machen, setzt dann die Animation auf der Keyframe-Komponente und spielt sie ab.
PlayCowAbdcutionAnimation()<suspends>:void =
Entity.SetGlobalTransform(StartTransform)
Sleep(2.0)
if:
Mesh := Entity.GetComponent[mesh_component]
MovementComponent := Entity.GetComponent[keyframed_movement_component]
then:
set Mesh.Visible = true
MovementComponent.SetKeyframes(Keyframes, oneshot_keyframed_movement_playback_mode{})
MovementComponent.Play()Schließlich wird mit der Funktion OnEntityEntered() Code immer dann ausgeführt, wenn die Kuh eine andere Entität, in diesem Fall das UFO, überlappt. Wenn das der Fall ist, holt es wieder das Mesh und die mit Keyframes erstellten Bewegungskomponenten ab, verwendet sie aber stattdessen, um die Wiedergabe aller laufenden Animationen zu stoppen und die Kuh unsichtbar zu machen, als wäre sie entführt worden. Es spawnt dann eine neue Instanz von PlayCowAbductionAnimation(), um den Prozess von vorne zu beginnen.
OnEntityEntered(OtherEntity:entity):void =
if:
Mesh := Entity.GetComponent[mesh_component]
MovementComponent := Entity.GetComponent[keyframed_movement_component]
then:
MovementComponent.Stop()
set Mesh.Visible = false
spawn { PlayCowAbdcutionAnimation() }Vollständiges Script
Unten findest du das vollständige Skript zur Entführung eines Kuhnetzes mit einem UFO-Netz.
using { /Verse.org }
using { /Verse.org/Native }
using { /Verse.org/SceneGraph }
using { /Verse.org/Simulation }
using { /Verse.org/SceneGraph/KeyframedMovement }
using { /Verse.org/SpatialMath }
using { /Fortnite.com/Game }
entity_entered_example_component<public> := class<final_super>(component):
Abfragen von Überlappungstreffern
Entitäten können auch Abfragen für andere Entitäten durchführen, indem sie Überschneidungsabfragen verwenden. Anstatt zu erkennen, wann eine Entität ein bestimmtes Mesh betritt oder verlässt, können Überlappungsabfragen verwendet werden, um jede Entität und Komponente zurückzugeben, die einen bestimmten Gebiet überlappen.
Dieser Bereich kann entweder die Entität selbst sein, ein bestimmtes Kollisions-Volume, wie z. B. eine Kugel oder ein Kasten, oder eine Position, von der aus die Entität simuliert werden soll. Sie gibt dann eine Liste von overlap_hit zurück. Jeder overlap_hit gibt dir Informationen über die Komponente oder das Volume, das vom Quell-Volumen überlappt wird, und du kannst diese Komponenten abfragen, um ihre assoziierte Entität zu finden.
Versuche zum Beispiel, auf die interaktive Fläche vor dem FindOverlapHits-Beispiel zu treten. Wenn du mit der Fläche interagierst, spawnt das UFO ein unsichtbares Kollisionsvolumen und benutzt es, um eine Überlappungsabfrage durchzuführen. Wenn das Kollisionsvolumen die Kuh überlappt, entführt das UFO sie!
Der Code für dieses Beispiel ist in FindOverlapHitsExampleComponent.verse definiert. Öffne diese Datei aus dem Verse-Explorer.
Die Klasse beginnt mit der Definition eines bearbeitbaren Bereich-Geräts namens Trigger, um die interaktive Fläche zu referenzieren, auf die der Spieler tritt, sowie einer Logik variable IsAbducting, ob die Kuh entführt wird oder nicht. Wenn die Komponente mit der Simulation beginnt, abonniert sie die Funktion OnRoundStarted() auf den Rundenstart des Rundenmanagers. Die Funktion OnRoundStarted() abonniert in ähnlicher Weise einfach das AgentEntersEvent und das AgentExitsEvent vom Trigger zu den Funktionen OnTriggerEntered() bzw. OnTriggerExited().
find_overlaphits_example_component<public> := class<final_super>(component):
@editable
Trigger:volume_device = volume_device{}
var IsAbducting:logic = false
OnBeginSimulation<override>():void =
Wenn der Spieler auf die Fläche tritt und das UFO gerade keine Kuh entführt, wird die Funktion OnTriggerEntered() aufgerufen, um jede Bewegung, die das UFO möglicherweise ausführt, anzuhalten, indem seine keyframed_movement_component abgerufen und Pause() aufgerufen wird. Es ruft dann EnableAbductionBeam() und PerformOverlapCheck() auf, um den Abduction Strahl zu aktivieren und zu prüfen, ob sich die Kuh unter dem UFO befindet.
OnTriggerEntered(Agent:agent):void=
if:
not IsAbducting?
MovementComponent := Entity.GetComponent[keyframed_movement_component]
then:
MovementComponent.Pause()
EnableAbductionBeam()
PerformOverlapCheck()Die eigentliche Logik der Prüfung auf Überlappungen ist in der Funktion PerformOverlapCheck() gespeichert. Um einen Ableitungsstrahl zu simulieren, erzeugt diese Funktion eine Kollisionskapsel und definiert eine CollisionTransform, die direkt unter dem UFO gesetzt wird.
PerformOverlapCheck():void =
CollisionCapsule := collision_capsule{Radius := 36.0, Length := 328.0}
var CollisionTransform:transform = Entity.GetGlobalTransform()
set CollisionTransform.Translation.Up = CollisionTransform.Translation.Up - 248.0Als nächstes ruft die Funktion in einem for-Ausdruck FindOverlapHits() auf, um Komponenten oder Volumen zu suchen und zurückzugeben. Es übergibt die CollisionCapsule als Volumen, in dem auf Kollisionen geprüft werden soll, und die CollisionTransform als Ort, an dem diese Kollision simuliert werden soll. Es iteriert dann durch jede Überlappung und prüft, ob die überlappende Komponente eine Mesh-Komponente war, insbesondere das SM_Toy_Cow Mesh von der Kuh-Entität. Wenn dies der Fall ist, erzeugt sie eine AbductCow()-Funktion, die die zu entführende Kuh übergibt.
# Perform the overlap check from the entity that contains the mesh_component
for:
Overlap : Entity.FindOverlapHits(CollisionTransform, CollisionCapsule)
# Cast to see if what was overlapped was the Cow
CowMesh := Meshes.SM_Toy_Cow[Overlap.TargetComponent]
CowPrefab := CowMesh.Entity
do:
spawn { AbductCow(CowPrefab) }Um das Entführen der Kuh zu simulieren, baut die Entität eine Animation auf und spielt sie dann auf der Kuh-Entität ab, ähnlich wie im Beispiel „Entitätsüberlappung“ oben. Da dieser Code von der UFO-Entität und nicht von der Kuh-Entität aufgerufen wird, muss der Code Komponenten von der Kuh-Entität holen und dann eine Animation übergeben, damit sie abgespielt wird. Es beginnt mit dem Abrufen des Mesh und der mit Keyframes versehenen Bewegungskomponenten von der Kuh und setzt dann IsAbducting auf True.
AbductCow(CowEntity:entity)<suspends>:void =
# Get the components on the Cow Prefab
if:
CowMesh := CowEntity.GetComponent[mesh_component]
MovementComponent := CowEntity.GetComponent[keyframed_movement_component]
then:
set IsAbducting = trueDa die in der Kuhentführung-Animation verwendeten Keyframes nicht im Outliner festgelegt sind, muss der Code sie basierend auf der unterschiedlichen Position zwischen dem UFO und der Kuh erstellen. Dazu wird die Differenzierung in der Verschiebung zwischen der Kuh und dem UFO ermittelt und dann ein neues keyframed_movement_delta aus diesen Werten erstellt. Es setzt dann diesen einzelnen Keyframe als Array in der Keyframe-Bewegungskomponente und ruft play auf, um die Kuh zwischen ihrer Startposition und dem UFO animieren zu lassen.
# Get the delta between Cow and UFO
DeltaTransform:transform = transform:
Translation:= Entity.GetGlobalTransform().Translation - CowEntity.GetGlobalTransform().Translation
Scale := vector3{Left:= 0.0, Up:= 0.0, Forward:= 0.0}
# Create a key frame
Keyframe := keyframed_movement_delta:
Transform := DeltaTransform
Duration := 2.0
Easing := ease_in_cubic_bezier_easing_function{}
Die Kuh kann zum UFO animieren, wenn sie entführt wird, aber der Code muss sie auch verschwinden lassen, wenn sie eine Überlappung mit dem UFO selbst hat. Dazu wartet der Code auf das EntityEnteredEvent der Mesh-Komponente von der Kuh und ruft dann RemoveFromParent() auf, um die Kuh-Entität aus der Szene zu entfernen. Da die Kuh weg ist, kann das UFO wieder patrouillieren, also spielen die Codeaufrufe die mit dem Keyframe versehene Bewegungskomponente des UFO ab, um es in Bewegung zu setzen.
# Wait for Entity Entered Event
CowMesh.EntityEnteredEvent.Await()
# Remove Cow from world
CowEntity.RemoveFromParent()
# Resume UFO Patrol
set IsAbducting = false
if:
UFOMovementComponent := Entity.GetComponent[keyframed_movement_component]
Schließlich fungieren die Funktionen EnableAdbuctionBeam() und DisableAbductionBeam() als einfache Helfer, die das Ableitungsstrahl-Mesh und die Spotlichtkomponenten auf dem UFO bei ihrem Aufruf ein- bzw. ausschalten.
EnableAbductionBeam():void =
for:
Mesh : Entity.FindDescendantComponents(Meshes.S_EV_SimpleLightBeam_01)
do:
Mesh.Enable()
for:
Light : Entity.FindDescendantComponents(spot_light_component)
do:
Light.Enable()
Vollständiges Script
Nachfolgend findest du das vollständige Skript zum Abfragen von Überlappungstreffern.
using { /Verse.org }
using { /Verse.org/Native }
using { /Verse.org/SceneGraph }
using { /Verse.org/Simulation }
using { /Verse.org/Colors }
using { /Verse.org/SceneGraph/KeyframedMovement }
using { /Verse.org/SpatialMath }
using { /Fortnite.com/Game }
using { /Fortnite.com/Devices }
Abfragen von Sweep-Treffern
Sweep hits bieten eine weitere wichtige Möglichkeit, Überschneidungen zwischen Entitäten abzufragen. Beim Sweeping wird ein Objekt über eine bestimmte Entfernung entlang eines bestimmten Vektors bewegt. So kannst du zum Beispiel einen Block über eine Plattform bewegen, um Spieler in eine Lücke zu stoßen, oder eine Rakete direkt nach vorne starten, um eine Wand zu zerstören.
Die Funktion FindSweepHits() gibt eine Liste von sweep_hit zurück. Jeder sweep_hit liefert dir dieselben Informationen wie ein overlap_hit, z. B. die Komponente oder den Volume-Treffer und das Quell-Volumen oder die Komponente, die den Sweep durchführt. Es liefert zusätzlich Informationen über die Kontaktposition, Normale, Flächennormale und den Abstand entlang des Sweeps, wo der Treffer aufgetreten ist.
Die Vorlage verwendet Sweep-Treffer, um eine erweiterte Version des vorherigen Beispiels der Überlappung zu erstellen. Gehe auf die letzte interaktive Fläche im zweiten Flur, um dir dieses Beispiel anzusehen. Wenn du auf das Pad trittst, erzeugt das UFO einen Entführungsstrahl. Es führt dann einen Sweep-Treffer vom UFO-Mesh abwärts durch und prüft die erste Entität, mit der der Sweep eine Überlappung aufweist. Wenn die Entität eine Kuh ist, entführt das UFO sie wie gewohnt. Wenn die Kuh jedoch durch eine Entität geschützt wird, trifft der Sweep zuerst die Entität und wird blockiert, wodurch verhindert wird, dass das UFO die Kuh entführt.
Öffne FindOverlapHitsExampleComponent.verse im Verse-Explorer, um den Code zu untersuchen. Der Aufbau hier ist dem obigen Beispiel der Überlappung sehr ähnlich, mit der gleichen Logik, die für das Entführen der Kuh und das Aktivieren und Deaktivieren des Abführungsstrahls verwendet wird. Der Hauptunterschied besteht in der Funktion OnTriggerEntered(), die ausgeführt wird, wenn der Spieler auf die interaktiv Fläche vor dem Beispiel tritt.
Der Code für diese Funktion beginnt ähnlich wie beim Beispiel der Überlappungstreffer, indem er die mit Keyframes versehene Bewegungskomponente aus der Entität abruft und den Ableitungsstrahl aktiviert.
OnTriggerEntered(Agent:agent):void=
# When a cow is inside the abduction area, stop the ship moving and start the abduction beam.
if:
not IsAbducting?
MovementComponent := Entity.GetComponent[keyframed_movement_component]
then:
MovementComponent.Pause()
EnableAbductionBeam()Da die Funktion jedoch Sweeps statt Überlappungen verwendet, ist die Logik dafür, ob sich die Kuh unter dem Abductionsstrahl befindet, etwas anders. Sie beginnt mit dem Abrufen des ersten Kindes der UFO-Entität, in diesem Fall der Mesh-Entität des UFO. Es erzeugt dann einen Verschiebungsvektor, von dem aus der Sweep durchgeführt werden kann, der vom UFO direkt nach unten zeigt.
# Perform the sweep from the UFO Mesh
if (Child := Entity.GetEntities()[0]):
DisplacementVector := vector3{Left:=0.0, Up:=-300.0, Forward:=0.0}Es verwendet dann diesen Verschiebungsvektor, um die Hilfsfunktion FindFirstSweepHit() aufzurufen, die das Mesh des UFOs und den Vektor übergibt. Wenn die erste Komponente die Mesh-Komponente der Kuh ist, erzeugt sie die Funktion AbductCow(), um die Entführung der Kuh zu simulieren.
# Perform the sweep from the UFO Mesh
if (Child := Entity.GetEntities()[0]):
DisplacementVector := vector3{Left:=0.0, Up:=-300.0, Forward:=0.0}
FirstSweepHitEntity := FindFirstSweepHit(Child, DisplacementVector)
# If the First Hit Entity is the Cow Mesh, then abduct the Cow
if (HitEntity := FirstSweepHitEntity?; HitEntity.GetComponent[Meshes.SM_Toy_Cow]):
spawn { AbductCow(HitEntity) }Die Funktion FindFirstSweepHit() nimmt die Entität, die gespawnt werden soll, und den Verschiebungsvektor, um sie entlang zu spawnen. Sie ruft FindSweepHits() auf, um einen Sweep zu simulieren, und iteriert dann durch jeden zurückgegebenen Sweep-Treffer in einem `for`-Ausdruck. Da jeder sweep_hit entweder eine Komponente oder ein Volume ist, kannst du entweder die TargetComponent oder das TargetVolume abfragen, um zu wissen, welchen Typ es hat. In diesem Fall holt der Code die besitzende Entität der TargetComponent ab und gibt sie als Option zurück, d. h. gibt `true` zurück, wenn der Sweep eine Komponente trifft, und andernfalls false.
# Returns the first Entity hit by FindSweepHits
FindFirstSweepHit(InEntity:entity, DisplacementVector:vector3):?entity =
for (SweepHit : InEntity.FindSweepHits(DisplacementVector)):
return option{ SweepHit.TargetComponent.Entity }
return falseVollständiges Script
Unten findest du das vollständige Skript zum Abfragen von Sweep-Treffern.
using { /Verse.org }
using { /Verse.org/Native }
using { /Verse.org/SceneGraph }
using { /Verse.org/Simulation }
using { /Verse.org/Colors }
using { /Verse.org/SceneGraph/KeyframedMovement }
using { /Verse.org/SpatialMath }
using { /Fortnite.com/Game }
using { /Fortnite.com/Devices }