Оценка выражений
Godot предоставляет класс Expression, который можно использовать для оценки выражений.
Выражение может быть:
Математическое выражение, такое как
(2 + 4) * 16/4.0.Булевое выражение, такое как
true && false.Встроенный вызов метода типа
deg_to_rad(90).Вызов метода в предоставленном пользователем скрипте, таком как
update_health(), еслиbase_instanceустановлено на значение, отличное отnullпри вызове Expression.execute().
Примечание
Класс Expression независим от GDScript. Он доступен даже при компиляции Godot с отключённым модулем GDScript.
Базовое использование
Для оценки математического выражения используйте:
var expression = Expression.new()
expression.parse("20 + 10*2 - 5/2.0")
var result = expression.execute()
print(result) # 37.5
Доступны следующие операторы:
Оператор |
Примечания |
|---|---|
Добавление |
Также может использоваться для объединения строк и массивов: - |
Вычитание ( |
|
Умножение ( |
|
Деление ( |
Выполняет целочисленное деление, если оба операнда — целые числа. Если хотя бы один из них — число с плавающей точкой, возвращает значение с плавающей точкой. |
Остаток ( |
Возвращает остаток от деления целого числа (по модулю). Результат всегда будет иметь знак делимого. |
Союз ( |
Возвращает результат boolean AND (И). |
Дизъюнкция ( |
Возвращает результат boolean OR (ИЛИ). |
Отрицание ( |
Возвращает результат boolean NOT (НЕ). |
Пробелы вокруг операторов необязательны. Также помните, что действует обычный порядок выполнения операций. При необходимости используйте скобки, чтобы переопределить порядок выполнения операций.
Можно использовать все типы Variant, поддерживаемые в Godot: целые числа (integers), числа с плавающей точкой (floating-point numbers), строки (strings), массивы (arrays), словари (dictionaries), цвета (colors), векторы (vectors), …
Массивы и словари можно индексировать как в GDScript:
# 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
Передача переменных в выражение
Вы можете передавать переменные в выражение. Эти переменные станут доступны в «контексте» выражения и будут подставляться при использовании в выражении:
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
Имена и значения переменных должны быть указаны в виде массива, даже если вы определяете только одну переменную. Кроме того, имена переменных чувствительны к регистру.
Установка базового экземпляра для выражения
По умолчанию выражение имеет базовый экземпляр null. Это означает, что с выражением не связан ни один базовый экземпляр.
При вызове Expression.execute() вы можете задать значение параметра base_instance для конкретного экземпляра объекта, например self, другого экземпляра скрипта или даже синглтона:
func double(number):
return number * 2
func _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) в выражении.Ссылайтесь на переменные-члены экземпляра (
var) в выражении.Вызовите методы, определенные в экземпляре, и используйте их возвращаемые значения в выражении.
Предупреждение
Установка базового экземпляра в значение, отличное от null, позволяет ссылаться на константы, переменные-члены и вызывать все методы, определённые в скрипте, прикреплённом к экземпляру. Разрешение пользователям вводить выражения может привести к читерству в вашей игре или даже создать уязвимости безопасности, если вы разрешите произвольным клиентам запускать выражения на устройствах других игроков.
Пример скрипта
Приведенный ниже скрипт демонстрирует возможности класса Expression:
const DAYS_IN_YEAR = 365
var script_member_variable = 1000
func _ready():
# Constant boolean expression.
evaluate("true && false")
# Boolean expression with variables.
evaluate("!(a && b)", ["a", "b"], [true, false])
# Constant mathexpression.
evaluate("2 + 2")
# Math expression with variables.
evaluate("x + y", ["x", "y"], [60, 100])
# Call built-in method (built-in math function call).
evaluate("deg_to_rad(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
Вывод скрипта будет следующим:
false
true
4
160
1.5707963267949
You called 'call_me()' in the expression text.
1365
You called 'call_me()' in the expression text.
Argument passed: 42
0
You called 'call_me()' in the expression text.
Argument passed: some string
0
Встроенные функции
Все методы в Global Scope доступны в классе Expression, даже если к выражению не привязан ни один базовый экземпляр. Доступны те же параметры и типы возвращаемых значений.
Однако, в отличие от GDScript, параметры всегда обязательны, даже если они указаны как необязательные в ссылке на класс. В отличие от этого, это ограничение на аргументы не распространяется на пользовательские функции при привязке базового экземпляра к выражению.