Skip to content

Construction Scripts 2.5+

Construction scripts can be defined for any custom node class. They may run both in-editor and in-game. When running in the editor it is possible to programmatically modify a node based on user input.

ConstructionStateGif

Creating a new node class will default the construction script as follows:

Editor Execution will only run while designing your state machine and Game Execution will only execute during run-time.

When do construction scripts run?

In-game construction scripts always run once, when the state machine is initialized and after all nodes are instantiated.

In-editor construction scripts can be configured to run at different times. By default on new projects they run whenever a blueprint is modified. This allows immediate feedback when the user changes a value on a node.

Editor construction scripts are optimized not to run when there is no construction script logic defined in a graph. It will always run for native classes unless bSkipNativeEditorConstructionScripts is set to true. This can be set in code from the C++ constructor. Make sure to wrap it with #if WITH_EDITORONLY_DATA

1
2
3
#if WITH_EDITORONLY_DATA
    bSkipNativeEditorConstructionScripts = true;
#endif

Modify Node Properties

With editor execution you can dynamically set variable default values. Setting a default value will always replace whatever instance value was entered by the user. Consider this when modifying construction scripts as this will automatically update existing node instances when state machine blueprints are compiled.

Variables can also be marked read only or hidden. Nodes can have their icon or color changed.

ConstructionStateGif

BlueprintConstructionScripts

ConstructionState.h
#pragma once

#include "SMStateInstance.h"

#include "ConstructionState.generated.h"

UCLASS()
class USMConstructionState : public USMStateInstance
{
public:
    GENERATED_BODY()

protected:
    virtual void ConstructionScript_Implementation() override
    {
#if WITH_EDITORONLY_DATA
        if (IsEditorExecution())
        {
            SetVariableHidden(GET_MEMBER_NAME_CHECKED(USMConstructionState, HiddenVariable), bHidden);
            SetVariableReadOnly(GET_MEMBER_NAME_CHECKED(USMConstructionState, ReadOnlyVariable), bReadOnly);

            ReadOnlyVariable = TEXT("I'm set by the construction script!");

            if (bHidden)
            {
                HiddenVariable = TEXT("You hid me!");
            }
        }
#endif
    }

protected:
    UPROPERTY(BlueprintReadWrite, Category=Default)
    bool bReadOnly;

    UPROPERTY(BlueprintReadWrite, Category=Default)
    FString ReadOnlyVariable;

    UPROPERTY(BlueprintReadWrite, Category=Default)
    bool bHidden;

    UPROPERTY(BlueprintReadWrite, Category=Default)
    FString HiddenVariable;
};

Traverse State Machine Nodes

It is possible to retrieve information from the state machine the node is placed in, such as all included nodes or connected nodes. In the example below a state machine node displays its nested states, and the state node displays its connected states. Note that while all nodes in the state machine are available, the SMInstance itself will not be since that is the class being compiled.

Construction

The state node construction script: ConstructionDef

The state machine node construction script: ConstructionDef

Can I access the owning state machine blueprint's properties by calling GetStateMachineInstance()?

No, but this is a highly requested feature. The reason this is not an option is because node construction scripts need to occur while the owning state machine blueprint is compiling.

At this stage of the kismet compiler process, Unreal has already cleared out the old class default object which contains your values and is in the process of generating a new one, which is what GetStateMachineInstance() would need to return.


This gets fairly technical, but the only way to retrieve this information is using UE's FBlueprintCompilationManager in C++. Here an old default value can be retrieved in an exported string format. See FBlueprintCompilationManager::GetDefaultValue. This is currently what the FSMEditorConstructionManager uses to retrieve the NodeClass value for the Root State Machine Node.

Snippet from FSMEditorConstructionManager...
SMEditorConstructionManager.cpp
// This could be during a compile where the CDO is cleared out.
// The compilation manager keeps track of old CDOs and can recover default property values.

FProperty* Property = FindFProperty<FProperty>(BPGC, USMInstance::GetStateMachineClassPropertyName());
check(Property);
Property = FBlueprintEditorUtils::GetMostUpToDateProperty(Property);

FString DefaultValue;
if (FBlueprintCompilationManager::GetDefaultValue(BPGC, Property, DefaultValue))
{
    if (!DefaultValue.IsEmpty() && DefaultValue != TEXT("None"))
    {
        const TSoftClassPtr<USMStateMachineInstance> StateMachineNodeClassSoftPtr(DefaultValue);
        StateMachineNodeClass = StateMachineNodeClassSoftPtr.LoadSynchronous();
    }
}

Configuring Editor Construction Script Settings

Construction

You may configure how editor constructions run for your project.

  • Navigate to Edit -> Project Settings -> Logic Driver
  • Select a value for Editor Node Construction Script Setting

Construction scripts can be configured for editor use in three ways:

  1. Standard
    • They run whenever the blueprint is modified or compiled.
  2. Compile
    • They run only on compile. This can help with editor performance while still producing the same functional results as standard.
  3. Legacy
    • They run the same as on older versions which is only on initial node instantiation. This is a backwards compatible setting and not recommended for new projects as it severely limits the capabilities of construction scripts.
Upgrading Old Logic Driver Pro Projects to the New Construction Scripts

If your project was used with Logic Driver 2.4 or lower, the construction script settings are defaulted to Legacy. This is done as a precaution in case your project used construction scripts in a way that isn't safe with the updated behavior. An example would be setting the default value of a property. While this previously had no effect in the editor, in 2.5 it will actually set that default value when the blueprint is modified or compiled. A very useful feature, but less useful if you accidentally wipe out data because of a behavior change you weren't expecting.

After upgrading and before changing the Editor Node Construction Script Setting it is recommended to validate your project isn't currently using construction scripts, or they are aren't being used in a way that might negatively impact your data.

Considerations

  • The context won't be available during editor construction scripts. It will just be a dummy object.
  • GetStateMachineInstance (the main blueprint you're modifying) won't be available during editor execution since this is the class being compiled.
  • Only default values are able to be read from exposed variables during editor execution. The property graph itself cannot be evaluated at this stage since it belongs to the class being compiled.
  • During editor construction scripts, be careful of accessing another node's variables that are also being modified from a construction script. There isn't a guarantee in the order the nodes run their construction scripts and the data may not be what you are expecting.
  • Parent State Machine Nodes won't be expanded and cannot be traversed during editor construction.