Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Evaluando expresiones

Godot proporciona una clase Expression que puedes usar para evaluar expresiones.

Una expresión puede ser:

  • Una expresión matemática como (2 + 4) * 16/4.0.

  • A built-in method call like deg_to_rad(90).

  • Una llamada a un método en un script proporcionado por el usuario, como update_health(), si base_instance se establece con un valor distinto de null al llamar a Expression.execute().

Nota

La clase Expression es independiente de GDScript. Está disponible incluso si compilas Godot con el módulo GDScript desactivado.

Uso básico

Para evaluar una expresión matemática, utiliza:

var expression = Expression.new()
expression.parse("20 + 10*2 - 5/2.0")
var result = expression.execute()
print(result)  # 37.5

Los siguientes operadores estan disponibles:

Operador

Notas

Adición +

Correcto, también se puede utilizar para concatenar cadenas y arreglos: - "hello" + " world" = hello world- [1, 2] + [3, 4] = [1, 2, 3, 4]

Sustacción (-)

Multiplicación (*)

División (/)

Realiza una división entera si ambos operandos son enteros. Si al menos uno de ellos es un número de punto flotante, devuelve un valor de punto flotante.

Modulo o Residuo (%)

Devuelve el residuo de una división entera.

Los espacios alrededor de los operadores son opcionales. Además, ten en cuenta que se aplica el orden habitual de las operaciones. Utiliza paréntesis para anular el orden de las operaciones si es necesario.

Todos los tipos de variantes admitidos en Godot se pueden usar: enteros, números de punto flotante, cadenas, arreglos, diccionarios, colores, vectores, entre otros…

Los arreglos y diccionarios se pueden indexar igual que en 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

Pasando variables a una expresión

Puedes pasar variables a una expresión. Estas variables estarán disponibles en el "contexto" de la expresión y se sustituirán cuando se utilicen en la expresión:

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

Tanto los nombres de las variables como los valores de las variables deben especificarse como un arreglo, incluso si solo defines una variable. Además, los nombres de las variables son sensibles a mayúsculas y minúsculas.

Configurando una instancia base para la expresión

Por defecto, una expresión tiene una instancia base de null. Esto significa que la expresión no tiene ninguna instancia base asociada a ella.

Cuando llamas a Expression.execute(), puedes establecer el valor del parámetro base_instance en una instancia específica de objeto, como self, otra instancia de script o incluso un singleton:

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

Asociar una instancia base permite hacer lo siguiente:

  • Referenciar las constantes (const) de la instancia en la expresión.

  • Referenciar las variables miembro (var) de la instancia en la expresión.

  • Llamar a los métodos definidos en la instancia y utilizar sus valores de retorno en la expresión.

Advertencia

Establecer una instancia base con un valor distinto de null permite hacer referencia a constantes, variables miembro y llamar a todos los métodos definidos en el script adjunto a la instancia. Permitir que los usuarios ingresen expresiones puede permitir trampas en tu juego, o incluso introducir vulnerabilidades de seguridad si permites que clientes arbitrarios ejecuten expresiones en los dispositivos de otros jugadores. Por lo tanto, debes tener cuidado al permitir que los usuarios ingresen expresiones y asegurarte de validar y filtrar adecuadamente cualquier entrada para evitar posibles problemas.

Script de ejemplo

El siguiente script demuestra lo que la clase Expression es capaz de hacer:

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 (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

La salida de tu script será:

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

Funciones integradas

All methods in the Global 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.

Sin embargo, a diferencia de GDScript, los parámetros siempre son requeridos, incluso si se especifican como opcionales en la referencia de clase. En contraste, esta restricción en los argumentos no se aplica a las funciones hechas por el usuario cuando se vincula una instancia base a la expresión.