├── .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 | ![](/img/scripting.png) 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 | ![Properties](/img/properties.png) 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 | ![](/img/timer.png) 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 | ![Functions](/img/functions.png) 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 | ![Debugging](/img/debug.png) -------------------------------------------------------------------------------- /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 | > ![](/img/open-workspace.png) 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 |
class AIntroductionActor : 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 | ![](/img/place-actors.png) 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 |
class AIntroductionActor : AActor
{
    UPROPERTY()
    float CountdownDuration = 5.0;

    float CurrentTimer = 0.0;
    bool bCountdownActive = false;

    UFUNCTION(BlueprintOverride)
    void BeginPlay()
    {
        // Start the countdown on beginplay with the configured duration
        CurrentTimer = CountdownDuration;
        bCountdownActive = true;
    }

    UFUNCTION(BlueprintOverride)
    void Tick(float DeltaSeconds)
    {
        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 | ![](/img/countdown-duration.png) 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 | ![](/img/countdown-print.png) 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 |
class AIntroductionActor : AActor
{
    UPROPERTY(DefaultComponent, RootComponent)
    USceneComponent SceneRoot;

    UPROPERTY(DefaultComponent, Attach = SceneRoot)
    UStaticMeshComponent Mesh;

    UPROPERTY(DefaultComponent, Attach = SceneRoot)
    UBillboardComponent Billboard;

....
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 | ![](/img/intro-components.png) 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 | ![](/img/bp-pickparent.png) 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 | ![](/img/choose-staticmesh.png) 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)
    void BeginPlay()
    {
        // We no longer start the countdown on BeginPlay automatically
    }

    UFUNCTION()
    void StartCountdown()
    {
        // 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)
    void FinishedCountdown() {}

    UFUNCTION(BlueprintOverride)
    void Tick(float DeltaSeconds)
    {
        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 | ![](/img/intro-bpnodes.png) 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 |
class AMyActor : AActor
{
}

class UMyComponent : 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 |
class AExampleActor : AActor
{
    UPROPERTY(DefaultComponent)
    USceneComponent SceneRoot;
    UPROPERTY(DefaultComponent)
    UMyComponent MyComponent;
}
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 |
class AExampleActor : AActor
{
    // Explicit root component
    UPROPERTY(DefaultComponent, RootComponent)
    USceneComponent SceneRoot;

    // Will be attached to SceneRoot by default, as no attachment is specified
    UPROPERTY(DefaultComponent)
    USkeletalMeshComponent CharacterMesh;

    // Will be attached to the CharacterMesh' RightHand socket
    UPROPERTY(DefaultComponent, Attach = CharacterMesh, AttachSocket = RightHand)
    UStaticMeshComponent WeaponMesh;

    // Will be attached to the WeaponMesh
    UPROPERTY(DefaultComponent, Attach = WeaponMesh)
    UStaticMeshComponent ScopeMesh;
}
31 | 32 | ![](/img/attach-hierarchy.png) 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 |
class AExampleActor : AActor
{
    UPROPERTY(DefaultComponent, RootComponent)
    USceneComponent SceneRoot;

    UPROPERTY(DefaultComponent)
    USkeletalMeshComponent CharacterMesh;

    // The character mesh is always placed a bit above the actor root
    default CharacterMesh.RelativeLocation = FVector(0.0, 0.0, 50.0);

    UPROPERTY(DefaultComponent)
    UStaticMeshComponent ShieldMesh;

    // The shield mesh is hidden by default, and should only appear when taking damage
    default ShieldMesh.bHiddenInGame = true;
    // The shield mesh should not have any collision
    default ShieldMesh.SetCollisionEnabled(ECollisionEnabled::NoCollision);
}
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 |
AActor Actor;

// Retrieve the first skeletal mesh component we can find on the actor
USkeletalMeshComponent SkelComp = USkeletalMeshComponent::Get(Actor);

// Find the specific skeletal mesh component with this component name
USkeletalMeshComponent WeaponComp = USkeletalMeshComponent::Get(Actor, n"WeaponMesh");
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.
// If it does not exist, create it.
UInteractionComponent InteractComp = UInteractionComponent::GetOrCreate(Actor);

// Find an interaction handling component specifically named "ClimbingInteraction",
// or create a new one with that name
auto ClimbComp = UInteractionComponent::GetOrCreate(Actor, n"ClimbingInteraction");
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 |
ACharacter Character;

// Create a new static mesh component on the character and attach it to the character mesh
UStaticMeshComponent NewComponent = UStaticMeshComponent::Create(Character);
NewComponent.AttachToComponent(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
FVector SpawnLocation;
FRotator SpawnRotation;
AExampleActor SpawnedActor = SpawnActor(AExampleActor, SpawnLocation, SpawnRotation);
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 |
class AExampleSpawner : AActor
{
    /**
     * Which blueprint example actor class to spawn.
     * This needs to be configured either in the level,
     * or on a blueprint child class of the spawner.
     */
    UPROPERTY()
    TSubclassOf<AExampleActor> ActorClass;

    UFUNCTION(BlueprintOverride)
    void BeginPlay()
    {
        FVector SpawnLocation;
        FRotator SpawnRotation;

        AExampleActor SpawnedActor = SpawnActor(ActorClass, SpawnLocation, SpawnRotation);
    }
}
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 |
class AExampleActor : AActor
{
    // How many meshes to place on the actor
    UPROPERTY()
    int SpawnMeshCount = 5;

    // Which static mesh to place
    UPROPERTY()
    UStaticMesh MeshAsset;

    UFUNCTION(BlueprintOverride)
    void ConstructionScript()
    {
        Print(f"Spawning {SpawnMeshCount} meshes from construction script!");

        for (int i = 0; i < SpawnMeshCount; ++i)
        {
            // Construct a new static mesh on this actor
            UStaticMeshComponent MeshComp = UStaticMeshComponent::Create(this);
            // Set the mesh we wanted for it
            MeshComp.SetStaticMesh(MeshAsset);
        }
    }
}
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 |
AActor Actor;

TArray<UStaticMeshComponent> StaticMeshComponents;
Actor.GetComponentsByClass(StaticMeshComponents);

for (UStaticMeshComponent MeshComp : 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 |
class ABaseActor : AActor
{
    // This base actor specifies a root component that is just a scene component
    UPROPERTY(DefaultComponent, RootComponent)
    USceneComponent SceneRoot;
}

class AChildActor : 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)
    UStaticMeshComponent RootStaticMesh;
}
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 |
void TeleportActorToOtherActor(AActor ActorReference, AActor TeleportToActor)
{
    FTransform TeleportToTransform = TeleportToActor.GetActorTransform();
    ActorReference.SetActorTransform(TeleportToTransform);
}
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 |
class AExampleActor : AActor
{
    // Set default values for class properties in the class body
    UPROPERTY()
    float ConfigurableValue = 5.0;

    // Set default values for subobjects with `default` statements
    UPROPERTY(DefaultComponent)
    UCapsuleComponent CapsuleComponent;
    default CapsuleComponent.CapsuleHalfHeight = 88.0;
    default CapsuleComponent.CapsuleRadius = 40.0;
    default CapsuleComponent.bGenerateOverlapEvents = true;
}
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 |
float ValueDouble = 1.0; // <-- This is a 64-bit double-precision float
float32 ValueSingle = 1.f; // <-- This is a 32-bit single-precision float
float64 ValueAlsoDouble = 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
delegate void FExampleDelegate(UObject Object, float Value);
12 | 13 | From there, you can pass around values of your delegate type, bind them, and execute them: 14 | 15 |
class ADelegateExample : AActor
{
    FExampleDelegate StoredDelegate;

    UFUNCTION(BlueprintOverride)
    void BeginPlay()
    {
        // Bind the delegate so executing it calls this.OnDelegateExecuted()
        StoredDelegate.BindUFunction(this, n"OnDelegateExecuted");

        // You can also create new bound delegates by using the constructor:
        StoredDelegate = FExampleDelegateSignature(this, n"OnDelegateExecuted");
    }

    UFUNCTION()
    private void OnDelegateExecuted(UObject Object, float Value)
    {
        Print(f"Delegate was executed with object {Object} and value {Value}");
    }

    UFUNCTION(BlueprintOverride)
    void Tick(float DeltaSeconds)
    {
        // If the delegate is bound, execute it
        StoredDelegate.ExecuteIfBound(this, DeltaSeconds);
    }
}
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 |
event void FExampleEvent(int Counter);

class AEventExample : AActor
{
    UPROPERTY()
    FExampleEvent OnExampleEvent;

    private int CallCounter = 0;

    UFUNCTION(BlueprintOverride)
    void BeginPlay()
    {
        // Add two functions to be called when the event is broadcast
        OnExampleEvent.AddUFunction(this, n"FirstHandler");
        OnExampleEvent.AddUFunction(this, n"SecondHandler");
    }

    UFUNCTION()
    private void FirstHandler(int Counter)
    {
        Print("Called first handler");
    }

    UFUNCTION()
    private void SecondHandler(int Counter)
    {
        Print("Called second handler");
    }

    UFUNCTION(BlueprintOverride)
    void Tick(float DeltaSeconds)
    {
        CallCounter += 1;
        OnExampleEvent.Broadcast(CallCounter);
    }
}
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 | ![](/img/bp-event-dispatcher.png) 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 | ![](/img/generate-method.png) -------------------------------------------------------------------------------- /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 |
class AExampleActor : AActor
{
#if EDITOR
    default PivotOffset = FVector(0, 0, 10);
#endif

    UFUNCTION(BlueprintOverride)
    void ConstructionScript()
    {
#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 |
delegate void FExampleDelegate();

class ANameLiteralActor : AActor
{
    TMap<FName, int> ValuesByName;

    void UseNameLiteral()
    {
        FName NameVariable = n"MyName";
        ValuesByName.Add(NameVariable, 1);

        FExampleDelegate Delegate;
        Delegate.BindUFunction(this, n"FunctionBoundToDelegate");
        Delegate.ExecuteIfBound();

        // Due to the name literal, no string manipulation happens
        // in calls to UseNameLiteral() during runtime.
    }

    UFUNCTION()
    void FunctionBoundToDelegate()
    {
        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
Print(f"Hexadecimal: {20 :#x}"); // 0x14
Print(f"Binary: {1574 :b}"); // 11000100110
Print(f"Binary 32 Bits: {1574 :#032b}"); // 0b00000000000000000000011000100110

// Alignment works too
Print(f"Aligned: {GetName() :>40}"); // Adds spaces to the start of GetName() so it is 40 characters
Print(f"Aligned: {GetName() :_<40}"); // Adds underscores to the end of GetName() so it is 40 characters

// You can combine the equals with a format specifier
Print(f"{DeltaSeconds =:.0}");
// This prints:
//   DeltaSeconds = 0

// Enums by default print a full debug string
Print(f"{ESlateVisibility::Collapsed}"); // "ESlateVisibility::Collapsed (1)"
// But the 'n' specifier prints only the name of the value:
Print(f"{ESlateVisibility::Collapsed :n}"); // "Collapsed"
-------------------------------------------------------------------------------- /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 |
class ATimerExample : AActor
{
    UFUNCTION(BlueprintOverride)
    void BeginPlay()
    {
        // Execute this.OnTimerExecuted() after 2 seconds
        System::SetTimer(this, n"OnTimerExecuted", 2.0, bLooping = false);
    }

    UFUNCTION()
    private void OnTimerExecuted()
    {
        Print("Timer executed!");
    }
}
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 |
class AExampleActor : AActor
{
    void MyMethod()
    {
        MyGlobalFunction(this);
    }
}

void MyGlobalFunction(AActor Actor)
{
    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 |
class AExampleActor : AActor
{
    UFUNCTION()
    void MyMethodForBlueprint()
    {
        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 |
class AExampleActor : AActor
{
    UFUNCTION(BlueprintOverride)
    void BeginPlay()
    {
        Print("I am a BeginPlay override");
    }

    UFUNCTION(BlueprintOverride)
    void Tick(float DeltaSeconds)
    {
        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 | ![](/img/override-lightbulb.png) 32 | 33 | Typing the name of an overridable event also suggests a completion for the full function signature: 34 | 35 | ![](/img/override-completion.png) 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 |
class AExampleActor : AActor
{
    UFUNCTION(BlueprintEvent)
    void OverridableFunction()
    {
        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 |
class AExamplePickupActor : AActor
{
    void PickedUp()
    {
        // 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
    UFUNCTION(BlueprintEvent, DisplayName = "Picked Up")
    void BP_PickedUp() {}
}
57 | 58 | ![](/img/bp-override.png) 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
UFUNCTION()
void ExampleGlobalFunctionMoveActor(AActor Actor, FVector MoveAmount)
{
    Actor.ActorLocation += MoveAmount;
}
67 | 68 | ![](/img/example-global-function.png) 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 |
class AScriptParentActor : AActor
{
    void PlainMethod(FVector Location)
    {
        Print("AScriptParentActor::PlainMethod()");
    }

    UFUNCTION(BlueprintEvent)
    void BlueprintEventMethod(int Value)
    {
        Print("AScriptParentActor::BlueprintEventMethod()");
    }
}

class AScriptChildActor : AScriptParentActor
{
    // Any script method can be overridden
    void PlainMethod(FVector Location) override
    {
        Super::PlainMethod(Location);
        Print("AScriptChildActor::PlainMethod()");
    }

    // Overriding a parent BlueprintEvent requires BlueprintOverride
    UFUNCTION(BlueprintOverride)
    void BlueprintEventMethod(int Value)
    {
        Super::BlueprintEventMethod(Value);
        Print("AScriptChildActor::BlueprintEventMethod()");
    }
}
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"
FGameplayTag TheTag = GameplayTags::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
mixin void ExampleMixinTeleportActor(AActor Self, FVector Location)
{
    Self.ActorLocation = Location;
}

void Example_MixinMethod()
{
    // Call the mixin method on an actor
    // Note how ActorReference is passed into Self automatically
    AActor ActorReference;
    ActorReference.ExampleMixinTeleportActor(FVector(0.0, 0.0, 100.0));
}
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 |
mixin void SetVectorToZero(FVector& Vector)
{
    Vector = FVector(0, 0, 0);
}

void Example_StructMixin()
{
    FVector LocalValue;
    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 |
class AReplicatedActor : AActor
{
    // Set the actor's replicates property to default to true,
    // so its declared replicated properties work.
    default bReplicates = true;

    // Will always be replicated when it changes
    UPROPERTY(Replicated)
    bool bReplicatedBool = true;

    // Only replicates to the owner
    UPROPERTY(Replicated, ReplicationCondition = OwnerOnly)
    int ReplicatedInt = 0;

    // Calls OnRep_ReplicatedValue whenever it is replicated
    UPROPERTY(Replicated, ReplicatedUsing = OnRep_ReplicatedValue)
    int ReplicatedValue = 0;

    UFUNCTION()
    void OnRep_ReplicatedValue()
    {
        Print("Replicated Value has changed!");
    }
}
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 |
class AExampleActor : AActor
{
    float ScriptProperty = 10.0;
}
15 | 16 | ## Editable Properties 17 | To expose a property to unreal, add a `UPROPERTY()` specifier above it. 18 | 19 |
class AExampleActor : AActor
{
    // Tooltip of the property
    UPROPERTY()
    float EditableProperty = 10.0;
}
20 | 21 | ![](/img/editable-property.png) 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 |
class AExampleActor : AActor
{
    // Can only be edited from the default values in a blueprint, not on instances in the level
    UPROPERTY(EditDefaultsOnly)
    float DefaultsProperty = 10.0;

    // Can only be edited on instances in the level, not in blueprints
    UPROPERTY(EditInstanceOnly)
    FVector InstanceProperty = FVector(0.0, 100.0, 0.0);

    // The value can be seen from property details anywhere, but *not* changed
    UPROPERTY(VisibleAnywhere)
    FName VisibleProperty = 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 | ![](/img/bp-properties.png) 33 | 34 | To limit the blueprint from reading or writing to the property, you can use one of the following specifiers: 35 | 36 |
class AExampleActor : AActor
{
    // This property can be both read and written from blueprints
    UPROPERTY()
    float BlueprintProperty = 10.0;

    // This property can use `Get` nodes in blueprint, but not `Set` nodes
    UPROPERTY(BlueprintReadOnly)
    float ReadOnlyProperty = 0.0;

    // This property cannot be accessed by blueprint nodes at all
    UPROPERTY(BlueprintHidden)
    int NoBlueprintProperty = 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 |
class AExampleActor : AActor
{
    UPROPERTY(Category = "First Category")
    float FirstProperty = 0.0;

    UPROPERTY(Category = "Second Category")
    float SecondProperty = 0.0;

    UPROPERTY(Category = "Second Category|Child Category")
    FString ChildProperty = "StringValue";
}
45 | 46 | ![](/img/property-categories.png) 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 |
class AExampleActor : AActor
{
    // The `property` keyword lets this function be used as a property instead
    FVector GetRotatedOffset() const property
    {
        return ActorRotation.RotateVector(FVector(0.0, 1.0, 1.0));
    }

    UFUNCTION(BlueprintOverride)
    void BeginPlay()
    {
        // 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 |
class AExampleActor : AActor
{
    private FVector Offset;
    protected bool bIsMoving = false;

    bool IsMoving() const
    {
        return bIsMoving;
    }

    protected void ToggleMoving()
    {
        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 |
struct FExampleStruct
{
    /* Properties with UPROPERTY() in a struct will be accessible in blueprint. */
    UPROPERTY()
    float ExampleNumber = 4.0;

    UPROPERTY()
    FString ExampleString = "Example String";

    /* Properties without UPROPERTY() will still be in the struct, but cannot be seen by blueprint. */
    float ExampleHiddenNumber = 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 |
UFUNCTION()
FExampleStruct CreateExampleStruct(float Number)
{
    FExampleStruct ResultStruct;
    ResultStruct.ExampleNumber = Number;
    ResultStruct.ExampleString = f"{Number}";

    return ResultStruct;
}

UFUNCTION(BlueprintPure)
bool IsNumberInStructEqual(FExampleStruct Struct, float TestNumber)
{
    return Struct.ExampleNumber == TestNumber;
}
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
UFUNCTION()
void RandomizeNumberInStruct(FExampleStruct& Struct)
{
    Struct.ExampleNumber = Math::RandRange(0.0, 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 | ![](/img/struct-input.png) 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 |
UFUNCTION()
void OutputRandomizedStruct(FExampleStruct&out OutputStruct, bool&out bOutSuccessful)
{
    FExampleStruct ResultStruct;
    ResultStruct.ExampleNumber = Math::RandRange(0.0, 1.0);

    OutputStruct = ResultStruct;
    bOutSuccessful = true;
}
36 | 37 | ![](/img/struct-multioutput.png) 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 |
void TestCreateNewLevel()
{
    auto LevelEditorSubsystem = ULevelEditorSubsystem::Get();
    LevelEditorSubsystem.NewLevel("/Game/NewLevel");
}
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 |
class UMyGameWorldSubsystem : UScriptWorldSubsystem
{
    UFUNCTION(BlueprintOverride)
    void Initialize()
    {
        Print("MyGame World Subsystem Initialized!");
    }

    UFUNCTION(BlueprintOverride)
    void Tick(float DeltaTime)
    {
        Print("Tick");
    }

    // Create functions on the subsystem to expose functionality
    UFUNCTION()
    void LookAtMyActor(AActor Actor)
    {
    }
}

void UseMyGameWorldSubsystem()
{
    auto MySubsystem = UMyGameWorldSubsystem::Get();
    MySubsystem.LookAtMyActor(nullptr);
}
30 | 31 | Any `UFUNCTION`s you've declared can also be accessed from blueprint on your subsystem: 32 | 33 | ![](/img/scripted-subsystem.png) 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 |
class UMyPlayerSubsystem : UScriptLocalPlayerSubsystem
{
}

void UseScriptedPlayerSubsystem()
{
    ULocalPlayer RelevantPlayer = Gameplay::GetPlayerController(0).LocalPlayer;
    auto MySubsystem = UMyPlayerSubsystem::Get(RelevantPlayer);
}
39 | 40 | > **Note:** It is also possible to directly pass an `APlayerController` when retrieving a local player subsystem. -------------------------------------------------------------------------------- /sass/docs.scss: -------------------------------------------------------------------------------- 1 | html { 2 | font-kerning: normal; 3 | text-rendering: optimizeLegibility; 4 | scroll-behavior: smooth; 5 | } 6 | 7 | body { 8 | margin: 0 0; 9 | font-size: 1.125rem; 10 | font-family: Segoe UI,system-ui,-apple-system,sans-serif; 11 | line-height: 1.75; 12 | background: #f9f9f9; 13 | color: #222; 14 | } 15 | 16 | main { 17 | display: grid; 18 | max-width: 72em; 19 | min-height: 100vh; 20 | } 21 | 22 | 23 | a { 24 | &:link, &:visited { 25 | color: #00a; 26 | text-decoration: none; 27 | } 28 | 29 | &:hover, &:visited:hover { 30 | color: #c00; 31 | } 32 | } 33 | 34 | nav { 35 | grid-row: 1; 36 | grid-column: 1; 37 | width: 18em; 38 | background-color: #ddeded; 39 | padding-left: 1em; 40 | padding-right: 1em; 41 | 42 | img { 43 | width: 15em; 44 | display: block; 45 | margin-left: 1.5em; 46 | margin-top: -1.5em; 47 | margin-bottom: -4em; 48 | } 49 | 50 | ul { 51 | padding: 0 0 0 2em; 52 | margin: 0 0 1em 0; 53 | } 54 | 55 | label { 56 | font-size: 110%; 57 | padding: 0; 58 | margin: 0; 59 | } 60 | 61 | .active a { 62 | font-weight: bold; 63 | } 64 | } 65 | 66 | article { 67 | grid-row: 1; 68 | grid-column: 2; 69 | padding: 2em; 70 | justify-self: start; 71 | } 72 | 73 | code { 74 | tab-size: 4; 75 | padding: 3px 5px 3px 5px; 76 | color: #af6020; 77 | background-color: #e4e4e4; 78 | border: 1px solid #c4c4c4; 79 | font-family: Consolas; 80 | white-space: nowrap; 81 | } 82 | 83 | pre { 84 | max-width: 60em; 85 | font-size: 16px; 86 | line-height: 21px; 87 | } 88 | 89 | div.code_block, pre > code { 90 | display:block; 91 | padding: 1em; 92 | line-height: 1.1; 93 | color: #d4d4d4; 94 | background-color: #1e1e1e; 95 | border: none; 96 | white-space: pre; 97 | max-width: 60em; 98 | overflow-x: auto; 99 | font-family: Consolas, 'Courier New', monospace !important; 100 | font-size: 16px !important; 101 | } 102 | 103 | blockquote 104 | { 105 | display: block; 106 | margin: 0; 107 | 108 | p { 109 | border: 1px solid #0d47a1; 110 | border-left: 30px solid #407ad1; 111 | border-radius: 0.5rem; 112 | background: #e3f2fd; 113 | 114 | padding-top: 10px; 115 | padding-bottom: 10px; 116 | padding-left: 1.5rem; 117 | padding-right: 1.5rem; 118 | } 119 | } 120 | 121 | kbd { 122 | background: #2e2e2e; 123 | color: #dedede; 124 | padding: 2px 8px 2px 8px; 125 | font-weight: bold; 126 | border-radius: 5px; 127 | } 128 | 129 | .zola-anchor { 130 | opacity: 0%; 131 | margin-left: 0.5em; 132 | margin-top: 0; 133 | font-size: 80%; 134 | } 135 | 136 | h1:hover .zola-anchor, 137 | h2:hover .zola-anchor, 138 | h3:hover .zola-anchor, 139 | h4:hover .zola-anchor 140 | { 141 | opacity: 100%; 142 | transition: 0.3s; 143 | transition-delay: 0.1s; 144 | } 145 | 146 | h1 { 147 | font-size: 170%; 148 | } 149 | 150 | h1 + p { 151 | margin-top: -1em; 152 | } 153 | 154 | h2 { 155 | font-size: 140%; 156 | margin-top: 1.5em; 157 | } 158 | 159 | h1 + h2 { 160 | margin-top: -1em; 161 | } 162 | 163 | h2 + p { 164 | margin-top: -1em; 165 | } 166 | 167 | h2 + h3 { 168 | margin-top: -1em; 169 | } 170 | 171 | h3 + p { 172 | margin-top: -1em; 173 | } 174 | 175 | a[href^="http://"]:not([href*="127.0.0.1"]):not([href*="angelscript.hazelight.se"]):after, 176 | a[href^="https://"]:not([href*="127.0.0.1"]):not([href*="angelscript.hazelight.se"]):after { 177 | content: "🔗"; 178 | margin-left: 0.1em; 179 | margin-right: 0.25em; 180 | font-size: 60%; 181 | position: relative; 182 | top: -0.4em; 183 | } -------------------------------------------------------------------------------- /static/angelscript_unreal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/angelscript_unreal.png -------------------------------------------------------------------------------- /static/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 36 | 38 | 42 | 46 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /static/img/attach-hierarchy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/attach-hierarchy.png -------------------------------------------------------------------------------- /static/img/bp-event-dispatcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/bp-event-dispatcher.png -------------------------------------------------------------------------------- /static/img/bp-override.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/bp-override.png -------------------------------------------------------------------------------- /static/img/bp-pickparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/bp-pickparent.png -------------------------------------------------------------------------------- /static/img/bp-properties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/bp-properties.png -------------------------------------------------------------------------------- /static/img/choose-staticmesh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/choose-staticmesh.png -------------------------------------------------------------------------------- /static/img/completion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/completion.png -------------------------------------------------------------------------------- /static/img/countdown-duration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/countdown-duration.png -------------------------------------------------------------------------------- /static/img/countdown-print.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/countdown-print.png -------------------------------------------------------------------------------- /static/img/coverage-dir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/coverage-dir.png -------------------------------------------------------------------------------- /static/img/coverage-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/coverage-file.png -------------------------------------------------------------------------------- /static/img/coverage-index.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/coverage-index.png -------------------------------------------------------------------------------- /static/img/coverage-toggle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/coverage-toggle.png -------------------------------------------------------------------------------- /static/img/debug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/debug.png -------------------------------------------------------------------------------- /static/img/editable-property.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/editable-property.png -------------------------------------------------------------------------------- /static/img/example-global-function.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/example-global-function.png -------------------------------------------------------------------------------- /static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/favicon.ico -------------------------------------------------------------------------------- /static/img/functions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/functions.png -------------------------------------------------------------------------------- /static/img/generate-method.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/generate-method.png -------------------------------------------------------------------------------- /static/img/intro-bpnodes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/intro-bpnodes.png -------------------------------------------------------------------------------- /static/img/intro-components.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/intro-components.png -------------------------------------------------------------------------------- /static/img/open-workspace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/open-workspace.png -------------------------------------------------------------------------------- /static/img/override-completion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/override-completion.png -------------------------------------------------------------------------------- /static/img/override-lightbulb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/override-lightbulb.png -------------------------------------------------------------------------------- /static/img/place-actors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/place-actors.png -------------------------------------------------------------------------------- /static/img/properties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/properties.png -------------------------------------------------------------------------------- /static/img/property-categories.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/property-categories.png -------------------------------------------------------------------------------- /static/img/scripted-subsystem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/scripted-subsystem.png -------------------------------------------------------------------------------- /static/img/scripting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/scripting.png -------------------------------------------------------------------------------- /static/img/struct-input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/struct-input.png -------------------------------------------------------------------------------- /static/img/struct-multioutput.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/struct-multioutput.png -------------------------------------------------------------------------------- /static/img/timer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazelight/Docs-UnrealEngine-Angelscript/a093179b56a293924bb3646077ae75bf68454d70/static/img/timer.png -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {% block title -%}{{ config.title }}{% endblock -%} 8 | 9 | 10 |
11 | 41 |
42 | {% block content -%} 43 | {{ section.content | safe }} 44 | {% endblock -%} 45 |
46 |
47 | -------------------------------------------------------------------------------- /templates/page.html: -------------------------------------------------------------------------------- 1 | {% extends "index.html" %} 2 | {% block title %} {{ config.title }} | {{ page.title }} {% endblock title %} 3 | {% block content %} 4 | {{ page.content | safe }} 5 | {% endblock content %} --------------------------------------------------------------------------------