This tutorial uses Verse to make certain features possible. By using Verse in this tutorial, you can:
Trigger and play animations intermittently to create a gameplay mechanic.
Updates the player’s score information for all the players in a mini-game.
Create player spawn delays and intermittent item spawn times.
You can reuse this code to perform the following tasks:
Switch the devices that are enabled and disabled while the game transitions from the HUB to gameplay and back to the HUB.
Check players’ scores to find the winning score and display it in the HUB.
End the game and teleport players back to the HUB at the end of the mini-game.
Setting Up the Verse Device and Editable Objects
Follow these steps to set up your Verse device and editable objects:
Create a new Verse device named
tiltnboomand add it to the level. See Create Your Own Device Using Verse for steps.Add the following modules at the top of the file:
Verseusing { /Fortnite.com/Characters } using { /Fortnite.com/Devices } using { /Fortnite.com/Game } using { /UnrealEngine.com/Temporary/Diagnostics } using { /Verse.org/Random } using { /Verse.org/Simulation }Add the following fields to the
tiltnboomclass definition:Two editable
triggerdevices; ActivateGameTrigger and EndGameTrigger.ActivateGameTriggeris used to activate this game. The trigger can be triggered by anything such as a Teleporter to the game, or after an intro cinematic.The
EndGameTriggeris used to end the minigame and remove all camera and control devices from players after the game is over.
Verse@editable ActivateGameTrigger:trigger_device = trigger_device{} @editable EndGameTrigger:trigger_device = trigger_device{}An editable Timer Device named GameTimer. This ends the game after a certain amount of time.
An
arrayof Cinematic Sequence devices namedCannonballSequences, Each device in the array plays a different cannonball landing position.An array of Damage Volumes named DamageVolumes that enable and disable based on the game state.
An array of Item Spawners named ItemSpawners that randomly spawn a random number of items during the game.
A Capture Area Device named CaptureArea. This gives players points for being on the raft, and is enabled or disabled based on the game state.
A Score Manager Device named
ScoreManager, which resets the score of players when a game starts and determines the winning player at the end of the game.A Teleporter named
HUBTeleporterwhich brings everyone back to the HUB after the game is over.A Player Reference Device named PlayerReference, which displays the winning player in the HUB between games.
Verse@editable GameTimer:timer_device = timer_device{} @editable CannonballSequences:[]cinematic_sequence_device = array{} @editable DamageVolumes:[]damage_volume_device = array{} @editable
Two editable arrays of Player Spawn Pads named
PlayerSpawnersandHUBSpawners. These disable spawning when the mini-game is over, and return players to the HUB after the mini-game.Verse@editable PlayerSpawners:[]player_spawner_device = array{} @editable HUBSpawners:[]player_spawner_device = array{}Two editable
floatsnamedMinimumItemSpawnTimeandMaximumItemSpawnTime. These are the minimum and maximum times to wait between spawning items on the raft.Verse@editable MinimumItemSpawnTime:float = 5.0 @editable MaximumItemSpawnTime:float = 10.0An editable
floatnamedDelayAfterGame. This is the delay for teleporting players back to the HUB once the game is over.Verse@editable DelayAfterGame:float = 5.0A
floatnamedDelayBetweenCannonballSequences. This is the delay for spawning cannonballs between sequences throughout the duration of the mini-game.VerseDelayBetweenCannonballSequences:float = 8.0A logic variable called
GameActiveto determine whether the game is active or not.Versevar GameActive:logic = false
Starting the Game
When the mini-game starts, several devices are enabled, and the player score resets to 0.
Above the
tiltnboomclass definition, add a log channel to print messages specific to the minigame. Then add a Logger to the class definition to use with the log channel.Versetiltnboom_log_channel := class(log_channel){} # A Verse-authored creative device that can be placed in a level tiltnboom := class(creative_device): Logger:log = log{Channel := tiltnboom_log_channel}Add a new method
OnTriggeredto thetitnboomclass definition that takes anInitiatingAgentand starts the game. Add an if expression to the method that returns if the game is already active, since you don’t want to start the game while one is already running.VerseOnTriggered(InitiatingAgent:?agent):void= if (GameActive?): return spawn{StartGame()}In
OnBegin(), subscribe the ActivateGameTrigger’sTriggeredEventto theOnTriggeredfunction to start the game. Any device that needs to be enabled at the beginning of the mini-game will subscribe to this event and enable when the OnTrigger event is triggered.VerseOnBegin<override>()<suspends>:void= ActivateGameTrigger.TriggeredEvent.Subscribe(OnTriggered)Add a new method
StartGame()that handles the logic to start the game. Add the<suspends>modifier to this function so it can run asynchronously.First, set the
GameActivetotrueto signal that the game is active Then enable theCaptureAreaand eachDamageVolumein theDamageVolumesarray.For each player, if that player has a score greater than 0, reset their score by awarding the player the inverse of their current score, which sets their score to 0.
Then in a race expression, race between the timer finishing, the cannonball sequence running, and random items spawning. The cannonball sequence and spawning random items are infinite loops, but are canceled as soon as the timer ends.
When the game ends, call the
OnGameFinished()function to handle cleanup at the end of the game.VerseStartGame()<suspends>:void= Logger.Print("Starting game.") set GameActive = true CaptureArea.Enable() for (DamageVolume : DamageVolumes): DamageVolume.Enable() for:
Creating a Cannonball Loop
This section covers adding a function tha tplays the cannonball Cinematic Sequences.
Add a new method
StartCannonSequence()to thetiltnboomclass definition that plays the cannonball Level Sequences and uses a loop to play the delay expression and insert a delay between cannonballs. Add the<suspends>modifier to this function so it can run asynchronously.In a loop, pick a random sequence in the
CannonballSequencesarray by indexing it withGetRandomInt(). Play the sequence, then sleep for aDelayBetweenCannonballSequencesamount of time before playing another sequence.VerseStartCannonSequence()<suspends>:void= loop: RandomCannonballSequence:int = GetRandomInt(0, CannonballSequences.Length - 1) if (CannonballSequence := CannonballSequences[RandomCannonballSequence]): Logger.Print("Set CannonballSequence to {RandomCannonballSequence}") CannonballSequence.Play()
Creating Random Spawning Item Loops
This section covers creating a function that loops spawning random items at random locations on the raft, which can either help–or hurt players’ chances of winning the mini-game.
Add a new method called
SpawnRandomItemsto thetitlnboomclass definition. This method controls the items that spawn on the raft.Get the number of items in the
ItemSpawnersarray, then loop through the array. Use a randomintto get a random item spawner from the array, then activate it. Sleep for a random amount of time between spawning items.The loop randomly decides how many items to spawn, and randomly selects an item to spawn, as many times as
NumberOfItemsToSpawn. TheDelayBetweenItemSpawnsgenerates an undetermined amount of time to wait between spawns.VerseSpawnRandomItems()<suspends>:void= ItemSpawnerCount:int = ItemSpawners.Length - 1 loop: NumberOfItemsToSpawn:int = GetRandomInt(0, ItemSpawnerCount) # Spawn a randomly selected item, as many times as NumberOfItemsToSpawn. for: CurrentItemSpawnNumber := 0..NumberOfItemsToSpawn
Ending the Game
At the end of the mini-game, you’ll need to send the winner’s score to the HUB, disable devices and teleport players back to the HUB.
Add a new method
OnGameFinishedto thetiltnboomclass definition. When the game is finished, this function sets the game to be inactive and disables the relevant devices.~~~(verse) OnGameFinished()<suspends>:void= Logger.Print("Game is finished.") set GameActive = false
CaptureArea.Disable()
for (PlayerSpawner : PlayerSpawners): PlayerSpawner.Disable()
for (DamageVolume : DamageVolumes): DamageVolume.Disable() ~~~
Add
variable intHighestScoreto track the player with the highest score, and an option variable reference to that playerWinningPlayer.Versevar HighestScore:int = -1 var WinningPlayer:?agent = falseIn a for/do expression, get all the players in the playspace, then get the
FortCharacterfor each of them. Freeze the character in place usingPutInStasis(), passing a new set ofstasis_argsto allow emoting and turning so the players can celebrate the game.Versefor: Player : GetPlayspace().GetPlayers() FortCharacter := Player.GetFortCharacter[] do: FortCharacter.PutInStasis(stasis_args{AllowTurning := true, AllowEmotes := true})In an
ifstatement, check each player’s score to find and store the winning score in the Player Reference device in the HUB.Verseif (ScoreManager.GetCurrentScore(Player) > HighestScore): set HighestScore = ScoreManager.GetCurrentScore(Player) set WinningPlayer = option{Player}Lastly, in another if statement, call
TeleportPlayersToHUB()to teleport everyone back to the HUB when a winning score is found.Verseif(Winner := WinningPlayer?): PlayerReference.Register(Winner) TeleportPlayersToHUB()
Teleporting Players Back to the HUB
When the scores have been calculated and a winner is declared, all players should teleport back to the HUB.
Add a new method
TeleportPlayersToHUB()to the tiltnboom class definition. This method enables all player spawners in the HUB, then waits a few seconds before teleporting everyone back to the HUB. This method should also trigger theEndGameTriggerto remove camera and control devices from players.VerseTeleportPlayersToHUB()<suspends>:void= for (HUBSpawner : HUBSpawners): HUBSpawner.Enable() Sleep(DelayAfterGame) EndGameTrigger.Trigger()In a
forexpression, teleport each player back to theHUBTeleporterand release them from stasis.Versefor: Player : GetPlayspace().GetPlayers() FortCharacter := Player.GetFortCharacter[] do: HUBTeleporter.Teleport(Player) Sleep(1.0) FortCharacter.ReleaseFromStasis()
On Your Own
Modify this code to create different tasks for the Timer Device to perform. Instead of determining how long a mini-game is, you can use the Timer Device to time a race.
using { /Fortnite.com/Characters }
using { /Fortnite.com/Devices }
using { /Fortnite.com/Game }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Verse.org/Random }
using { /Verse.org/Simulation }
tiltnboom_log_channel := class(log_channel){}
# A Verse-authored creative device that can be placed in a level