You can set variables to keep track of decisions made inside a dialogue, or to pass state in and out of dialogues from your wider code (C++ or Blueprints).
There are 2 scopes for variables, dialogue scope and global scope.
Every runtime instance of a script (also called a Dialogue) has a pool of variable memory, which is stored simply as a set of name/value pairs.
When you set a variable value on a dialogue instance, either in script or in code, it is added to this variable memory, which persists all the time the dialogue exists, and can be saved.
- All variables are shared across the entire script; indenting does not matter
- Variable state does not outlive the dialogue instance, unless you save them
- Variable names are case insensitive.
- Variable names can contain:
- Letters (a-z, A-Z)
- Numbers (0-9)
- Underscores (_)
- Periods (.)
- Variable names must not use the prefix
global.
, which is reserved for global variables
Variables are flexibly typed, which means you can assign any of the supported types to them.
There also exists a pool of global variables which are shared across all dialogue instances. If you have some common variable state that you don't want to set up every time you start a dialogue instance, or if you want changes made to a variable inside a dialogue instance to be available to other dialogues later, then you might want to use global variables. The alternative is to pass variable state in/out of individual dialogue instances as you start / finish them.
In script, global variables are simply variables which have the prefix global.
.
In C++ and Blueprints, there is a separate API for setting global variables,
see Setting Variables.
Type | Unreal Type | Notes |
---|---|---|
Integer | int32 | Whole numbers between -2,147,483,648 and 2,147,483,647. |
Float | float | Single-precision floating point numbers. Literals must contain a decimal point. |
Boolean | bool | Literals can be true or false |
Text | FText | Literal values are enclosed in double-quotes ("Text" ) and are localised |
Name | FName | Literal values are enclosed in backticks (`Name` ), no localisation |
Gender | ETextGender | Literals can be masculine , feminine or neuter |
This is done via Set lines.
You set dialogue variables in code by calling one of the dialogue's SetVariable
methods.
You set global variables using the SUDSSubsystem
's SetGlobalVariable
methods.
For dialogue variables, Blueprints have a specific variant of SetVariable
for each of the supported types,
for example:
For global variables, use the SUDSSubsystem
's SetGlobalVariable
methods.
Note that you don't use the "global." prefix on the name when setting from Blueprints / C++
From C++ you can call these type-specific methods too, or you can call a universal templated version which will determine the type automatically. For dialogue variables:
Dlg->SetVariable("NumCats", 3);
Dlg->SetVariable("HasLaserPointer", true);
For global variables:
auto SUDS = GetSUDSSubsystem(WorldContext);
SUDS->SetGlobalVariable("NumCats", 2);
SUDS->SetGlobalVariable("HasLaserPointer", true);
While the simplest way to get state from surrounding code into the dialogue is to do a one-time set of calls to SetVariable at creation of the dialogue, or using global variables, sometimes you might want to let the dialogue have access to state on demand. Perhaps the state is volatile and changes during the dialogue.
To do this, you can hook into the OnVariableRequested
event on the runtime dialogue
instance, or implement OnDialogueVariableRequested
on a Participant.
The event version might look something like this in Blueprints:
Or in C++ the Participant version might be:
void ANPC::OnDialogueVariableRequested_Implementation(USUDSDialogue* Dlg, FName VarName)
{
static const FName NumCats("NumCats");
static const FName HasLaserPointer("HasLaserPointer");
if (VarName == NumCats)
{
Dlg->SetVariable(Numcats, 3);
}
else if (VarName == HasLaserPointer)
{
Dlg->SetVariable(HasLaserPointer, true);
}
}
You can refer to the value of variables in many ways in the script.
In Speaker and Choice lines, you can substitute variables into the text using curly braces, for example:
NPC: Wow, look at that {Thing}!
NPC: There are {global.NumCats} cats!
Any variable prefixed with global.
is a global variable,
all other variables are dialogue variables.
See Text Markup for more details.
You can also use them in Expressions in both Set lines and Conditional lines.
You can retrieve the value of any variable by calling one of the GetVariable
methods. Like SetVariable
they have variants for each of the supported types.
However if for some reason you do not know the type you can call the generic
GetVariable
and receive the flexible type version, which is of type FSUDSValue
.
You can determine the type from that and retrieve the actual value, both in C++ and Blueprints, for example:
You can also get global variables from the SUDSSubsystem
in the same way
as setting variables above.
If you use the value of a variable which has not been set in expressions like
{SomeValue} + 1
, you get a default value depending on the context.
If you're doing a boolean test you get false, if numeric you get 0, and for text you get a blank string. This is so that expressions never fail to evaluate, so they don't break your script.
If you output an uninitialised variable in text, then you get just the original
text, unsubstituted. For example if you had a speaker line that said
NPC: So you want {Count}?
, and Count
is undefined, then that line will be
printed verbatim, rather than substituting the default 0. This is because you
basically never want to rely on defaults when outputting text to a player, so
printing the unsubstituted variable name makes it easier to detect a bug like this.