Getting Started with Verse in UEFN (Unreal Engine Fortnite) (Creator 2.0)

If you’re like me, you saw the new UEFN and verse programming language and thought that now was the perfect time to jump into creating things in Fortnite! My initial impressions were that the engine was effectively UE 5.1 and a new scripting language to boot! However, the engine is really stripped down, the language feature set is pretty limited and learning UEFN is not very similar to UE 5.1 after all! Even still, after messing around in the engine for a couple days, I feel as though I’ve gotten the ropes and can effectively utilize what the engine gives me to create cool and unique experiences! So in this article, I’ll be giving some pointers, taking about what UEFN adds to the engine over Fortnite creative, how the two interact, and I’ll be walking you through the basics of the engine as well as the Verse programming language. Without further ado, let’s dig in!

What is Fortnite Creative?

Fortnite creative is a way for people to create their very own games and modes within Fortnite. Fortnite creative has been around for a little bit now, however, it was relatively lightweight compared to the new release of Fortnite 2.0.

What is Different From Fortnite Creative vs UEFN?

Fortnite Creative is building worlds and games for Fortnite within Fortnite. UEFN, is an entirely separate program that you have to install, it’s a modified version of Unreal 5.1. This allows for further customization, custom audio, 3D models, animations, and custom sequences. It also gives you access to write custom scripts via a newly introduced programming language called Verse. Verse gives access to some of the Fortnite API, however, this is currently very limited. Verse’s capabilities are in general are quite limited as of writing, as Epic is releasing Verse in more of a “beta’ form, and will continue to release more features and expose more of the Fortnite API over the next few years. Epic is very committed to working on Verse, as they are proposing it to be the future language of the metaverse and want it to improve over many years.

Features of UEFN

You have access to all the typical devices that are within Fortnite Creative, however, UEFN has it’s own abilities as well. Specifically, you can import custom Audio, custom models, textures, animations, materials. You can make custom sequences where you can make your own cut scenes where you can do whatever you want! You can share projects with teams, and push updates right into Fortnite.

Making a Verse Script in your Project

When making a new Verse script, it’s easiest to open the ‘Verse Explorer” and add the file from there, you can find this window on the top bar, under the “Verse” section

Once in the verse explorer, you can right-click on the “Content” folder, and click “Create new Verse File”. From here, you can select to use the hello world template, or a blank empty file. It’s up to you what you think is easiest.

Features of Verse

Creative Devices

All code that you write in verse must live somewhere inside of the Fortnite scene, but how do you get it to live in the scene? The current way is to inherit from the creative_device, you can put variables into the creative device and then expose them so you can set them from within the scene. Once you compile the verse code, you can drag in the custom device you made into the scene. From here you will be able to see all of the editable variables. In this example the creative device is called escape sequence.

In this example, I have a few exposed variables, such as the ComputerScreen variable that takes a billboard_device object reference. This can then be dragged into the slot to be referenced in your code. To create a variable and expose it to the inspector, you just have to add some special syntax above the variable “@editable” as shown here:

@editable
var ComputerScreen:billboard_device = billboard_device{}

creative devices are how you interface with Fortnite, and there are some key points at which you can subscribe to within Fortnite, specifically OnBegin (When the match begins), and OnEnd (when the game ends).

The Structure Of a Variable

I’ll be real, Verse has some WEIRD syntax, variable deceleration isn’t too bad though. Let’s analyze the earlier mentioned line:

var ComputerScreen:billboard_device = billboard_device{}

“var” : The var at the start of the line signifies if the variable is modifiable. Neglecting the var at the beginning of declaration makes it so that the variable cannot be modified, or is marked “const” in other languages.
”ComputerScreen”: This is the name of the variable, and can be named anything that isn’t reserved, but in general I try to stick with Epic’s recommended UpperCamelCase structure, where the first letter of each word is capitalized.
”:” This separates the name of the variable from the type.
”billboard_device”: This is the type that the variable is. This type is more complex, as it’s defined by Fortnite, but it could be as simple as int, float, string, etc.
”=” : now we specify we will instantiate this variable
billboard_device{}” : This basically makes an empty instance of this structure, if it was something like an int, you would type in the number you want it to start at. For arrays and maps, you specify it is equal to array{} or map{}.

Note on Arrays, the [] notation to denote an array comes BEFORE the type, ie:

var ComputerScreens:[]billboard_device = array{}

Effect Specifiers

Verse has syntax for functions that tell the program something about how the function is going to execute, or in what context it is executing, or signifies the scope that the function or class is available. Some effects are exclusive, while others are additive. Exclusive effects can only have one of the effect, while additive can have any number of additive effects. These specifiers are supplied in brackets, like so

name<public> : type = value # This is an access specifier marking "public"
pet := class<abstract>(): #This class is marked abstract via the specifier
damage_over_time<suspends> : type = {code} #suspends marks async functions

There are many other effects, may of which can be found here: https://dev.epicgames.com/documentation/en-us/uefn/specifiers-and-attributes-in-verse

One such effect that is very useful that I do not see listed on this page is “localizes”

MakeMessage<localizes>(txt: string) : message = "{txt}"

This effect is used for UI, when displaying text on the screen, you need to have the text in localized form, so using the <localizes> specifier you can turn any string into a localized piece of text.

The <suspends> Effect (Async Functions or Coroutines)

The <suspends> effect is extremely useful, as it allows you to wait, or execute items over time. The main thing you need to know is that to wait, you need to call Sleep(TimeToWait) with TimeToWait, being the number of seconds to wait before being picked back up again.

If you have two <suspends> functions, and you call one from the other, the calling function will wait until the second function has finished. For example:

AsyncFunction1()<suspends>:void=
    AsyncFunction2()
    Logger.Print("Finished 1")

AsyncFunction2()<suspends>:void=
    Logger.Print("Starting 2")
    Sleep(1.0)
    Logger.Print("Finished 2")

The text output you would see from calling AsyncFunction1 would be:
Starting 2
… waiting one second …
Finished 2
Finished 1

However, you cannot call <suspends> functions from non-suspends functions, in these cases, you have to “spawn” them. Spawning functions from within a suspends function will also allow the calling function to continue execution without waiting. For example

AsyncFunction1():void=
    spawn{AsyncFunction2()}
    Logger.Print("Finished 1")

AsyncFunction2()<suspends>:void=
    Logger.Print("Starting 2")
    Sleep(1.0)
    Logger.Print("Finished 2")

The text output you would see from calling AsyncFunction1 would be:
Starting 2
Finished 1
… waiting one second …
Finished 2

Players

There are multiple players within a Fortnite match, specifically UI related things need to be player-specific. You can get the current players very easily, with Self.GetPlayspace().GetPlayers(), this should return a list of players that you can add UI to or check for validity.

Include Files

To make use of things like creative devices or player references, you need to make sure to include the proper header-files, these can be included easily, as they are hosted online and are publically accessible with the simple “using” keyword. For instance, to have access to creative_device, you would need to include:

using { /Fortnite.com/Devices }

Having the proper headers will give access to things you need from Fortnite, and your verse code will fail to compile (build) without the proper headers. Some other important ones are:

using { /Fortnite.com/Characters }
using { /Fortnite.com/UI }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /UnrealEngine.com/Temporary/UI}
using { /Verse.org/Simulation}
using { /Verse.org/Colors }
using { /Verse.org/Random }


You can find the proper module you need to include for a given class or function within the verse documentation for that function or class. For the simulation module, you can see here: https://dev.epicgames.com/documentation/en-us/uefn/verse-api/versedotorg/simulation

Executing Code Every “Frame” or “Tick”

Verse unfortnutely doesn’t have a “Tick()” function like the OnBegin, which is quite unfortunet. However, there is still a way around this, if you want something to execute every frame, make a new function called something like

Tick()<suspends>:void=

The important thing here is that it uses the “suspends” effect. As mentioned above, suspends allows you to write code that waits, or executes async. If you then write out a loop that goes on forever, and waits between each frame, you have a tick function! Something around 0.016 is 60FPS, and 0.033 is 30FPS. Calling with a sleep of 0.0 will ensure that it executes every frame. Note that the verse execution is slightly bugged, so even with a sleep(0.0) it may run twice in one frame sometimes, or miss a frame sometimes. Typically this isn’t a large issue, this mainly comes into play when you are trying to move something every frame, especially in regards to player position or input, there may be a frame delay.

Tick()<suspends>:void=
    loop:
        #Do all my code for that tick here.
        Sleep(0.0)

Events

Other times you need to execute code, is when an event fires! This could be something like pressing a button_device in the Fortnite game world. In verse, you will need to have references to the objects you want to listen to, and then you will need to subscribe to their event handlers. Listening to a button for instance would look like such:

keypadButton.InteractedWithEvent.Subscribe(ButtonClickedHandler)
ButtonClickedHandler(Agent: agent):void=
    #Do code here

Here, you need to have a reference to the agent (player) that interacted with the button. Any code in that function will run when the button is interacted with.

Passing variables to a subscription callback

Unfortunetly, you may want more information about the button that was pressed, for a keypad, you would want to know which number was pressed for instance (0-9), currently, there is no way to get that information, and we can’t make a llambda function with our own custom arguments, however, there is a workaround for this. We can have a different class, that has member attributes of things we want to store, we make an instance of this class, and instead of subscribing to a function within our own device, we instead subscribe to one in this new class. For instance:

CustomHandler:= class() {
    Device : escape_sequence_device   #this is the name of your divice
    KeypadValue: int 

    OnInteractedWithFunction(Agent : agent) : void = {
        Device.OnKeypadButtonPressed(KeypadValue)
    }
}

escape_sequence_device := class(creative_device):
    Logger : log = log{Channel:=log_secret}
    @editable
    var keypadButton:button_device = button_device{}

    OnBegin<override>()<suspends>:void=
        var value:int:=2
        keypadButton.InteractedWithEvent.Subscribe(CustomHandler{Device:=Self,       KeypadValue:=value}.OnInteractedWithFunction)

    OnKeypadButtonPressed(KeypadVal:int):void=
        Logger.Print("Keypad button is {KeypadVal}")

As you can see here, we have a custom class called CustomHandler, and then within our creative device, we instead of Subscribing to a function we have, we instead make a new CustomHadler instance, with our KeypadValue being set dynamically to our value variable, when the button is pressed, it calls this function, which then calls back into our device, on the OnKeypadButtonPressed function, and finally, we log the button press onto the Fortnite console log.

Building your verse code

At the top of the UEFN window, ther is a verse tab. Inside of this, you can see “Build Verse Code”, as well as “Verse Build Message Log”. Build Verse Code, will attempt to actually build the code in your project, if it succeeds, all is good, and you shoould be able to use it in your project. However, if not, you will need to open the “Verse Build Message Log” to see any errors, to help you debug your code and determine where you went wrong.

A Device Isn’t Verse Accessible

Sometimes Fortnite launches new devices and features, and these are not always verse accessible. However, sometimes you need to be able to interact with these from verse! One workaround for this is to create a reference to a trigger_device, and then, instead of calling the code directly, call the “Trigger” function on the trigger.

NonInteractableDeviceTrigger:trigger_device=trigger_device{}
...
NonInteractableDeviceTrigger.Trigger()

Then in the editor, create the trigger device, drag the reference onto your verse device. Then, on the device that isn’t verse accessible, you can tell the desired function to listen to the trigger device’s OnTriggered event.

More To Discover

Verse is being updated with new devices, and new functionality constantly. Even in it’s base initial version there is much more to discover in the syntax and devices. Make sure to keep up-to-date with the UEFN and creative patch notes, as they expand the verse API and add more devices to the Fortnite universe!

Conclusion

With this information, this should be a bit of a jumping-in point to getting started with Verse code inside of UEFN. As Verse and Fortnite continue to grow, no doubt will the APIs and code change and be updated. I will try to make updates to this post, or create new posts if deemed necessary in the future!


If you found this tutorial helpful and want to help support me in creating this content that I host and publish for free, please consider contributing to my Patreon or Ko-fi!