Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
運算式求值
Godot 提供 Expression 類別,可用來計算運算式。
運算式可以是:
數學運算式,例如
(2 + 4) * 16/4.0。布林運算式,例如
true && false。內建函式呼叫,例如
deg_to_rad(90)。如果於呼叫 Expression.execute() 時將
base_instance設為非null,則可以呼叫用戶自訂腳本的方法,如update_health()。
備註
Expression 類別獨立於 GDScript,即使編譯 Godot 時未啟用 GDScript 模組也可使用。
基本用法
要計算數學運算式,請使用:
var expression = Expression.new()
expression.parse("20 + 10*2 - 5/2.0")
var result = expression.execute()
print(result) # 37.5
可用的運算子如下:
運算子 |
說明 |
|---|---|
加法( |
亦可用於串接字串與陣列:- |
減法( |
|
乘法( |
|
除法( |
若兩個運算元皆為整數則執行整數除法;只要其中一個為浮點數則返回浮點數結果。 |
餘數( |
回傳整數除法的餘數(取模)。結果符號與被除數相同。 |
邏輯 AND( |
回傳布林值 AND 的結果。 |
邏輯 OR( |
回傳布林值 OR 的結果。 |
邏輯 NOT( |
回傳布林值 NOT 的結果。 |
運算子前後空格可加可不加。請注意一般的 運算子優先順序 依然適用。有需要時可用括號改變運算順序。
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 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 不同,這些函式的所有參數**皆必填**,即使在類別文件中標記為可選也一樣。若有綁定基礎實例,則自訂函式則不受此限制。