Evaluating expressions
Expression class you can use to evaluate expressions. An expression can be:
(2 + 4) * 16/4.0.deg2rad(90).update_health(), ifbase_instanceis set to a value other thannullwhen calling Expression.execute(). Note The Expression class is independent from GDScript. It’s available even if you compile Godot with the GDScript module disabled.Basic usage
To evaluate a mathematical expression, use:
The following operators are available: order of operations applies. Use parentheses to override the order of operations if needed. All the Variant types supported in Godot can be used: integers, floating-point numbers, strings, arrays, dictionaries, colors, vectors, … Arrays and dictionaries can be indexed like in GDScript:var expression = Expression.new()expression.parse("20 + 10*2 - 5/2.0")var result = expression.execute()print(result) # 37.5
# Returns 1.[1, 2][0]# Returns 3. Negative indices can be used to count from the end of the array.[1, 3][-1]# Returns "green".{"favorite_color": "green"}["favorite_color"]# All 3 lines below return 7.0 (Vector3 is floating-point).Vector3(5, 6, 7)[2]Vector3(5, 6, 7)["z"]Vector3(5, 6, 7).z
Passing variables to an expression
You can pass variables to an expression. These variables will then become available in the expression’s “context” and will be substituted when used in the expression:
must be specified as an array, even if you only define one variable. Also, variable names are case-sensitive.var expression = Expression.new()# Define the variable names first in the second parameter of `parse()`.# In this example, we use `x` for the variable name.expression.parse("20 + 2 * x", ["x"])# Then define the variable values in the first parameter of `execute()`.# Here, `x` is assigned the integer value 5.var result = expression.execute([5])print(result) # 30
Setting a base instance for the expression
null. This means the expression has no base instance associated to it. Expression.execute(), you can set the value of thebase_instanceparameter to a specific object instance such asself, another script instance or even a singleton:
Associating a base instance allows doing the following:func double(number): return number * 2func _ready(): var expression = Expression.new() expression.parse("double(10)") # This won't work since we're not passing the current script as the base instance. var result = expression.execute([], null) print(result) # null # This will work since we're passing the current script (i.e. self) # as the base instance. result = expression.execute([], self) print(result) # 20
const) in the expression.var) in the expression.- Call methods defined in the instance and use their return values in the expression.
Warning
nullallows referencing constants, member variables, and calling all methods defined in the script attached to the instance. Allowing users to enter expressions may allow cheating in your game, or may even introduce security vulnerabilities if you allow arbitrary clients to run expressions on other players’ devices.Example script
The script below demonstrates what the Expression class is capable of:
The output from the script will be:const DAYS_IN_YEAR = 365var script_member_variable = 1000func _ready(): # Constant mathexpression. evaluate("2 + 2") # Math expression with variables. evaluate("x + y", ["x", "y"], [60, 100]) # Call built-in method (hardcoded in the Expression class). evaluate("deg2rad(90)") # Call user method (defined in the script). # We can do this because the expression execution is bound to `self` # in the `evaluate()` method. # Since this user method returns a value, we can use it in math expressions. evaluate("call_me() + DAYS_IN_YEAR + script_member_variable") evaluate("call_me(42)") evaluate("call_me('some string')")func evaluate(command, variable_names = [], variable_values = []) -> void: var expression = Expression.new() var error = expression.parse(command, variable_names) if error != OK: push_error(expression.get_error_text()) return var result = expression.execute(variable_values, self) if not expression.has_execute_failed(): print(str(result))func call_me(argument = null): print("\nYou called 'call_me()' in the expression text.") if argument: print("Argument passed: %s" % argument) # The method's return value is also the expression's return value. return 0
41601.570796You called 'call_me()' in the expression text.1365You called 'call_me()' in the expression text.Argument passed: 420You called 'call_me()' in the expression text.Argument passed: some string0
Built-in functions
@GDScript scope are available in the Expression class, even if no base instance is bound to the expression. The same parameters and return types are available. always required even if they’re specified as being optional in the class reference. In contrast, this restriction on arguments doesn’t apply to user-made functions when you bind a base instance to the expression.
