├── .gitignore
├── README.md
├── config.toml
├── content
├── _index.md
├── cpp-bindings
│ ├── _index.md
│ ├── automatic-bindings.md
│ ├── mixin-libraries.md
│ └── precompiled-data.md
├── getting-started
│ ├── _index.md
│ ├── installation.md
│ └── introduction.md
├── project
│ ├── _index.md
│ ├── development-status.md
│ ├── license.md
│ └── resources.md
└── scripting
│ ├── _index.md
│ ├── actors-components.md
│ ├── cpp-differences.md
│ ├── delegates.md
│ ├── editor-script.md
│ ├── fname-literals.md
│ ├── format-strings.md
│ ├── function-libraries.md
│ ├── functions-and-events.md
│ ├── gameplaytags.md
│ ├── mixin-methods.md
│ ├── networking-features.md
│ ├── properties-and-accessors.md
│ ├── script-tests.md
│ ├── structs-refs.md
│ └── subsystems.md
├── sass
└── docs.scss
├── static
├── angelscript_unreal.png
├── favicon.svg
└── img
│ ├── attach-hierarchy.png
│ ├── bp-event-dispatcher.png
│ ├── bp-override.png
│ ├── bp-pickparent.png
│ ├── bp-properties.png
│ ├── choose-staticmesh.png
│ ├── completion.png
│ ├── countdown-duration.png
│ ├── countdown-print.png
│ ├── coverage-dir.png
│ ├── coverage-file.png
│ ├── coverage-index.png
│ ├── coverage-toggle.png
│ ├── debug.png
│ ├── editable-property.png
│ ├── example-global-function.png
│ ├── favicon.ico
│ ├── functions.png
│ ├── generate-method.png
│ ├── intro-bpnodes.png
│ ├── intro-components.png
│ ├── open-workspace.png
│ ├── override-completion.png
│ ├── override-lightbulb.png
│ ├── place-actors.png
│ ├── properties.png
│ ├── property-categories.png
│ ├── scripted-subsystem.png
│ ├── scripting.png
│ ├── struct-input.png
│ ├── struct-multioutput.png
│ └── timer.png
└── templates
├── index.html
└── page.html
/.gitignore:
--------------------------------------------------------------------------------
1 | public
2 | api
3 | .vscode
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Docs-UnrealEngine-Angelscript
2 | Source text for the [Unreal Engine Angelscript](http://angelscript.hazelight.se/) documentation website.
3 |
4 | Generated using [zola](https://www.getzola.org/).
--------------------------------------------------------------------------------
/config.toml:
--------------------------------------------------------------------------------
1 | base_url = "https://angelscript.hazelight.se"
2 | title = "Unreal Engine Angelscript"
3 | compile_sass = true
4 | build_search_index = true
5 |
6 | [markdown]
7 | highlight_code = true
8 |
9 | [extra]
10 | logo = "angelscript_unreal.png"
--------------------------------------------------------------------------------
/content/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Index"
3 | +++
4 |
5 | # Unreal Engine Angelscript
6 | UnrealEngine-Angelscript is a set of engine modifications and a plugin for UE5 that integrates a
7 | full-featured scripting language.
8 | It is actively developed by [Hazelight](http://hazelight.se), creators of [Split Fiction](https://www.ea.com/games/split-fiction/split-fiction) and [It Takes Two](https://www.ea.com/games/it-takes-two), which were shipped with the majority of their gameplay written in angelscript.
9 | Games from [several other studios](project/resources) have also been released using UnrealEngine-Angelscript.
10 |
11 | The unreal plugin that integrates angelscript is open source, and has received contributions from studios in Stockholm and globally.
12 |
13 | See [Scripting Introduction](getting-started/introduction) for an introduction to the scripting language.
14 |
15 | Come talk to us in our [Discord Server](https://discord.gg/39wmC2e) if you're interested or have questions!
16 |
17 | ## Mission Statement
18 | When making gameplay systems of higher complexity, blueprint visual scripting can easily lead to unmaintainable spaghetti.
19 | However, making these systems in C++ imposes long iteration times, and can be daunting for designers or gameplay scripters to use.
20 |
21 | With this plugin you can write gameplay in a customized version of [Angelscript](https://www.angelcode.com/angelscript/), a simple but powerful scripting language.
22 |
23 | Some key benefits that this plugin helps achieve:
24 | * **Rapid Iteration** - Scripts can be reloaded instantly in the editor, letting developers focus on creating cool shit instead of waiting for compiles and editor restarts.
25 | * **Improved Cooperation** - Because programmers and designers are no longer separated by the C++/Blueprint divide, they can work closely together using the same systems and tools.
26 | * **Performance** - Angelscript performs significantly better than blueprint for game scripting, and approaches native C++ performance when using [transpiled scripts](/cpp-bindings/precompiled-data) in a shipping build.
27 |
28 | ## Features
29 | ### Familiar but Simplified
30 |
31 | 
32 |
33 | Programmers used to working in Unreal C++ will find the scripts instantly familiar, but with many key simplifications to make life easier for designers and avoid common C++ pitfalls.
34 |
35 | ### Script Hotreload for Fast Iteration
36 | See your changes to scripted actors and components reflected immediately when you hit save.
37 |
38 | All modifications to scripts can be reloaded without restarting the Unreal Editor.
39 | While running the game in PIE (Play In Editor), non-structural changes to the script code can also be reloaded without having to exit the play session!
40 |
41 | 
42 |
43 | ### Scripting with Full Editor Support
44 |
45 | To make scripting easier, a [Visual Studio Code Extension](https://marketplace.visualstudio.com/items?itemName=Hazelight.unreal-angelscript) is available implementing full Language Server Protocol support.
46 |
47 | This includes support for many editor features, such as:
48 | * Code Autocompletion
49 | * Error Diagnostics
50 | * Rename Symbol
51 | * Find All References
52 | * Semantic Highlighting
53 |
54 | 
55 |
56 | ### Integration with existing C++ and Blueprint workflows
57 | Angelscript classes can override any BlueprintImplementableEvent you expose from C++,
58 | and can be used seamlessly as base classes for child blueprints.
59 |
60 | Use whatever combination of tools fits your workflow best.
61 |
62 | 
63 |
64 | ### Debugging Support Through Visual Studio Code
65 | Debug your script code through the Visual Studio Code extension.
66 | Set breakpoints and inspect variables, and step through your scripts to find issues.
67 |
68 | 
--------------------------------------------------------------------------------
/content/cpp-bindings/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "C++ Usage and Bindings"
3 | weight = 40
4 | sort_by = "weight"
5 | +++
6 |
--------------------------------------------------------------------------------
/content/cpp-bindings/automatic-bindings.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Automatic Bindings"
3 | weight = 10
4 | +++
5 |
6 | # Automatic Bindings
7 | When the engine starts, the angelscript plugin automatically goes through all of unreal's reflection data.
8 |
9 | Relevant types, properties and functions from C++ are automatically given bindings into Angelscript so they can be used from your scripts.
10 |
11 | The general principle of automatic bindings is:
12 | If it can be used from Blueprint, it should be usable from Angelscript.
13 |
14 | ## Class Bindings
15 | Classes in C++ that are marked with `UCLASS()` are automatically bound either when they have the `BlueprintType` specifier, or if they contain any functions with `BlueprintCallable`.
16 |
17 | Classes can be skipped for automatic bindings by adding the `NotInAngelscript` metadata.
18 |
19 | ## Struct Bindings
20 | Structs in C++ that are marked with `USTRUCT()` are automatically bound either when they have the `BlueprintType` specifier, or if they contain any properties that are blueprint-accessible or editable.
21 |
22 | Structs can be skipped for automatic bindings by adding the `NoAutoAngelscriptBind` metadata.
23 |
24 | ## Property Bindings
25 | ### Read/Write Flags
26 | C++ `UPROPERTY`s that are declared with `BlueprintReadWrite` or `BlueprintReadOnly` are automatically bound to script.
27 |
28 | If the property is `BlueprintReadOnly`, it will become `const` and unable to be changed from script.
29 |
30 | To expose a property to Angelscript without exposing it to blueprint, you can use the `ScriptReadWrite` or `ScriptReadOnly` specifiers.
31 |
32 | ### Editable Flags
33 | Properties that are declared with any of the editable flags (`EditAnywhere`, `EditInstanceOnly` or `EditDefaultsOnly`) are also exposed to script.
34 |
35 | > **Note:** If a property has an editable flag, but not a blueprint access flag, it will **only** be accessible in script from inside a class `default` statement.
36 | > *See [Default Statements](/scripting/actors-components/#default-statements).*
37 |
38 | ### Skipping Properties
39 | Properties can be skipped for angelscript binds even if they are otherwise accessible to blueprint by adding the `NotInAngelscript` metadata.
40 |
41 | ## Function Bindings
42 | ### Callable Flags
43 | Any C++ `UFUNCTION` that has `BlueprintCallable` or `BlueprintPure` is automatically bound to script.
44 |
45 | To expose a function to Angelscript without exposing it to blueprint, you can use the `ScriptCallable` specifier.
46 |
47 | ### Blueprint Events
48 | `UFUNCTION`s with the `BlueprintImplementableEvent` and `BlueprintNativeEvent` specifiers can be overridden from script as well as blueprint.
49 |
50 | > See [Overriding BlueprintEvents from C++](/scripting/functions-and-events/#overriding-blueprintevents-from-c)
51 |
52 | ### Skipping Functions
53 | Functions can be skipped for angelscript binds even if they are otherwise accessible to blueprint by adding the `NotInAngelscript` metadata.
54 |
55 | ### Deprecated Functions
56 | Functions marked as deprecated are not bound to script at all.
57 |
58 | There is no deprecation warning functionality in script, so engine upgrades may necessitate script changes when Epic deprecates certain APIs.
59 |
60 | ## Static Functions
61 | Static functions declared on `UCLASS`es are bound as namespaced global functions in script.
62 |
63 | Note that for static functions only, the name of the class will go through [Namespace Simplification](/scripting/function-libraries/#namespace-simplification) when they are bound.
64 |
65 | ## Enum Bindings
66 | Any `UENUM()` declared in C++ is automatically usable in script.
--------------------------------------------------------------------------------
/content/cpp-bindings/mixin-libraries.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Script Mixin Libraries"
3 | weight = 10
4 | +++
5 |
6 | # Script Mixin Libraries
7 | Instead of adding new namespaced static functions for scripts, it can be useful to provide additional _methods_ on existing types.
8 |
9 | To do this, use the `ScriptMixin` metadata on a C++ class with static functions.
10 | Any static function whose first argument matches the type specified in the metadata will be bound as a method on that type.
11 |
12 | A common use case for this is to add methods to `USTRUCT`s, which cannot have `UFUNCTION`s on them, and as such cannot have methods using normal automatic bindings.
13 |
14 | ## Mixin Libraries for Structs
15 | For example, the following C++ mixin library class adds two new methods to the `FVector` struct in script:
16 |
17 | ```cpp
18 | UCLASS(Meta = (ScriptMixin = "FVector"))
19 | class UFVectorScriptMixinLibrary : public UObject
20 | {
21 | GENERATED_BODY()
22 | public:
23 |
24 | // This will be accessible in script as
25 | // FVector Vector;
26 | // Vector.ResetTo(4.0);
27 | UFUNCTION(ScriptCallable)
28 | static void ResetTo(FVector& Vector, float NewValue)
29 | {
30 | Vector = FVector(NewValue, NewValue, NewValue);
31 | }
32 |
33 | // This will become a const method, as it takes
34 | // a const reference to the mixin type:
35 | // Usable in script as both Vector.SummedValue
36 | // or Vector.GetSummedValue()
37 | UFUNCTION(ScriptCallable)
38 | static float GetSummedValue(const FVector& Vector)
39 | {
40 | return Vector.X+Vector.Y+Vector.Z;
41 | }
42 | }
43 | ```
44 |
45 | ## Mixin Libraries for Classes
46 | It is also possible to add new methods to `UCLASS`es. In that case, take a pointer to the type as the first argument.
47 |
48 | The following C++ mixin library adds a new method to all `AActor`s in script:
49 |
50 | ```cpp
51 | UCLASS(Meta = (ScriptMixin = "AActor"))
52 | class UMyActorMixinLibrary : public UObject
53 | {
54 | GENERATED_BODY()
55 | public:
56 |
57 | // This can be used in script as:
58 | // Actor.TeleportToOrigin();
59 | UFUNCTION(ScriptCallable)
60 | static void TeleportToOrigin(AActor* Actor)
61 | {
62 | Actor->SetActorLocation(FVector(0, 0, 0));
63 | }
64 | }
65 | ```
66 |
67 | > **Note:** The angelscript plugin comes with a number of mixin libraries in it, mostly to expose C++ functionality that is not normally exposed to blueprint.
68 | > For example, see the [TimelineComponentMixinLibrary](https://github.com/Hazelight/UnrealEngine-Angelscript/blob/angelscript-master/Engine/Plugins/Angelscript/Source/AngelscriptCode/Public/FunctionLibraries/TimelineComponentMixinLibrary.h)
69 |
--------------------------------------------------------------------------------
/content/cpp-bindings/precompiled-data.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Using Precompiled Scripts"
3 | weight = 100
4 | +++
5 |
6 | # Using Precompiled Scripts
7 | ## Functionality
8 | Normally, when the engine starts up the angelscript plugin will read all `.as` files in
9 | your Project's script folder and parse and compile them. This can take a relatively long
10 | amount of time, especially on platforms with slower CPUs and hard drives.
11 |
12 | In order to improve startup time in packaged builds, it is possible to instruct the
13 | packaged binary to emit a precompiled script cache. When a precompiled script
14 | cache file is present, the plugin will load the compiled script bytecode directly
15 | from the cache, skipping the need to load, parse and compile all the script
16 | files.
17 |
18 | In addition to this, the plugin is able to generate a directory of C++ code files
19 | that function the same as the angelscript bytecode for your scripts. Recompiling
20 | the game binary with these C++ files included in it will then hook into angelscript's
21 | JIT compilation system to replace virtual machine bytecode execution with native C++.
22 | This significantly improves runtime execution speed of script code.
23 |
24 | ## Usage
25 | Precompiled script must be generated by the same `.exe` binary that it will be loaded by.
26 |
27 | To trigger the generation:
28 |
29 | - Package your game in the configuration you want to run.
30 | - Run your `ProjectName.exe` while specifying the `-as-generate-precompiled-data` command line parameter.
31 |
32 | This generates a file `ProjectName/Script/PrecompiledScript.Cache` that should be part of your game distribution.
33 |
34 | The next time you run your packaged game, script will be loaded from the precompiled cache instead of from the `.as` scripts.
35 |
36 | ## Transpiled C++ Code
37 | In addition to the cache, the generate step will also output a folder called `AS_JITTED_CODE/` with a file in it for every script file that was compiled.
38 |
39 | You can copy this folder into your project's source folder and then rebuild the `.exe` for your game in the appropriate configuration.
40 |
41 | When including the `AS_JITTED_CODE/` folder in your project ensure that the module that it's being included it has `AngelscriptCode` as a dependency, i.e. within your project's Build.cs file.
42 |
43 | Using the new `.exe` compiled with the included `AS_JITTED_CODE/` and in combination with the `PrecompiledScript.Cache` file will let the
44 | angelscript plugin automatically run the correct optimized C++ code when executing angelscript.
45 |
46 | ## Compatibility
47 | Because precompiled scripts directly contain hardcoded byte offsets to C++ properties and sizes of C++ structures,
48 | you should never use a `PrecompiledScript.Cache` file that was generated by a different binary than it is being used by.
49 |
50 | Whenever you rebuild your game's packaged `.exe`, **always** regenerate the precompiled script cache from that `.exe`.
51 | (The necessary exception of course being the rebuild when you add the generated C++ code to the binary)
52 |
53 | The inverse is not necessary: it is possible to change the `.as` script files and generate a new `PrecompiledScript.Cache`
54 | without recompiling the game binary.
55 | If the old binary contained generated C++ code, it will no longer match the precompiled script cache and will not be used until the binary is rebuilt with the new `AS_JITTED_CODE`.
56 |
57 | ## Reloading Scripts
58 | When using a `PrecompiledScript.Cache` file, the actual `.as` script files are not loaded from the script folder. This means
59 | changes to those files will not be used, and hot reload is disabled.
60 |
61 | In order to circumvent loading precompiled scripts when they are present, you can pass the `-as-development-mode` command line parameter to your packaged game binary.
--------------------------------------------------------------------------------
/content/getting-started/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Getting Started"
3 | weight = 10
4 | sort_by = "weight"
5 | +++
6 |
--------------------------------------------------------------------------------
/content/getting-started/installation.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Installation"
3 | weight = 10
4 | +++
5 |
6 | # Installation
7 | ## 1. Getting Unreal Engine Source Access
8 | The angelscript integration requires direct changes to unreal engine code to work.
9 | You will need to get access to unreal engine source code to be able to access the
10 | version of the engine used in this project.
11 |
12 | To get source code access, follow this guide from Epic Games:
13 | [https://www.unrealengine.com/en-US/ue-on-github](https://www.unrealengine.com/en-US/ue-on-github)
14 |
15 |
16 | ## 2. Downloading UnrealEngine-Angelscript
17 | You can download a precompiled editor binary with angelscript from the
18 | [Releases Pages](https://github.com/Hazelight/UnrealEngine-Angelscript/releases)
19 | on github.
20 |
21 | Alternatively, clone the [GitHub Repository](https://github.com/Hazelight/UnrealEngine-Angelscript)
22 | and build the unreal editor using visual studio as usual.
23 |
24 | Note that you will need to build from source yourself if you want to use any additional plugins.
25 | This fork will not be compatible with any binary plugin distributions from the unreal marketplace.
26 |
27 |
28 | ## 3. Installing the Visual Studio Code Extension
29 | A visual studio code extension with auto-completion and debugging support is available.
30 |
31 | Install visual studio code from [https://code.visualstudio.com/](https://code.visualstudio.com/).
32 |
33 | Then install the [Unreal Angelscript Extension](https://marketplace.visualstudio.com/items?itemName=Hazelight.unreal-angelscript)
34 | from the marketplace, or search for 'Unreal Angelscript' in the extensions sidebar within Visual Studio Code.
--------------------------------------------------------------------------------
/content/getting-started/introduction.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Scripting Introduction"
3 | weight = 20
4 | +++
5 |
6 | # Scripting Introduction
7 | This introduction will run you through how to create your first Actor class in script,
8 | and how to interact with it in unreal and blueprint.
9 |
10 | ## Setup
11 | Make sure you have the following set up:
12 | * Install or compile the custom engine build for UnrealEngine-Angelscript.
13 | * Install [Visual Studio Code](https://code.visualstudio.com/).
14 | * Install the [Unreal Angelscript Extension](https://marketplace.visualstudio.com/items?itemName=Hazelight.unreal-angelscript) for visual studio code.
15 |
16 | > See the [Installation](/getting-started/installation/) page for details.
17 |
18 | ## Starting the Project
19 | * Start the custom unreal editor and open your project.
20 | Opening your project will automatically create an empty `Script/` folder inside your project folder.
21 | * Start Visual Studio Code, and from the menu `File -> Open Folder`, open your new `MyProject/Script/` folder.
22 |
23 | > **Tip:** You can also click the "Open Angelscript workspace" option from the Tools menu to automatically open the scripts folder in Visual Studio Code.
24 | > 
25 |
26 | ## Creating the Actor Class
27 | Within Visual Studio Code, create a new file and call it `IntroductionActor.as`.
28 |
29 | Files with the `.as` extension placed under your project's `Script/` folder are automatically loaded by the angelscript plugin.
30 |
31 | Inside `IntroductionActor.as`, let's declare a new Actor class:
32 |
33 |
classAIntroductionActor : AActor
{
}
34 |
35 | We've now created our first scripted Actor!
36 |
37 | ## Placing the Actor in Unreal
38 | Immediately after hitting "Save" on our script file, it should become available within the unreal editor.
39 |
40 | * Open the `Place Actors` panel (this can be found in Unreal's `Window` menu if you don't have it open already).
41 | * Search for "Introduction Actor". Your new scripted actor should appear in the list.
42 | * Place the "Introduction Actor" into your level.
43 |
44 | 
45 |
46 | ## Adding Functionality to the Actor
47 | We have a totally empty actor in the level now with no functionality.
48 | As an example, let's make this actor perform a configurable countdown:
49 |
50 |
classAIntroductionActor : AActor
{
UPROPERTY()
floatCountdownDuration = 5.0;
floatCurrentTimer = 0.0;
boolbCountdownActive = false;
UFUNCTION(BlueprintOverride)
voidBeginPlay()
{
// Start the countdown on beginplay with the configured duration
CurrentTimer = CountdownDuration;
bCountdownActive = true;
}
UFUNCTION(BlueprintOverride)
voidTick(floatDeltaSeconds)
{
if (bCountdownActive)
{
// Count down the timer
CurrentTimer -= DeltaSeconds;
if (CurrentTimer <= 0.0)
{
// The countdown was complete!
// Print a message to the screen
Print("Countdown was completed!");
bCountdownActive = false;
}
}
}
}
51 |
52 | Some of the important things that are happening here:
53 | * The `CountdownDuration` variable has been declared as a `UPROPERTY()`, this makes it configurable from the Unreal editor. You can select the actor in the level and change the countdown duration to be higher or lower than the default 5 seconds.
54 | *See the documentation on [Properties and Accessors](/scripting/properties-and-accessors/)*
55 | 
56 | * We override the `BeginPlay` and `Tick` events to implement functionality on the actor.
57 | *See the documentation on [Functions and BlueprintEvents](/scripting/functions-and-events/)*
58 | * When BeginPlay happens, we start our countdown.
59 | * When Tick happens, we count down the countdown and check if it's complete.
60 | * After the countdown is done, we use `Print()` to show a message on screen.
61 |
62 | Now, if you play the level the actor is placed in and wait 5 seconds, you will see the message appear:
63 | 
64 |
65 | ## Adding Components to the Actor
66 | Right now, our Actor is still empty of any components, and only implements some functionality on tick.
67 |
68 | Let's add some components to it! We want a `Scene Component` as the root, and then attach a `Static Mesh Component` and a `Billboard Component` to it.
69 |
70 | Add the following at the top of your actor code:
71 |
72 |
classAIntroductionActor : AActor
{
UPROPERTY(DefaultComponent, RootComponent)
USceneComponentSceneRoot;
UPROPERTY(DefaultComponent, Attach = SceneRoot)
UStaticMeshComponentMesh;
UPROPERTY(DefaultComponent, Attach = SceneRoot)
UBillboardComponentBillboard;
....
73 |
74 | When you save your script file, you should see the new components appear on the Introduction Actor you've placed in the level.
75 |
76 | You can read more about adding components on the [Actors and Components](/scripting/actors-components/) page.
77 |
78 | 
79 |
80 | > **Tip:** Clicking one of the *"Edit in C++"* links in the components menu will jump your Visual Studio Code to the place the component is added in your script.
81 | > The angelscript plugin often hooks into Unreal's normal C++ functionality, so script classes behave like C++ classes in many ways.
82 |
83 |
84 | ## Creating a Blueprint Actor
85 | The actor now has a Static Mesh Component, but we can't see it because no Static Mesh has been chosen on it!
86 |
87 | We could of course select the actor in the level and choose one, but we don't want to do that for each actor we place individually.
88 |
89 | Instead, let's create a Blueprint of our new introduction actor:
90 |
91 | * Open the Content Browser, and click `Add -> Blueprint Class`, to use the normal way to create a new blueprint.
92 | * When asked to pick a Parent Class, search for our "Introduction Actor" and select it:
93 | 
94 | * Let's call our new blueprint `BP_IntroductionActor`, so it's clear that we're dealing with an actor blueprint.
95 | * Now we can open our new blueprint and choose a mesh for its Static Mesh Component.
96 | Here I am choosing the engine's standard `SM_Cube` mesh, but feel free to choose one of your own.
97 | 
98 | * Make sure to remove the existing `IntroductionActor` from your level, and place a new `BP_IntroductionActor` in the level so we can see it!
99 |
100 | ## Calling in and out of Blueprint
101 | Now that we have a blueprint, we can change the script to work together with its node graph:
102 | * We will change the actor so the countdown is no longer started right away, but requires a function call to start it.
103 | * We also add an overridable blueprint event so our actor blueprint can be notified when the countdown is finished.
104 |
105 | In our `IntroductionActor.as`, change the script code for its BeginPlay and Tick functions to this:
106 |
107 |
UFUNCTION(BlueprintOverride)
voidBeginPlay()
{
// We no longer start the countdown on BeginPlay automatically
}
UFUNCTION()
voidStartCountdown()
{
// Start the countdown when StartCountdown() is called
CurrentTimer = CountdownDuration;
bCountdownActive = true;
}
/**
* Declare an overridable event so the actor blueprint can
* respond when the countdown finishes
*/
UFUNCTION(BlueprintEvent)
voidFinishedCountdown() {}
UFUNCTION(BlueprintOverride)
voidTick(floatDeltaSeconds)
{
if (bCountdownActive)
{
// Count down the timer
CurrentTimer -= DeltaSeconds;
if (CurrentTimer <= 0.0)
{
// The countdown was complete!
// Print a message to the screen
Print("Countdown was completed!");
// Also: trigger a blueprint event
FinishedCountdown();
bCountdownActive = false;
}
}
}
108 |
109 | After saving this change, we can now open `BP_IntroductionActor`, and add nodes like this:
110 |
111 | 
112 |
113 | Now, the blueprint must specifically start the countdown, and when the countdown is finished the blueprint will automatically destroy the actor.
114 |
115 | If you play the level with the blueprint placed, you will see it disappear after 5 seconds.
116 |
117 | # Script Examples
118 | The `UnrealEngine-Angelscript` project contains a `Script-Examples/` folder.
119 | Here, you can find more detailed example scripts that you can read or copy to your project.
120 |
121 | * One good place to start is the [Example_MovingObject.as](https://github.com/Hazelight/UnrealEngine-Angelscript/blob/angelscript-master/Script-Examples/Examples/Example_MovingObject.as) actor example.
122 |
123 | * You can also look through the [Examples Folder on Github](https://github.com/Hazelight/UnrealEngine-Angelscript/tree/angelscript-master/Script-Examples/Examples).
124 |
125 | # Further Reading
126 | More documentation is available on this website in the sidebar to the left.
127 |
128 | We recommend reading through at least the "Script Features" pages to get an overview of what can be done in scripts.
129 |
130 | Some good starting points are:
131 |
132 | * [Functions and BlueprintEvents](/scripting/functions-and-events/)
133 | * [Function Libraries](/scripting/function-libraries/)
134 | * [Differences with Unreal C++](/scripting/cpp-differences/)
--------------------------------------------------------------------------------
/content/project/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "UE-AS Development"
3 | weight = 50
4 | sort_by = "weight"
5 | +++
6 |
--------------------------------------------------------------------------------
/content/project/development-status.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Development Status"
3 | weight = 10
4 | +++
5 |
6 | # Development Status
7 | At [Hazelight](http://hazelight.se), this project's angelscript integration
8 | has been actively used for game development since early 2018. It is being used daily by 30+ developers on our team.
9 |
10 | Our two latest games, [Split Fiction](https://www.ea.com/games/split-fiction/split-fiction) and [It Takes Two](https://www.ea.com/games/it-takes-two), were both shipped with the majority of their gameplay written in angelscript.
11 | Split Fiction contains over 1,700,000 lines of angelscript code, written in more than 16,000 script files.
12 |
13 | Hazelight does not guarantee any maintenance or support beyond what
14 | is already provided on this site. If you are considering using the
15 | angelscript integration in a commercial project, we highly recommend
16 | having an engine programmer available to investigate issues that may occur
17 | in your usage of it.
18 |
19 |
20 | ## Platform Support
21 | The plugin is regularly used and tested at Hazelight on the Windows, PS5, and Xbox Series X|S platforms.
22 | Other studios have successfully built and ran it on other platforms not tested internally by Hazelight.
23 |
24 | If you have any questions about other platforms, feel free to [join our discord server](https://discord.gg/39wmC2) and ask around.
25 |
26 |
27 | ## Known Limitations
28 | * `Super::Function()` calls only work for parent functions in angelscript. It is not possible to call the C++ super function when overriding a BlueprintNativeEvent.
29 | * Unreal Interfaces (IInterface/UInterface) are not supported for use in angelscript.
--------------------------------------------------------------------------------
/content/project/license.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "License"
3 | weight = 20
4 | +++
5 |
6 | # License
7 |
8 | Unreal Engine itself is proprietary software, and you must obtain a valid license from Epic Games
9 | to use it or any of the modifications this project makes directly to engine code.
10 |
11 | The Angelscript library's source code and all modifications made directly to it in this project are distributed
12 | under the open-source [zlib license](https://www.angelcode.com/angelscript/sdk/docs/manual/doc_license.html).
13 |
14 | The UnrealEngine-Angelscript plugin code in this project is distributed under the standard MIT open source license.
15 |
16 | For more information on licensing, see the `LICENSE.md` file contained within the UnrealEngine-Angelscript project's source.
--------------------------------------------------------------------------------
/content/project/resources.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Resources and Links"
3 | weight = 15
4 | +++
5 |
6 | # Resources and Links
7 | ## Games Using UnrealEngine-Angelscript
8 | * [It Takes Two](https://www.ea.com/games/it-takes-two), by [Hazelight](https://hazelight.se) (2021)
9 | * [The Talos Principle 2](https://www.thetalosprinciple.com/), by [Croteam](http://www.croteam.com/) (2023)
10 | * [THE FINALS](https://www.reachthefinals.com/), by [Embark Studios](https://www.embark-studios.com/) (2023)
11 | * [Archons](https://store.steampowered.com/app/2779570/Archons/), by [BulletHell Studios](https://www.bullethellstudios.com/) (2024)
12 | * [Split Fiction](https://www.ea.com/games/split-fiction/split-fiction), by [Hazelight](https://hazelight.se) (2025)
13 | * [ARC Raiders](https://www.arcraiders.com/), by [Embark Studios](https://www.embark-studios.com/) (TBA)
14 |
15 | ## Documentation and Examples
16 | * [Creating Widgets with Unreal & Angelscript](https://www.predictable-paul.com/blog/unreal-angelscript-widgets/)
17 | A nice overview on how to interact with UMG widget blueprints through script
18 |
19 | ## Development Resources
20 | * [Unreal Angelscript Clang-Format](https://marketplace.visualstudio.com/items?itemName=Hazelight.unreal-angelscript-clang-format)
21 | Extension for vscode to use clang-format to format UE-AS scripts
22 | * [GameplayMessageRouter with Angelscript](https://github.com/IncantaUnreal/GameplayMessageRouter)
23 | GameplayMessageRouter plugin from the Lyra sample project with added angelscript bindings
24 |
25 | ## Videos
26 | * [Building Tools Quickly: Blueprints, Menus, Utilities, and Widgets | Unreal Fest 2022 (Youtube)](https://www.youtube.com/watch?v=wJqOn88cU7o)
27 | From Embark Studios about their internal tooling, touches a bit on Angelscript usage
28 |
29 | ## Community
30 | * [UnrealEngine-Angelscript Discord Server](https://discord.gg/39wmC2e)
31 |
32 | ## UnrealEngine-Angelscript Development
33 | * [UnrealEngine-Angelscript (GitHub)](https://github.com/Hazelight/UnrealEngine-Angelscript/tree/angelscript-master)
34 | Main development repository for the UE-AS plugin and engine divergences
35 | * [vscode-unreal-angelscript (GitHub)](https://github.com/Hazelight/vscode-unreal-angelscript)
36 | Source code repository for the vscode extension for UnrealEngine-Angelscript
37 | * [Docs-UnrealEngine-Angelscript (GitHub)](https://github.com/Hazelight/Docs-UnrealEngine-Angelscript)
38 | Source text for this documentation website
39 |
--------------------------------------------------------------------------------
/content/scripting/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Script Features"
3 | weight = 20
4 | sort_by = "weight"
5 | insert_anchor_links = "right"
6 | +++
7 |
--------------------------------------------------------------------------------
/content/scripting/actors-components.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Actors and Components"
3 | weight = 25
4 | sort_by = "weight"
5 | +++
6 |
7 | # Actors and Components
8 | Actors and components are two of the fundamental gameplay types in unreal code.
9 |
10 | Creating a new actor or component type in script is as simple as creating a new script file and adding a class that inherits from an actor type:
11 |
12 |
classAMyActor : AActor
{
}
classUMyComponent : UActorComponent
{
}
13 |
14 | > **Note:** The script plugin automatically sets the most useful class flags for any script classes, adding a `UCLASS()` specifier is not necessary in script, but can still optionally be used to configure additional class settings.
15 |
16 | ## Default Components
17 | Unlike in C++, script classes do not make use of their constructors for creating components.
18 | To add a default component to the actor, use the `DefaultComponent` specifier for them.
19 | Default components are automatically created on the actor when it is spawned.
20 |
21 | The following class will have two components on it when placed. A scene component at the root, and the custom `UMyComponent` we declared before:
22 |
23 |
classAExampleActor : AActor
{
UPROPERTY(DefaultComponent)
USceneComponentSceneRoot;
UPROPERTY(DefaultComponent)
UMyComponentMyComponent;
}
24 |
25 | ## Component Attachments
26 | Likewise, the default attachment hierarchy is specified in `UPROPERTY` specifiers, rather than set up in a constructor. Use the `Attach =` and `AttachSocket =` specifiers.
27 |
28 | If an explicit attachment is not specified, the component will be attached to the actor's root.
29 |
30 |
classAExampleActor : AActor
{
// Explicit root component
UPROPERTY(DefaultComponent, RootComponent)
USceneComponentSceneRoot;
// Will be attached to SceneRoot by default, as no attachment is specified
UPROPERTY(DefaultComponent)
USkeletalMeshComponentCharacterMesh;
// Will be attached to the CharacterMesh' RightHand socket
31 |
32 | 
33 |
34 | > **Note:** You can explicitly note which component should be the default root component with the `RootComponent` specifier. If you do not add this specifier, the first component to be created will become the root.
35 |
36 | ## Default Statements
37 | To assign default values to properties on the actor's components, you can use `default` statements:
38 |
39 |
classAExampleActor : AActor
{
UPROPERTY(DefaultComponent, RootComponent)
USceneComponentSceneRoot;
UPROPERTY(DefaultComponent)
USkeletalMeshComponentCharacterMesh;
// The character mesh is always placed a bit above the actor root
40 |
41 | ## Working with Components
42 | ### Retrieving Components
43 | If you have an actor and want to find a component of a type on it, use `UMyComponentClass::Get()`:
44 |
45 |
AActorActor;
// Retrieve the first skeletal mesh component we can find on the actor
46 |
47 | If no component of the specified type exists, this will return `nullptr`.
48 |
49 | Use `UMyComponentClass::GetOrCreate()` to retrieve a potential existing component, or create it if one does not exist already:
50 |
51 |
// Find our own interaction handling component on the actor.
52 |
53 | ### Adding New Components
54 | Creating a new component works similarly by calling `UMyComponentClass::Create()`.
55 | Specifying a component name is optional, if none is specified one will be automatically generated.
56 |
57 |
ACharacterCharacter;
// Create a new static mesh component on the character and attach it to the character mesh
58 |
59 | > **Tip:** If you have a dynamic `TSubclassOf<>` or `UClass` for a component class, you can also use the generic functions on actors for these operations by using
60 | > `Actor.GetComponent()`, `Actor.GetOrCreateComponent()`, or `Actor.CreateComponent()`
61 |
62 | ## Spawning Actors
63 | Actors can be spawned by using the global `SpawnActor()` function:
64 |
65 |
// Spawn a new Example Actor at the specified location and rotation
66 |
67 | ### Spawning a Blueprinted Actor
68 | It is often needed to dynamically spawn an actor blueprint, rather than a script actor baseclass.
69 | To do this, use a `TSubclassOf<>` property to reference the blueprint, and use the global `SpawnActor()` function.
70 |
71 | An example of a spawner actor that can be configured to spawn any blueprint of an example actor:
72 |
73 |
classAExampleSpawner : AActor
{
/**
* Which blueprint example actor class to spawn.
* This needs to be configured either in the level,
74 |
75 |
76 | ## Construction Script
77 | Actor construction script can be added by overriding the `ConstructionScript()` blueprint event.
78 | From construction scripts, you can create new components and override properties like normal.
79 |
80 | For example, an actor that creates a variable amount of meshes inside it based on its settings in the level could look like this:
81 |
82 |
classAExampleActor : AActor
{
// How many meshes to place on the actor
UPROPERTY()
intSpawnMeshCount = 5;
// Which static mesh to place
UPROPERTY()
UStaticMeshMeshAsset;
UFUNCTION(BlueprintOverride)
voidConstructionScript()
{
Print(f"Spawning {SpawnMeshCount} meshes from construction script!");
83 |
84 | ## Getting All Actors or Components
85 | To get all components of a particular type that are on an actor, use `Actor.GetComponentsByClass()` and pass in the array.
86 | This function takes a `?` parameter, and will determine which component type to look for by the type of array you pass in.
87 |
88 | For example, to get all static meshes on an actor:
89 |
90 |
for (UStaticMeshComponentMeshComp : StaticMeshComponents)
{
Print(f"Static Mesh Component: {MeshComp.Name}");
}
91 |
92 | Similarly, to get all actors of a particular type that are currently in the world, use the `GetAllActorsOfClass()` global function, and pass in an array of the type of actor you want:
93 |
94 |
// Find all niagara actors currently in the level
TArray<ANiagaraActor> NiagaraActors;
GetAllActorsOfClass(NiagaraActors);
95 |
96 | > **Note:** Getting all actors of a class requires iterating all actors in the level, and should not be used from performance-sensitive contexts.
97 | > That is, try running it once and storing the value rather than using it every tick.
98 |
99 | ## Override Components
100 | Unreal provides a mechanism for overriding one of a parent actor class' default components to use a child component class instead of the one specified on the parent actor.
101 | In script, this can be accessed by using the `OverrideComponent` specifier:
102 |
103 |
classABaseActor : AActor
{
// This base actor specifies a root component that is just a scene component
UPROPERTY(DefaultComponent, RootComponent)
USceneComponentSceneRoot;
}
classAChildActor : ABaseActor
{
/**
* Because static meshes are a type of scene component,
* we can use an override component to turn the base class' root
* scene component into a static mesh.
*/
UPROPERTY(OverrideComponent = SceneRoot)
UStaticMeshComponentRootStaticMesh;
}
104 |
105 | > **Note:** Override components are similar to using `ObjectInitializer.SetDefaultSubobjectClass()` in a C++ constructor.
--------------------------------------------------------------------------------
/content/scripting/cpp-differences.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Differences with Unreal C++"
3 | weight = 300
4 | sort_by = "weight"
5 | +++
6 |
7 | # Overview of Differences for C++ Unreal Developers
8 | While the script files will feel familiar to developers used to working in C++ with Unreal, there are a number of differences.
9 | Most of the differences are intended to simplify the script language for people coming in from using Blueprint.
10 |
11 | Some differences you will most likely run into are highlighted here.
12 |
13 | ## Objects Instead of Pointers
14 | Any variable declared with a `UObject` type is automatically an object reference. Pointers do not exist in the script language.
15 | This is similar to how object reference variables work in blueprint.
16 | There is no `->` arrow operator in script, everything happens with `.` dots.
17 |
18 | > **Note:** Unlike in C++, it is **not** necessary to declare a property as `UPROPERTY()` in order to avoid it being garbage collected. All object references in script are automatically inserted into the GC.
19 |
20 |
21 |
22 | ## Default Accessibility for Properties
23 | `UPROPERTY()` variables are `EditAnywhere` and `BlueprintReadWrite` by default. This can be overridden by specifying `NotBlueprintCallable` or `NotEditable`.
24 |
25 | The default access specifiers for properties in script can be configured from Project Settings.
26 |
27 | The intent of this is to simplify property specifiers. Since `UPROPERTY()` is not needed for correct garbage collection, you should only specify it when you want it to be accessible in the editor/blueprint.
28 |
29 | ## Default Callability for Functions
30 | Functions declared with `UFUNCTION()` are `BlueprintCallable` by default, even when this is not specified explicitly.
31 | This is intended to simplify function declarations, as making a script function a `UFUNCTION()` is generally already an indicator of wanting it to be called from blueprint.
32 |
33 | This behavior can be turned off from Project Settings, if you prefer requiring `BlueprintCallable` to be explicit.
34 |
35 | ## Use the `default` Keyword Instead of Constructors
36 | Instead of using object constructors, which can run at unpredictable times during hot reloads, any default values for properties should be specified in the class body.
37 |
38 | For setting values on subobjects, use the `default` keyword:
39 |
40 |
classAExampleActor : AActor
{
// Set default values for class properties in the class body
UPROPERTY()
floatConfigurableValue = 5.0;
// Set default values for subobjects with `default` statements
41 |
42 | ## Floating Point Width
43 | With Unreal 5.0, Epic has started using `double`s for all gameplay-related vectors, rotators, etc.
44 | Rather than confuse people that are used to working with `float` in blueprint, they decided to keep calling these doubles `float` everywhere in the editor like before.
45 |
46 | The angelscript integration follows this decision, meaning that when you declare a `float` in script, it is actually a 64-bit double value.
47 | To create a floating-point variable with a specific width, you can explicitly use the `float32` or `float64` types.
48 |
49 |
floatValueDouble = 1.0; // <-- This is a 64-bit double-precision float
float32ValueSingle = 1.f; // <-- This is a 32-bit single-precision float
float64ValueAlsoDouble = 1.0; // <-- This is *also* a 64-bit double-precision float
--------------------------------------------------------------------------------
/content/scripting/delegates.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Delegates and Events"
3 | weight = 100
4 | sort_by = "weight"
5 | +++
6 |
7 | # Delegates
8 | You must first declare a delegate type to indicate what parameters and return value your delegate wants.
9 | In global scope:
10 |
11 |
// Declare a new delegate type with this function signature
16 |
17 | > **Note:** A `delegate` declaration is equivalent to a `DECLARE_DYNAMIC_DELEGATE()` macro in C++.
18 | > Functions bound to delegates are required to be declared as `UFUNCTION()`.
19 |
20 | # Events
21 | Events are similar to delegates, but can have multiple functions added to them, rather than always being bound to only one function.
22 |
23 | Declare events with the `event` keyword in global scope, then use `AddUFunction()` and `Broadcast()`:
24 |
25 |
eventvoidFExampleEvent(intCounter);
classAEventExample : AActor
{
UPROPERTY()
FExampleEventOnExampleEvent;
privateintCallCounter = 0;
UFUNCTION(BlueprintOverride)
voidBeginPlay()
{
// Add two functions to be called when the event is broadcast
26 |
27 | > **Note:** An `event` declaration is equivalent to a `DECLARE_DYNAMIC_MULTICAST_DELEGATE()` macro in C++.
28 | > Functions added to events are required to be declared as `UFUNCTION()`.
29 |
30 | ## Events in Blueprint
31 | By declaring `OnExampleEvent` as a `UPROPERTY()` in the previous example, we allow it to be accessed from blueprint.
32 | For events this means it will appear in the `Event Dispatchers` list for actors in the level, and we can bind it from the level blueprint:
33 |
34 | 
35 |
36 | ## Tip: Automatic signature generation in Visual Studio Code
37 | If you bind a delegate or add a function to an event, and the function does not exist yet, the visual studio code extension will try to offer to create it for you.
38 |
39 | Click the lightbulb icon or press Ctrl + ., and select the `Generate Method` option from the code actions dropdown:
40 |
41 | 
--------------------------------------------------------------------------------
/content/scripting/editor-script.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Editor-Only Script"
3 | weight = 110
4 | sort_by = "weight"
5 | +++
6 |
7 | # Editor-Only Script
8 | Some properties, functions, or classes from C++ are only available in the editor.
9 | If you try to use them in a cooked game, the script will fail to compile.
10 |
11 | This could be things like actor labels, editor subsystems or visualizers, etc.
12 |
13 | ## Preprocessor Blocks
14 | If you need to use editor-only code within a class, you can use the `#if EDITOR` preprocessor statement around the code.
15 | Any code within these blocks is not compiled outside of the editor, and can safely use editor-only functionality.
16 |
17 |
classAExampleActor : AActor
{
#if EDITOR
defaultPivotOffset = FVector(0, 0, 10);
#endif
UFUNCTION(BlueprintOverride)
voidConstructionScript()
{
#if EDITOR
SetActorLabel("Example Actor Label");
#endif
}
}
18 |
19 | > **Tip:** Other useful macro conditions:
20 | > `EDITORONLY_DATA` - Whether properties that are only relevant to the editor are readable.
21 | > `RELEASE` - Whether the game is built in either the Shipping or Test build configurations.
22 | > `TEST` - Whether the game is built in Debug, Development, or Test build configurations.
23 |
24 | ## Editor-Only Directories
25 | It is also possible for complete scipt files to be skipped outside of the editor.
26 | Any folder named `Editor` will be completely ignored by the script compiler in cooked builds.
27 | This can be useful to put for example editor visualizer or subsystem classes under an `Editor` folder.
28 |
29 | In addition to the `Editor` folder, the two other folder names `Examples` and `Dev` are also ignored in cooked builds.
30 |
31 | # Testing with Simulate-Cooked Mode
32 | Because of editor-only scripts, it's possible to have scripts in your project that work and compile in the editor, but will fail once the game is cooked.
33 | To make it easier to detect these errors - for instance in a CI task - you can use the `-as-simulate-cooked` command line parameter.
34 |
35 | When simulate cooked mode is active, editor-only properties and classes are not available in script, and `#if EDITOR` blocks are compiled out.
36 |
37 | You can use this in combination with the `AngelscriptTest` commandlet to make sure everything compiles.
38 | An unreal command line to test whether the scripts compile might look like:
39 | ```sh
40 | UnrealEditor-Cmd.exe "MyProject.uproject" -as-simulate-cooked -run=AngelscriptTest
41 | ```
--------------------------------------------------------------------------------
/content/scripting/fname-literals.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "FName Literals"
3 | weight = 50
4 | sort_by = "weight"
5 | +++
6 |
7 | # FName Literals
8 | A lot of unreal systems use `FName` to efficiently pass around arbitrary
9 | names without having to copy and compare strings a lot. The name struct itself
10 | is just an index into a name table, and creating an `FName` from a string does
11 | a table lookup or inserts a new entry into the table.
12 |
13 | A common pattern in C++ is to declare a global/static variable for an `FName`
14 | constant to use, so that the name table lookup only happens once at startup.
15 |
16 | In angelscript, this pattern is simplified by using name literals.
17 | Any string that is declared as `n"NameLiteral"` will be
18 | initialized at angelscript compile time, removing
19 | the nametable lookup from runtime.
20 |
21 | Name literals have many uses. An example of using a name literal to bind
22 | a delegate to a `UFUNCTION()` in angelscript:
23 |
24 |
// Due to the name literal, no string manipulation happens
// in calls to UseNameLiteral() during runtime.
}
UFUNCTION()
voidFunctionBoundToDelegate()
{
Print("Delegate executed");
}
}
--------------------------------------------------------------------------------
/content/scripting/format-strings.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Formatted Strings"
3 | weight = 60
4 | sort_by = "weight"
5 | +++
6 |
7 | # Formatted Strings
8 | Scripts have support for writing formatted string literals in order to place the value of variables or expressions within a string.
9 | This can be especially useful for logging or debugging.
10 |
11 | The syntax and format specifiers are heavily inspired by [Python's f-string feature](https://peps.python.org/pep-0498/).
12 |
13 | Formatted strings are declared with the prefix `f""`, and expression values to interpolate are contained within `{}`.
14 | Curly braces inside formatted strings can be escaped by doubling up. That is, `f"{{"` is equivalent to `"{"`.
15 |
16 | An example of some of the usages:
17 |
18 |
// Format Strings begin with f" and can hold expressions
// inside braces to replace within the string.
Print(f"Called from actor {GetName()} at location {ActorLocation}");
// Adding a = at the end of the expression will print the expression first
// For example:
Print(f"{DeltaSeconds=}");
// This prints:
// DeltaSeconds = 0.01
// Format specifiers can be added following similar syntax to python's f-strings:
Print(f"Three Decimals: {ActorLocation.Z :.3}"); // Format float at three decimals of precision
Print(f"Extended to 10 digits with leading zeroes: {400 :010d}"); // 0000000400
--------------------------------------------------------------------------------
/content/scripting/function-libraries.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Function Libraries"
3 | weight = 30
4 | sort_by = "weight"
5 | +++
6 |
7 | # Function Libraries
8 | Interacting with unreal from scripts often happens through function libraries.
9 | These are exposed to script as namespaces containing a set of related functions.
10 |
11 | For example, to set a timer you can call `System::SetTimer()`:
12 |
13 |
14 |
15 | ## Common Libraries
16 | Clicking the library will bring you to the API documentation for them, listing the available functions:
17 |
18 | * [Math::](/api/index.html#CClass:Math) - All standard math functionality
19 | * [Gameplay::](/api/index.html#CClass:Gameplay) - Game functionality such as streaming, damage, player handling
20 | * [System::](/api/index.html#CClass:System) - Engine functionality such as timers, traces, debug rendering
21 | * [Niagara::](/api/index.html#CClass:Niagara) - Spawning and controlling particle systems
22 | * [Widget::](/api/index.html#CClass:Widget) - UMG widget functionality
23 |
24 | ## Namespace Simplification
25 | The functions for function libraries in script are automatically taken from blueprint function library classes in C++.
26 |
27 | Before binding, the angelscript plugin simplifies the name of the class to make a shorter namespace.
28 | For example, the functions in the `System::` namespace are automatically sourced from the `UKismetSystemLibrary` class in C++.
29 |
30 | Common prefixes and suffixes that get stripped automatically are:
31 | * U...Statics
32 | * U...Library
33 | * U...FunctionLibrary
34 | * UKismet...Library
35 | * UKismet...FunctionLibrary
36 | * UBlueprint...Library
37 | * UBlueprint...FunctionLibrary
38 |
39 | For some examples of how namespaces are simplified:
40 | * `UNiagaraFunctionLibrary` becomes `Niagara::`
41 | * `UWidgetBlueprintLibrary` becomes `Widget::`
42 | * `UKismetSystemLibrary` becomes `System::`
43 | * `UGameplayStatics` becomes `Gameplay::`
44 |
45 | # Math Library
46 | Because blueprint and C++ have fairly different ways of doing math code, we have decided to keep the `Math::` namespace in script closer to the C++ `FMath::` namespace in general.
47 |
48 | Sticking closer to C++ math eases the transition for experienced programmers and lets code be ported between the two more easily.
49 |
50 | This means that `UKismetMathLibrary` gets ignored for automatic binding.
--------------------------------------------------------------------------------
/content/scripting/functions-and-events.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Functions and BlueprintEvents"
3 | weight = 10
4 | sort_by = "weight"
5 | +++
6 |
7 | # Functions and BlueprintEvents
8 | ## Plain Script Functions
9 | Functions can be declared as methods in a class or globally.
10 | By default any function you declare can only be called from script and is not accessible to blueprint.
11 |
12 |
classAExampleActor : AActor
{
voidMyMethod()
{
MyGlobalFunction(this);
}
}
voidMyGlobalFunction(AActorActor)
{
if (!Actor.IsHidden())
{
Actor.DestroyActor();
}
}
13 |
14 | ## Functions that can be called from Blueprint
15 | To make it so a function can be called from blueprint, add a `UFUNCTION()` specifier above it.
16 |
17 |
classAExampleActor : AActor
{
UFUNCTION()
voidMyMethodForBlueprint()
{
Print("I can be called from a blueprint!");
}
}
18 |
19 | > **Note:** Unlike in C++, it is not necessary to specify `BlueprintCallable`, it is assumed by default.
20 |
21 | ## Overriding BlueprintEvents from C++
22 | To override a Blueprint Event declared from a C++ parent class, use the `BlueprintOverride` specifier.
23 | You will use this often to override common events such as `BeginPlay` or `Tick`:
24 |
25 |
classAExampleActor : AActor
{
UFUNCTION(BlueprintOverride)
voidBeginPlay()
{
Print("I am a BeginPlay override");
}
UFUNCTION(BlueprintOverride)
voidTick(floatDeltaSeconds)
{
Print("I get called every tick");
}
}
26 |
27 | The visual studio code extension has helpers for easily overriding blueprint events from parent classes.
28 |
29 | When the cursor is within a class, you can click the Lightbulb icon (or press Ctrl + . by default) to choose a function to override:
30 |
31 | 
32 |
33 | Typing the name of an overridable event also suggests a completion for the full function signature:
34 |
35 | 
36 |
37 | > **Note:** For C++ functions that don't explicitly specify a `ScriptName` meta tag, some name simplification is automatically done to remove common prefixes.
38 | > For example, the C++ event is called `ReceiveBeginPlay`, but the preceeding `Receive` is removed and it just becomes `BeginPlay` in script.
39 | > Other prefixes that are removed automatically are `BP_`, `K2_` and `Received_`.
40 |
41 | ## Overriding a Script Function from Blueprint
42 | Often you will want to create a blueprint that inherits from a script parent class.
43 | In order to make a function so it can be overridden from a child blueprint, add the `BlueprintEvent` specifier.
44 |
45 |
classAExampleActor : AActor
{
UFUNCTION(BlueprintEvent)
voidOverridableFunction()
{
Print("This will only print if not overridden from a child BP.");
}
}
46 |
47 | > **Note:** Script has no split between `BlueprintImplementableEvent` and `BlueprintNativeEvent`
48 | > like C++ has. All script functions require a base implementation, although it can be left empty.
49 |
50 | ### Tip: Separate Blueprint Events
51 | One pattern that is employed often in Unreal is to have separate base and blueprint events.
52 | This way you can guarantee that the script code always runs in addition to nodes in the child blueprint, and you will never run into issues if the blueprint hasn't done "Add call to parent function".
53 |
54 | For example, a pickup actor might do:
55 |
56 |
classAExamplePickupActor : AActor
{
voidPickedUp()
{
// We always want this script code to run, even if our blueprint child wants to do something too
Print(f"Pickup {this} was picked up!");
SetActorHiddenInGame(false);
// Call the separate blueprint event
BP_PickedUp();
}
// Allows blueprints to add functionality, does not contain any code
57 |
58 | 
59 |
60 | ## Global Functions
61 | Any script function in global scope can also have `UFUNCTION()` added to it.
62 | It will then be available to be called from any blueprint like a static function.
63 |
64 | This lets you create functions not bound to a class, similar to how Blueprint Function Libraries work.
65 |
66 |
// Example global function that moves an actor somewhat
67 |
68 | 
69 |
70 | > **Tip:** Comments above function declarations become tooltips in blueprint, just like in C++
71 |
72 | ## Calling Super Methods
73 | When overriding a script function with another script function, you can use the same `Super::` syntax from Unreal to call the parent function.
74 | Note that script methods can be overridden without needing `BlueprintEvent` on the base function (all script methods are virtual). However, when overriding a `BlueprintEvent`, you *will* need to specify `BlueprintOverride` on the overrides.
75 |
76 |
77 |
78 | > **Note:** When overriding a C++ `BlueprintNativeEvent`, it is not possible to call the C++ Super method due to a technical limitation. You can either prefer creating `BlueprintImplementableEvent`s, or put the base implementation in a separate callable function.
79 |
--------------------------------------------------------------------------------
/content/scripting/gameplaytags.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Gameplay Tags"
3 | weight = 105
4 | sort_by = "weight"
5 | +++
6 |
7 | # Gameplay Tags
8 |
9 | Gameplay Tags are used in many unreal systems. See the [Unreal Documentation on Gameplay Tags](https://docs.unrealengine.com/5.1/en-US/using-gameplay-tags-in-unreal-engine/) for more details.
10 |
11 | All `FGameplayTag` will automatically be bound to the global namespace `GameplayTags`. All non-alphanumeric characters, including the dot separators, are turned into underscore `_`.
12 |
13 |
// Assuming there is a GameplayTag named "UI.Action.Escape"
--------------------------------------------------------------------------------
/content/scripting/mixin-methods.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Mixin Methods"
3 | weight = 100
4 | sort_by = "weight"
5 | +++
6 |
7 | # Mixin Methods
8 | It's possible in script to declare a method on a type outside the class body.
9 | This can be useful either to add methods to types from C++, or to separate out functionality from different systems.
10 |
11 | To do this, declare a global function with the `mixin` keyword.
12 | The first parameter of the mixin function is filled with the object it is called on.
13 |
14 |
// Mixin method that teleports any actor
// The first, 'Self' parameter gets set to the actor it is called on
15 |
16 | When creating mixins for structs, you can take a reference to the struct as the first parameter.
17 | This allows changes to be made to it:
18 |
19 |
mixinvoidSetVectorToZero(FVector& Vector)
{
Vector = FVector(0, 0, 0);
}
voidExample_StructMixin()
{
FVectorLocalValue;
LocalValue.SetVectorToZero();
}
20 |
21 | > **Note:** It is also possible to create mixin functions from C++ with bindings.
22 | > See [Script Mixin Libraries](/cpp-bindings/mixin-libraries) for details.
--------------------------------------------------------------------------------
/content/scripting/networking-features.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Networking Features"
3 | weight = 80
4 | sort_by = "weight"
5 | +++
6 |
7 | # Unreal Networking Features
8 | Unreal networking features are supported to a similar extent as they are in blueprint.
9 |
10 | `UFUNCTION()`s can be marked as `NetMulticast`, `Client`, `Server` and/or `BlueprintAuthorityOnly`
11 | in their specifiers, functioning much the same as they do in C++. The function body will
12 | automatically be used as an RPC, whether calling it from angelscript or blueprint.
13 |
14 | Unlike C++, angelscript RPC functions default to being reliable. If you want an unreliable
15 | RPC message, put the `Unreliable` specifier in the `UFUNCTION()` declaration.
16 |
17 | `UPROPERTY()`s can be marked as `Replicated`. Optionally, you can set a condition for
18 | their replication as well, similar to the dropdown for blueprint properties. This can be
19 | done with the `ReplicationCondition` specifier.
20 |
21 | Similar to C++ and Blueprint networking, in order for RPCs and replicated properties to
22 | work, the actor and component need to be set to replicate. In angelscript this can
23 | be done using `default` statements.
24 |
25 | Example:
26 |
27 |
classAReplicatedActor : AActor
{
// Set the actor's replicates property to default to true,
28 |
29 | Available conditions for `ReplicationCondition` match the ELifetimeCondition enum in C++, and are as follows:
30 |
31 | - None
32 | - InitialOnly
33 | - OwnerOnly
34 | - SkipOwner
35 | - SimulatedOnly
36 | - AutonomousOnly
37 | - SimulatedOrPhysics
38 | - InitialOrOwner
39 | - Custom
40 | - ReplayOrOwner
41 | - ReplayOnly
42 | - SimulatedOnlyNoReplay
43 | - SimulatedOrPhysicsNoReplay
44 | - SkipReplay
45 |
46 |
47 | It is also possible to specify `ReplicatedUsing` on a replicated `UPROPERTY` that will be called whenever
48 | the value of that property is replicated. Note that any function used with `ReplicatedUsing` must be
49 | declared as a `UFUNCTION()` so it is visible to unreal.
--------------------------------------------------------------------------------
/content/scripting/properties-and-accessors.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Properties and Accessors"
3 | weight = 20
4 | sort_by = "weight"
5 | +++
6 |
7 | # Properties and Accessors
8 | ## Script Properties
9 | Properties can be added as variables in any script class.
10 | The initial value of a property can be specified in the class body.
11 |
12 | By default any plain property you declare can only be used from script and is not accessible to blueprint or in the editor.
13 |
14 |
classAExampleActor : AActor
{
floatScriptProperty = 10.0;
}
15 |
16 | ## Editable Properties
17 | To expose a property to unreal, add a `UPROPERTY()` specifier above it.
18 |
19 |
classAExampleActor : AActor
{
// Tooltip of the property
UPROPERTY()
floatEditableProperty = 10.0;
}
20 |
21 | 
22 |
23 | > **Note:** It is not necessary to add `EditAnywhere` to properties in script. Unlike in C++, this is assumed as the default in script.
24 |
25 | To be more specific about where/when a property should be editable from the editor UI, you can use one of the following specifiers:
26 |
27 |
classAExampleActor : AActor
{
// Can only be edited from the default values in a blueprint, not on instances in the level
UPROPERTY(EditDefaultsOnly)
floatDefaultsProperty = 10.0;
// Can only be edited on instances in the level, not in blueprints
// The value can be seen from property details anywhere, but *not* changed
UPROPERTY(VisibleAnywhere)
FNameVisibleProperty = NAME_None;
// This property isn't editable anywhere at all
UPROPERTY(NotEditable)
TArray<int> VisibleProperty;
}
28 |
29 | ## Blueprint Accessible Properties
30 | When a property is declared with `UPROPERTY()`, it also automatically becomes usable within blueprint:
31 |
32 | 
33 |
34 | To limit the blueprint from reading or writing to the property, you can use one of the following specifiers:
35 |
36 |
classAExampleActor : AActor
{
// This property can be both read and written from blueprints
UPROPERTY()
floatBlueprintProperty = 10.0;
// This property can use `Get` nodes in blueprint, but not `Set` nodes
UPROPERTY(BlueprintReadOnly)
floatReadOnlyProperty = 0.0;
// This property cannot be accessed by blueprint nodes at all
UPROPERTY(BlueprintHidden)
intNoBlueprintProperty = 5;
}
37 |
38 | > **Note:** It is not necessary to add `BlueprintReadWrite` to properties in script. Unlike in C++, this is assumed as the default in script.
39 |
40 | ## Categories
41 | It can be helpful to specify a `Category` for your properties.
42 | Categories help organize your properties in the editor UI:
43 |
44 |
45 |
46 | 
47 |
48 | # Property Accessor Functions
49 | Script methods that start with `Get..()` or `Set..()` can use the `property` keyword to allow them to be used as if they are properties.
50 | When the property value is used within other code, the appropriate Get or Set function is automatically called:
51 |
52 |
classAExampleActor : AActor
{
// The `property` keyword lets this function be used as a property instead
// This automatically calls GetRotatedOffset() when used as a property
Print("Offset at BeginPlay: "+RotatedOffset);
}
}
53 |
54 | ## Property Accessors in C++ Binds
55 | Note that _all_ C++ binds can be used as property accessors regardless.
56 | That means that any C++ function that starts with `Get...()` can be accessed as a property.
57 |
58 | This lets you access things such as `Actor.ActorLocation` as a property.
59 | For C++ binds, both forms are valid, so `ActorLocation` and `GetActorLocation()` produce the same result.
60 |
61 | # Access Modifiers
62 | If you want a property or function to be `private` or `protected` in script, each individual property needs to be specified that way:
63 |
64 |
classAExampleActor : AActor
{
privateFVectorOffset;
protectedboolbIsMoving = false;
boolIsMoving() const
{
returnbIsMoving;
}
protectedvoidToggleMoving()
{
bIsMoving = !bIsMoving;
}
}
65 |
66 | Properties that are `private` cannot be accessed at all outside the class they are declared in.
67 | Properties that are `protected` can only be accessed by the class itself and its children.
68 |
69 | > **Tip:** Access modifiers work for functions as well as for properties.
--------------------------------------------------------------------------------
/content/scripting/structs-refs.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Structs and References"
3 | weight = 75
4 | +++
5 |
6 | # Structs
7 | Classes declared in script are always types of `UObject`, and are part of unreal's normal object system and garbage collector.
8 |
9 | You can also make structs in script, which behave as value types:
10 |
11 |
structFExampleStruct
{
/* Properties with UPROPERTY() in a struct will be accessible in blueprint. */
UPROPERTY()
floatExampleNumber = 4.0;
UPROPERTY()
FStringExampleString = "Example String";
/* Properties without UPROPERTY() will still be in the struct, but cannot be seen by blueprint. */
floatExampleHiddenNumber = 3.0;
};
12 |
13 | > **Note:** Unlike classes, structs cannot have `UFUNCTION()`s. They _can_ have plain script methods on them however, although they will not be usable from blueprint.
14 |
15 | ## Passing and Returning Structs
16 | Structs can be passed and returned from script functions and `UFUNCTION`s as normal:
17 |
18 |
19 |
20 | ## Struct References
21 | By default, argument values in script functions are read-only.
22 | That means properties of a struct parameter cannot be changed, and non-const methods cannot be called on it.
23 |
24 | If needed, you can take a reference to a struct to modify it:
25 |
26 |
// Change the parameter struct so its number is randomized between 0.0 and 1.0
27 |
28 | ## Declaring Out Parameters
29 | When a function with a struct reference is called from a blueprint node, the struct will be passed as an input value:
30 |
31 | 
32 |
33 | When you want a struct parameter to be an ouput value only, declare the reference as `&out` in script. This works to create output pins for primitives as well:
34 |
35 |
36 |
37 | 
38 |
39 | ## Automatic References for Function Parameters
40 | As an implementation detail: script functions never take struct parameters by value.
41 | When you declare a struct parameter, it is internally implemented as a const reference, as if you added `const &`.
42 |
43 | This means there is no difference between an `FVector` parameter and a `const FVector&` parameter. Both behave exactly the same in performance and semantics.
44 |
45 | This choice was made to improve script performance and avoid having to instruct gameplay scripters to write `const &` on all their parameters.
--------------------------------------------------------------------------------
/content/scripting/subsystems.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Subsystems"
3 | weight = 140
4 | +++
5 |
6 | # Subsystems
7 | Subsystems are one of unreal's ways to collect common functionality into easily accessible singletons.
8 | See the [Unreal Documentation on Programming Subsystems](https://docs.unrealengine.com/5.1/en-US/programming-subsystems-in-unreal-engine/) for more details.
9 |
10 | ## Using a Subsystem
11 | Subsystems in script can be retrieved by using `USubsystemClass::Get()`.
12 |
13 |
14 |
15 | > **Note:** Many subsystems are _Editor Subsystems_ and cannot be used in packaged games.
16 | > Make sure you only use editor subsystems inside [Editor-Only Script](/scripting/editor-script/).
17 |
18 | ## Creating a Subsystem
19 | To allow creating subsystems in script, helper base classes are available to inherit from that expose overridable functions.
20 | These are:
21 | * `UScriptWorldSubsystem` for world subsystems
22 | * `UScriptGameInstanceSubsystem` for game instance subsystems
23 | * `UScriptLocalPlayerSubsystem` for local player subsystems
24 | * `UScriptEditorSubsystem` for editor subsystems
25 | * `UScriptEngineSubsystem` for engine subsystems
26 |
27 | For example, a scripted world subsystem might look like this:
28 |
29 |
// Create functions on the subsystem to expose functionality
UFUNCTION()
voidLookAtMyActor(AActorActor)
{
}
}
voidUseMyGameWorldSubsystem()
{
autoMySubsystem = UMyGameWorldSubsystem::Get();
MySubsystem.LookAtMyActor(nullptr);
}
30 |
31 | Any `UFUNCTION`s you've declared can also be accessed from blueprint on your subsystem:
32 |
33 | 
34 |
35 | ## Local Player Subsystems
36 | In case of local player subsystems, you need to pass which `ULocalPlayer` to retrieve the subsystem for into the `::Get()` function:
37 |
38 |