Unreal Engine Programming with Verse
Duality - Mika Laaksonen, 2023

Unreal Engine Programming with Verse

Few years ago, there were rumours about new programming language in Unreal Engine. Some speculated that UE would integrate one of existing programming languages, and many thought that it would be Python. Although Python has been part of UE programming for a long time, you could not use it to program complete games – instead it has been mostly a “tools programming language”. Developers were guessing that Epic Games would integrate Python to cover all aspects of game programming.

That proved to be false news. When Unreal Engine 5 was released, it was revealed that the additional language is called Verse, and it is totally new language, developed in-house at Epic Games specifically for Unreal Engine. However, it wasn’t exactly what people thought it to be, not to mention that you could not even use it until now, and you cannot use it in regular Unreal Engine 5, only in Unreal Editor for Fortnite. So, lets delve into this more thoroughly.


Unreal Engine, Unreal Engine Fortnite – What’s the Difference

At this point it is important to understand that there are now two different Unreal Engines. Although they share the common core, and look quite the same, there are clear differences in how you can develop games, what tools you can use, and how you can release your games. Unreal Engine 4 and 5 are regular versions of UE, which allow developing software for many purposes. Unreal Editor for Fortnite or Unreal Engine Fortnite is the new, separate version of UE, which offers most of UE features (but not all), and adds some new features, and it is aimed at developers producing Fortnite content. So, these two have different development and gaming ecosystems, and you must choose either of them based on your project and target audience.

Regular Unreal Engine we all know already. You have all the familiar features at your disposal, and you can develop games, VR, AR, Virtual Production, architecture visualization etc. for desktop, console and mobile platforms. Programming is done with C++ and Blueprints.

Unreal Engine Fortnite is a new way to design, develop, and publish content into Fortnite using the Unreal Editor’s development workflows and proven PC-based toolset. As the name suggests, it is meant to be used for Fortnite ecosystems – games and large experiences expanding the Fortnite Creative in new ways. Programming is done with Blueprints and Verse.

At this moment, it is very clear that you cannot use both Unreal Engine C++ and Verse in your project, and what you use depends on your project goal.

You can use C++ with Unreal Engine Fortnite, but only for building your own game using the Unreal Engine source code (making it unusable in Fortnite ecosystem), and in that case it would be better to use regular Unreal Engine. You cannot use C++ to create or customize devices for Fortnite Creative. For that, you need to use Verse. Verse is integrated with Unreal Editor for Fortnite and can be used to create your own gameplay and customize your devices for Fortnite Creative.

However, Unreal Editor for Fortnite is not the same as the regular Unreal Engine editor that you can use to build your own games using C++ or Blueprints. Therefore, you cannot mix Verse and C++ code in the same project, unless you somehow export or import your Verse code or devices into a regular Unreal Engine project, which I don't think is possible or supported now. Perhaps in the future Verse is integrated into regular Unreal Engine, too.

In my opinion it is wise to learn Verse basics, even if you don’t currently develop anything for Fortnite ecosystem. First, Verse may be part of regular UE in the future. Second, there is always a possibility that you may encounter an opportunity to develop something for Fortnite, especially if you want to expand your career.


What is Verse?

Verse is the new programming language for Unreal Engine Fortnite. It is a web3 programming language that was introduced to enable game developers to create their own gameplay in Unreal Editor for Fortnite, including customizing their devices for Fortnite Creative. Verse is designed to be simple, general, productive, statically verified, performant, complete and timeless.

Verse is a multi-paradigm language that uses the best of functional programming, object-oriented programming, and imperative programming. Some of the paradigms that Verse supports are:

Determinism: Data is immutable by default, and given the same code and data, results will always be exactly the same.

Expression-oriented: Everything is an expression, which means that everything has a result.

Failure-based control flow: Instead of using true / false values to change the flow of your program, Verse uses failable expressions, which produce a value if they succeed or don’t if they fail.

Speculative execution: You can try out actions without committing them. When an expression succeeds, the effects of the expression are committed, but if the expression fails, the effects of the expression are rolled back as though the expression never happened.

Concurrency: You can perform actions simultaneously using language-level concurrency instead of relying on system-level threads across multiple processors.


People are often afraid of C++, thinking that it is overtly complicated, impossible to learn and hanging on various other excuses or false beliefs. In my opinion C++ is not that complicated compared to many other, all that is just a myth, which has grown during the decades. I know several non-technical persons who have learned to program with C++.

Many thought that now things get easier with Verse, but many will be disappointed, too. As I explained above, you cannot use Verse in regular UE projects. Also, Verse is not very much easier than C++, Verse has its own complications. When I taught programming in university, I noticed that especially functional programming is a concept that is hard to grasp on practical level for many students.

Verse is a compiled language. This means that Verse code is translated into machine code before it can be executed by the computer. This translation process is done by a program called a compiler, which takes a Verse file as input and produces an executable file as output. The executable file can then be run by the computer without the need for the Verse file or the compiler.

The advantage of a compiled language is that it can run faster and more efficiently than an interpreted language, which is a language that is translated and executed line by line at runtime by a program called an interpreter. The disadvantage of a compiled language is that it requires more time and resources to compile the code, and that it may not be compatible with different platforms or architectures.

Unreal Verse uses a custom compiler that is integrated with Unreal Editor for Fortnite. The Verse compiler is responsible for translating the Verse code into executable instructions that can run on various platforms, such as Windows, Mac, iOS, Android, and consoles. The Verse compiler also performs static analysis and verification on the Verse code, which means it checks for errors and potential problems before running the code. The Verse compiler supports features such as:

  • Incremental compilation, which means it only recompiles the parts of the code that have changed, making the compilation process faster and more efficient.
  • Hot reload and hot restart, which means you can make changes to your Verse code and see the results in the game without restarting the game or losing your progress.
  • Live coding, which means you can edit your Verse code while the game is running and see the changes in real time, without having to recompile or reload the game.



Advantages and Disadvantages of Verse

Since Verse is a totally new language, we should expect that its creators have learned from several decades of experiences in every programming language, and that it would avoid many legacy mistakes.

Some advantages of using Verse over C++ for Unreal Engine are:

- Verse is simpler and easier to learn as a first-time programmer, while C++ is complex and has a steep learning curve.

- Verse is strongly typed and statically verified, which means it can catch many runtime errors at compile time and prevent uncaught errors in development or deployment, while C++ is weakly typed and prone to memory leaks and undefined behavior.

- Verse is multi-paradigm and supports functional, object-oriented, and imperative programming styles, while C++ is mainly object-oriented and imperative.

- Verse uses failable expressions and speculative execution to handle failure as control flow, which means you can try out actions without committing them and roll back the effects if they fail, while C++ uses true/false values and exception handling to change the flow of the program, which can be cumbersome and error-prone.

- Verse supports concurrency at the language level, which means you can perform actions simultaneously without relying on system-level threads, while C++ requires external libraries or frameworks to achieve concurrency.

 

These are some of the features that make Verse a better suited language for video game and game-like experiences than C++. However, C++ still has its advantages, such as having full control of the engine, being able to access the underlying source code, and having a large and mature ecosystem of tools and libraries.

But no programming language can claim to be perfect, and the suitability is more relevant question than “what is the best programming language”. You should always think about how any programming language suits your project, your goals, your development style, your team, maintenance etc.

Some disadvantages of using Verse over C++ for Unreal Engine are:

- Verse is a new and experimental language that is still in beta and may have bugs, limitations, or changes in the future, while C++ is a well-established and stable language that has been used for decades.

- Verse is specific to Unreal Engine and may not be compatible or transferable to other engines or platforms, while C++ is a general-purpose language that can be used for a variety of applications and systems.

- Verse has a smaller and less mature ecosystem of tools, libraries, and resources than C++, which means you may have less support or options for developing your projects.

- Verse has a different syntax and semantics than C++, which means you may have to learn new concepts and paradigms that are not familiar or intuitive to you, such as failable expressions, speculative execution, and concurrency.

- Verse may not have all the features or functionalities that C++ offers, such as pointers, templates, multiple inheritance, operator overloading, etc., which may limit your flexibility or creativity in some cases.

 

These are some of the challenges or drawbacks of using Verse instead of C++. However, Verse also has its advantages, such as being simpler, safer, more productive, and more performant than C++, as well as being designed for video game and game-like experiences. Ultimately, the choice of language depends on your goals, preferences, and needs.


Verse Syntax

The syntax of Verse is the set of rules that define how to write valid Verse code. The syntax covers various aspects of the language, such as:

 

Expressions: The smallest unit of code that produces a value when evaluated, such as `1 + 2` or `if (x > 0) { print ("Positive") } else { print ("Negative or zero") }`

Comments: Text that explains something about the code or the programmer's intention, but is ignored when the program runs, such as `# This is a single-line comment`

Constants and variables: Names that store information or values that the program uses, such as `PI : float = 3.14` or `var Name : string = "Alice"`

Types: Categories of values that determine their characteristics and behavior, such as `int`, `float`, `string`, `logic`, etc.

Operators: Symbols that perform operations on values, such as `+`, `-`, `*`, `/`, `%`, `==`, `!=`, `<`, `>`, etc.

Control flow: Structures that change the order of execution of expressions based on conditions, such as `if ... else`, `case ...`, `for ... `, etc.

Functions: Blocks of code that perform a specific task and can be reused, such as `Add (x : int, y : int) : int { return x + y }`

Classes: Templates that define the properties and methods of objects, such as `character := class: { var Health : int = 100; Move (Direction : vector) { ... } }`

Modules: Collections of related code that can be imported and used by other modules, such as `module Math { Square (x : float) : float { return x * x } }`


Best Practices

Some best practices for writing Verse code are:

- Use descriptive and consistent names for your constants, variables, functions, classes, and modules. This will make your code more readable and maintainable.

- Use comments to explain the purpose, logic, or intention of your code. This will help you and others understand what your code does and why.

- Use indentation and whitespace to format your code properly. This will make your code more organized and clear.

- Use constants instead of literals when possible. This will make your code more flexible and easy to change.

- Use failable expressions and speculative execution to handle failure gracefully. This will make your code more robust and reliable.

- Use concurrency to perform actions simultaneously. This will make your code more efficient and responsive.

- Use modules to organize your code into logical units. This will make your code more modular and reusable.


Verse Structure and Modules

Verse is structured as modules. The base Verse module is the module that contains the core definitions and features of the Verse language, such as classes, interfaces, functions, constants, operators, etc. The base Verse module is identified by the path /Verse.org/Verse, and it is automatically imported into every Verse file, so you don't need to explicitly import it. For example, you can use the class event or the function print without importing anything.

The base Verse module contains various submodules that group related definitions together, such as Math, Random, Time, etc. You can import these submodules by their paths, such as /Verse.org/Verse/Math or /Verse.org/Verse/Random. For example, if you want to use the function GetRandomInt from the Random submodule, you need to import it first:

using { /Verse.org/Verse/Random }
 
# Now you can use GetRandomInt
var x : int = GetRandomInt (1, 10)


You can make separate files for Actors, Classes, and other data objects in Verse. To do that, you need to use modules. A module is an atomic unit of code that can be redistributed and depended upon, and that you can import into your Verse file to use code definitions from other Verse files. A module is specified by the folder in the file hierarchy of the project, and the module's name is the name of the folder. All .verse files in the same folder as the file are part of that module, and can access definitions from the other Verse files in the module without explicitly importing the module.

For example, if you have a folder called Actors in your project, and inside that folder you have a .verse file called Player.verse that defines a Player class, you can access that class from any other .verse file in the Actors folder without importing anything. However, if you want to use that class from a .verse file in a different folder, such as Classes, you need to import the Actors module by its path, such as:

using { /Verse.org/Actors }
 
# Now you can use the Player class from the Actors module
var player : Player = new Player ()

You can also define modules within a .verse file using the following syntax:

module1 := module:
 # Module contents here
 
module2<public> := module:
 # Module contents here

A module defined in this way can contain anything that is contained at the top level of a .verse file, such as function definitions, constant definitions, various type definitions, as well as other module definitions. The visibility of a module and its contents can be set using visibility specifiers, such as public and internal. By default, the visibility for definitions are internal, which means they're only discoverable within their own module.

Some best practices for organizing Verse files and modules are:

- Use descriptive and consistent names for your files, folders, and modules. This will make your code more readable and maintainable.

- Use folders to group related files and modules together. This will make your code more organized and modular.

- Use visibility specifiers to control the access of your definitions from other files and modules. This will make your code more secure and reliable.

- Use imports to access definitions from other modules by their paths. This will make your code more flexible and reusable.

- Use in-file modules to define smaller units of code within a file. This will make your code more concise and clear.


Interface Inheritance

Verse does not have multiple inheritance like C++. Multiple inheritance is a feature that allows a class to inherit from more than one parent class, which can lead to various problems and ambiguities, such as the diamond problem, the name collision problem, and the constructor order problem. Verse avoids these problems by using a different approach called **interface inheritance**.

Interface inheritance is a feature that allows a class to implement one or more interfaces, which are abstract types that define a set of methods and properties that a class must provide. A class can implement multiple interfaces without inheriting their implementation, which means that there is no ambiguity or conflict between them. A class can also inherit from a single parent class, which can provide a default implementation for some or all of the interface methods and properties. For example:

# Define an interface for flying
iFlyable := interface(): {
 Fly()<decides> : void
}
# Define an interface for swimming
iSwimmable := interface() {
 Swim()<decides> : void
}
# Define a class for animals
animal := class() {
 var Name : string
 # Define an abstract method for making sounds
 MakeSound () : void
}
# Define a class for ducks that inherits from Animal and implements IFlyable and ISwimmable
duck := class( animal, iFlyable, iSwimmable ) {
 # Override the MakeSound method from Animal
 MakeSound <override> () : void {
   print ("Quack")
 }
 # Implement the Fly method from IFlyable
 Fly () : void {
   print (Name + " is flying")
 }
 # Implement the Swim method from ISwimmable
 Swim () : void {
   print (Name + " is swimming")
 }
}



Example of Verse Code

This is a simple example of Verse code that handles game character logic. Here is a snippet of code that defines a character class with some properties and methods, such as health, speed, jump, and damage:

character := class: {
 # The character's health points
 var Health : int = 100
 # The character's movement speed
 var Speed : float = 10.0
 # The character's jump force
 var Jump : float = 5.0
 # The character's damage output
 var Damage : int = 10
 # A method that makes the character move in a direction
 Move (Direction : vector):void {
   # Apply the movement speed to the direction vector
   var Velocity : vector = Direction * Speed
   # Set the character's velocity to the calculated vector
   SetVelocity (Velocity)
 }
 # A method that makes the character jump
 Jump ():void {
   # Apply the jump force to the vertical axis
   var Impulse : vector = vector (0, 0, Jump)
   # Add the impulse to the character's velocity
   AddImpulse (Impulse)
 }
 # A method that makes the character attack another character
 Attack (Target : character):void {
   # Deal damage to the target based on the character's damage output
   Target.TakeDamage (Damage)
 }
 # A method that makes the character take damage from another source
 TakeDamage (Amount : int):void {
   # Subtract the damage amount from the character's health points
   Health -= Amount
   # Check if the character's health is zero or below
   if (Health <= 0) {
     # Call the death method
     Die ()
   }
 }
 # A method that makes the character die
 Die ():void {
   # Destroy the character's actor
   DestroyActor ()
   # Add some logic to handle characters death etc.
 }
}


 

This is just a simple (and not very good) example of how Verse can be used to define game character logic. All this should give at least a basic idea of Verse as programming language, and whether it suits your purposes or not.

Kalevi Laaksonen

Freelance Game Developer (C++, C#, Unreal Engine, CryEngine, Lumberyard, Blockchain, Procedural Generation)

1y

Interesting! Quite probably I will have very little use for Verse, but it is good to know.

Like
Reply
Jussi Mäntymäki

Lead Machine Learning Engineer at HighSurge

1y

Thanks, this is interesting!

Like
Reply

To view or add a comment, sign in

Insights from the community

Others also viewed

Explore topics