表达式估值
Godot 提供了 Expression 类,可以用来对表达式进行估值。
表达式可以是:
类似
(2 + 4) * 16/4.0
的数学表达式。类似
deg2rad(90)
的内置方法调用。调用 Expression.execute() 时如果
base_instance
非null
,那么调用用户提供脚本的方法,比如update_health()
。
备注
Expression 类是独立于 GDScript 的。即便禁用 GDScript 模块编译 Godot 也能使用。
基本用法
要对数学表达式求值,请使用:
var expression = Expression.new()
expression.parse("20 + 10*2 - 5/2.0")
var result = expression.execute()
print(result) # 37.5
可以使用以下操作符:
操作符 | 注意 |
---|---|
加 | 还可以用于连接字符串和数组:- |
减( | |
乘( | |
除( | 两个操作数都是整数时执行整数除法。如果至少有一个是浮点数,就会返回浮点值。 |
求余( | 返回整数除法的余数。 |
操作符周围的空格是可选的。另外请记住,此处适用一般的运算次序。必要时请使用括号来覆盖运算符的次序。
Godot 所支持的所有 Variant 类型都可以使用:整数、浮点数、字符串、数组、字典、颜色、向量……
数组与字典的索引方法与 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 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
脚本的输出将会是:
4
160
1.570796
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
内置函数
@GDScript 作用域中的大多数方法都可以在 Expression 类中使用,无需为表达式绑定基础实例。参数和返回类型也是一样的。
然而,与 GDScript 不同,参数始终是必须的,即使类参考中说明此参数为可选。不过,为表达式绑定了基础实例时,用户定义函数的参数没有此限制。