A partir del 1 de noviembre de 2024 con la versión 32.00, estabilizaremos el lenguaje de Verse a la versión 1. Te recomendamos que actualices tu proyecto tanto por su estabilidad como para que sea más fácil actualizar tu código de forma incremental cuando lleguen futuras actualizaciones del lenguaje Verse. Esta mejora es opcional; tu versión actual del proyecto siempre seguirá funcionando en una versión anterior de Verse. Dicho esto, puede haber un momento en el futuro en el que necesites actualizar tu proyecto a una versión más reciente de Verse si deseas cargar una iteración más nueva del mismo.
Desde su primer lanzamiento público, seguimos ampliando y desarrollando el lenguaje Verse y esos cambios se han distribuido de forma transparente a los usuarios sin necesidad de actualizar a una nueva versión del lenguaje. Esto continuará así y la mayor parte de los cambios en el lenguaje se harán de forma que tengan retrocompatibilidad con versiones anteriores del lenguaje y se distribuirán a los usuarios con nuevos lanzamientos de UEFN.
Sin embargo, algunos cambios de lenguaje no son compatibles con versiones anteriores y pueden requerir cambios en el código para que el código se compile. Dichos cambios incompatibles con versiones anteriores solo se activarán si el usuario actualiza su proyecto para que esté en la nueva versión del lenguaje.
Las advertencias aparecerán cada vez que guardes código que no sea compatible con versiones anteriores e indicarán que el comportamiento de tu código está obsoleto en las versiones más recientes del lenguaje. Por ejemplo, continuar utilizando prácticas de codificación que no son compatibles con la nueva versión del lenguaje Verse generará advertencias sobre tu código.
Si tu proyecto compila en la V0 sin ninguna advertencia de obsolescencia, puedes actualizar a la V1 sin ningún cambio en el comportamiento de tu código. Cuando abres un proyecto V0 en UEFN 32.00 y se compila sin errores ni advertencias, el editor te preguntará si deseas actualizar.
Si deseas actualizar o volver a la versión anterior más adelante por algún motivo, puedes hacerlo en la configuración de tu proyecto.
Click image to enlarge.
También puedes abrir los archivos del proyecto desde la carpeta Proyectos de Fortnite y cambiar la versión de Verse de los archivos .uplugin .
Click image to enlarge.
La mayoría de las obsolescencias preparan el camino para futuras mejoras del lenguaje y aún no brindan ningún beneficio a los usuarios. Dos excepciones son los calificadores locales y la comparación de estructuras.
Cambios en V1
Fallo en conjunto
Ya no se permite que la expresión que ejecuta un set falle. Anteriormente, el código:
F():void=
var X:int = 0
set X = FailableExpression[]
Estaba permitido, y X se habría establecido en lo que sea que FailableExpression evaluó con una advertencia. En la V1, esto no está permitido.
Para corregir el código, deberás asegurarte de que la expresión no pueda fallar. Una forma posible de hacerlo es con la siguiente modificación:
var X:int = 0
Value:= FailableExpression[] or DefaultValue
set X = Value
Fallo en las claves literales del mapa
Anteriormente, las claves literales de un mapa podían fallar:
map{ExpressionThatCannotFail=>Value}
Un ejemplo simple es map{ (0 = 0) =>0 }, donde 0 = 0 falla. Esto ya no está permitido.
Cómo mezclar separadores de punto y coma, coma y nueva línea para bloques
Anteriormente, se permitía mezclar puntos y comas, comas y líneas nuevas para separar subexpresiones, lo que resultaba en código como el que se muestra a continuación:
A,
B
for (A := 0..2):
# more code here
Internamente, este código se interpretaba como:
block:
A
B
for (A := 0..2):
# more code here
Esto significaba que ambas definiciones de A en el bloque de código no entraban en conflicto entre sí, ya que se creaba un bloque implícito que tenía su propio ámbito separado.
Sin embargo, este es un comportamiento incorrecto y se corrigió en la última versión del lenguaje Verse. Ahora, ese mismo código trata a cada subexpresión por separado, lo que resulta en lo siguiente:
A
B
for (A := 0..2):
# more code here
Esto significa que la primera A y la segunda definición de A := 0..2 ahora se sombrean entre sí y el significado es ambiguo.
Para solucionar esto, los creadores (y cualquier persona que confíe en este comportamiento) deben dejar de mezclar puntos y comas, comas y líneas nuevas para separar subexpresiones en todo su código de Verse.
Example:
PropPosition := Prop.GetTransform().Translation,
if(Round[PropPosition.Z] = Round[ROOT_POSITION.Z]) { break }
Sleep(0.0)
Debería modificarse de la siguiente manera:
PropPosition := Prop.GetTransform().Translation # note the trailing comma here has been removed
if(Round[PropPosition.Z] = Round[ROOT_POSITION.Z]) { break }
Sleep(0.0)
Anteriormente, se producía una advertencia cada vez que se detectaban separadores mixtos a partir de 28.20. Esto ahora no está permitido en la última versión del lenguaje Verse.
Cambios en el especificador de unicidad
Las clases con el especificador <unique> ahora requieren el efecto de construcción <allocates>. Por ejemplo, la clase class<unique><computes> ya no está permitida.
Calificadores locales de función
El calificador (local:) puede aplicarse a identificadores dentro de funciones para desambiguarlos de otros identificadores.
For example:
ExternallyDefinedModuleB<public> := module:
ShadowX<public>:int = 10 # añadido solo después de la publicación de `ModuleC`
ModuleC := module:
using{ExternallyDefinedModuleB}
FooNoLocal():float=
ShadowX:float = 0.0
ShadowX
El código anterior produciría un error de sombreado, ya que ShadowX es ambiguo (¿es de ExternallyDefinedModuleB.ShadowX o ShadowX dentro de FooNoLocal?)
Para resolver esto, puedes usar el calificador (local:) para aclarar a qué ShadowX se refiere, como en el siguiente ejemplo:
ExternallyDefinedModuleA<public> := module:
ShadowX<public>:int = 10 # añadido solo después de la publicación de `ModuleB`
ModuleB := module:
using{ExternallyDefinedModuleA}
FooLocal():float=
(local:)ShadowX:float = 0.0 #El calificador `local` puede usarse aquí para desambiguar
(local:)ShadowX
Anteriormente, generábamos una advertencia cuando detectábamos que estabas usando la palabra local como identificador de definición de datos, ya que ahora es una palabra clave reservada. En la última versión del lenguaje, el uso de local da como resultado un error, y si deseas utilizar el identificador local como un identificador de definición de datos normal, su uso debe calificarse explícitamente.
Este es otro ejemplo de un calificador local:
MyModule := module:
X:int = 1
Foo((local:)X:int):int = (MyModule:)X + (local:)X
En este ejemplo, si no se especifica el calificador (local:), la X en Foo(X:int) ensombrecería la definición X:int = 1 directamente arriba, ya que tanto X están en el mismo ámbito. Por lo tanto, usar el calificador (local:) nos permite desambiguar los dos, al hacer que la X en la cláusula del parámetro del argumento de Foo sea específica de solo dentro del ámbito de Foo. Lo mismo se aplica a los identificadores X en el cuerpo de Foo.
Campos públicos en estructuras
Todos los campos en las struct ahora deben ser públicos. De forma predeterminada, este también es el caso a partir de la V1. (Usar <public> ya no es necesario).
La V1 también añade la capacidad de comparar dos struct. Si todos los campos de una estructura son comparables, entonces puedes usar = para comparar dos instancias de la estructura campo por campo. Por ejemplo:
vector3i := struct{X:int, Y:int, Z:int}
vector3i{X:=0, Y:=0, Z:=0} = vector3i{X:=0, Y:=0, Z:=0} # tiene éxito
vector3i{X:=0, Y:=0, Z:=0} = vector3i{X:=0, Y:=0, Z:=1} # falla porque Z es diferente entre las dos instancias