A partir del 1 de noviembre de 2024 con la versión 32.00, estabilizaremos el lenguaje Verse a la versión 1. Te recomendamos que actualices tu proyecto tanto por estabilidad como para que sea más fácil actualizar el código de forma incremental cuando lleguen futuras actualizaciones del lenguaje Verse. Esta mejora es opcional; tu versión actual del proyecto seguirá funcionando siempre en una versión anterior de Verse. Dicho esto, puede haber un momento en el futuro en el que tengas que actualizar tu proyecto a una versión más reciente de Verse si quieres cargar una nueva versión del mismo.
Desde su primera versión pública, el lenguaje Verse ha seguido evolucionando de forma transparente para los usuarios, sin necesidad de actualizar a una nueva versión. Esperamos que esto continúe, de modo que la mayoría de los cambios del lenguaje sigan siendo compatibles con sus versiones anteriores y lleguen a los usuarios junto a las nuevas versiones de UEFN.
Sin embargo, algunos cambios del lenguaje no son compatibles con versiones anteriores y pueden requerir cambios en el código para que este se compile. Esta incompatibilidad solo se activará si el usuario actualiza su proyecto para adaptarlo a la nueva versión del idioma.
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á en desuso en las versiones más recientes del lenguaje. Por ejemplo, si sigues utilizando prácticas de programación que no son compatibles con la nueva versión del lenguaje Verse, aparecerán advertencias sobre tu código.
Si tu proyecto se compila en la versión V0 sin avisos de desactivación, puedes actualizar a la V1 sin cambios en el comportamiento de tu código. Cuando abras un proyecto de la V0 en la versión 32.00 de UEFN y se compile sin errores ni advertencias, el editor te preguntará si deseas actualizar.
Si más adelante quieres actualizarlo o cambiarlo a una versión anterior, puedes hacerlo en la configuración del proyecto.
Click image to enlarge.
También puedes abrir archivos de 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 funciones obsoletas permitirán futuras mejoras del lenguaje y todavía no aportan ningún beneficio a los usuarios, salvo por dos excepciones: los calificadores locales y la comparación de estructuras.
Cambios en la V1
Fallo en set
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 a cualquier FailableExpression que se evaluara con una advertencia. En la V1, esto no está permitido.
Para corregir tu código, tendrás que asegurarte de que la expresión no puede fallar. Una forma de hacerlo es a través de la siguiente modificación:
var X:int = 0
Value:= FailableExpression[] or DefaultValue
set X = Value
Fallo en las claves del literal del mapa
Anteriormente, las claves literales de un mapa podían fallar:
map{ExpressionThatCannotFail=>Value}
Un ejemplo sencillo es map{ (0 = 0) =>0 }, en el que 0 = 0 falla. Esto ya no está permitido.
Cómo mezclar los separadores de punto y coma, coma y nueva línea para bloques
Anteriormente, se permitía mezclar puntos y coma/comas/nuevas líneas 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 descompilaba de esta forma:
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 independiente.
Sin embargo, este comportamiento es incorrecto y se ha corregido en la última versión del lenguaje Verse. Ahora el mismo código tratará cada subexpresión por separado, que dará como resultado 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 hacen sombra mutuamente y el significado es ambiguo.
Para solucionarlo, los creadores (y cualquiera que confíe en este comportamiento) deben dejar de mezclar puntos y coma/comas/nueva línea para separar subexpresiones en todo su código Verse.
Example:
PropPosition := Prop.GetTransform().Translation,
if(Round[PropPosition.Z] = Round[ROOT_POSITION.Z]) { break }
Sleep(0.0)
Debería modificarse para que sea:
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 un aviso cada vez que se detectaban separadores mixtos a partir de la versión 28.20. Esto no está permitido en la última versión del lenguaje Verse.
Cambios en el especificador unique
Las clases con el especificador <unique> ahora requieren el efecto de construcción <allocates>. Por ejemplo, class<unique><computes> ya no está permitido.
Calificadores locales de función
El calificador (local:) puede aplicarse a los identificadores dentro de las funciones para eliminar la ambigüedad de otros identificadores.
For example:
ExternallyDefinedModuleB<public> := module:
ShadowX<public>:int = 10 # Se añade 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 (¿proviene de ExternallyDefinedModuleB.ShadowX o del ShadowX dentro de FooNoLocal?).
Para solucionarlo, puedes utilizar el calificador (local:) para aclarar a qué ShadowX se refiere, como en el ejemplo siguiente:
ExternallyDefinedModuleA<public> := module:
ShadowX<public>:int = 10 # Se añade solo después de la publicación de `ModuleB`.
ModuleB := module:
using{ExternallyDefinedModuleA}
FooLocal():float=
(local:)ShadowX:float = 0.0 #El calificador `local` puede utilizarse aquí para eliminar la ambigüedad.
(local:)ShadowX
Anteriormente, se producía una advertencia cuando se detectaba que se estaba utilizando la palabra local como identificador de definición de datos, ya que ahora se trata de una palabra clave reservada. En la última versión del lenguaje, el uso de local produce un error, y si quieres utilizar el identificador local como un identificador de definición de datos normal, su uso debe calificarse explícitamente.
Aquí tienes otro ejemplo de calificador local:
MyModule := module:
X:int = 1
Foo((local:)X:int):int = (MyModule:)X + (local:)X
En este ejemplo, si no se especificara el calificador (local:), la X de Foo(X:int) haría sombra a la definición X:int = 1 directamente arriba, ya que ambos identificadores X están en el mismo ámbito. Por tanto, el calificador (local:) permite eliminar la ambigüedad de los dos, haciendo que la X de la cláusula del parámetro del argumento de Foo sea específica solo dentro del ámbito de Foo. Lo mismo se aplica a los identificadores X en el cuerpo de Foo.
Campos públicos en estructuras
Ahora todos los campos de struct deben ser públicos. De forma predeterminada, esto también ocurre a partir de la versión 1 (ya no es necesario utilizar <public>).
La versión 1 también incluye la posibilidad de comparar dos struct. Si todos los campos de una estructura son comparables, puedes utilizar = 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} # Se completa correctamente.
vector3i{X:=0, Y:=0, Z:=0} = vector3i{X:=0, Y:=0, Z:=1} # Falla porque Z es diferente entre las dos instancias.