A partir de 1º de novembro de 2024 na versão 32.00, estamos estabilizando a linguagem Verse para a versão 1. Recomendamos que você atualize seu projeto para maior estabilidade e para facilitar a atualização incremental do seu código quando futuras atualizações da linguagem Verse forem disponibilizadas. Essa atualização é opcional: sua versão atual do projeto sempre continuará a funcionar em uma versão mais antiga do Verse. Dito isso, pode haver um momento no futuro em que você precisará atualizar seu projeto para uma versão mais recente do Verse se quiser carregar uma iteração mais recente dele.
Desde seu primeiro lançamento público, continuamos a enriquecer e aprimorar a linguagem do Verse, sempre divulgando de maneira transparente para as pessoas e sem que seja necessário aprimorar para uma nova versão. Acreditamos que isso não vá mudar, e a maioria das alterações implementadas na linguagem será compatível com versões anteriores e divulgadas a todos com os lançamentos novos do UEFN.
No entanto, algumas alterações de linguagem não são compatíveis com versões anteriores e podem exigir alterações no seu código para que ele seja compilado. Essas alterações incompatíveis com versões anteriores apenas serão acionadas se o usuário atualizar seu projeto para direcionar a nova versão da linguagem.
Avisos aparecerão sempre que você salvar um código que não é compatível com versões anteriores e indicarão que o comportamento do seu código está obsoleto em versões mais recentes da linguagem. Por exemplo, continuar usando práticas de codificação que não são compatíveis com a nova versão da linguagem Verse resultará em avisos sobre seu código.
Se o seu projeto for compilado na V0 sem nenhum aviso de descontinuação, você poderá atualizar para a V1 sem alterações no comportamento do seu código. Quando você abrir um projeto da V0 no UEFN 32.00 e ele for compilado sem erros ou avisos, o editor perguntará se você deseja atualizar.

Se quiser atualizar ou rebaixar mais tarde por qualquer motivo, você poderá fazer isso nas configurações do seu projeto.
Click image to enlarge.
Você também pode abrir arquivos de projeto na pasta Projetos do Fortnite e alterar a versão do Verse dos arquivos .uplugin .
Click image to enlarge.
A maioria das descontinuações abre caminho para melhorias futuras da linguagem e ainda não fornece nenhum benefício para os usuários. Duas exceções são qualificadores locais e comparação de structs.
Mudanças na V1
Falha em Set
A expressão que um set
executa não pode mais falhar. Anteriormente, o código:
F():void=
var X:int = 0
set X = FailableExpression[]
era permitido, e X
teria sido definido como qualquer FailableExpression
avaliada com um aviso. Na V1, isso não é permitido.
Para corrigir seu código, você precisará garantir que a expressão não possa falhar. Uma maneira possível de fazer isso é com a seguinte modificação:
var X:int = 0
Value:= FailableExpression[] ou DefaultValue
set X = Value
Falha em chaves de literais de mapa
Anteriormente, era possível que as chaves de literais em um mapa falhassem:
map{ExpressionThatCannotFail=>Value}
Um exemplo simples é map{ (0 = 0) =>0 }
, em que 0 = 0
falha. Isso não é mais permitido.
Como misturar separadores de ponto e vírgula, vírgula e nova linha para blocos
Anteriormente, a mistura de ponto e vírgula/vírgulas/novas linhas para separar subexpressões era permitida e resultava no código exibido abaixo:
A,
B
for (A := 0..2):
# more code here
Internamente depurado para o código, conforme exibido abaixo:
block:
A
B
for (A := 0..2):
# more code here
Isso significava que ambas as definições de A
no bloco de código não entravam em conflito entre si, pois era criado um bloco implícito que tinha seu próprio escopo separado.
No entanto, esse é um comportamento incorreto e foi corrigido na versão mais recente da linguagem Verse. Agora, o mesmo código trata cada subexpressão separadamente, resultando no seguinte:
A
B
for (A := 0..2):
# more code here
Isso significa que o primeiro A e a segunda definição de A := 0..2
agora se sobrepõem, e o significado é ambíguo.
Para corrigir isso, ambos os criadores (e todos que dependem desse comportamento) devem parar de misturar ponto e vírgula, vírgulas e novas linhas para separar subexpressões em todo o código Verse.
Example:
PropPosition := Prop.GetTransform().Translation,
if(Round[PropPosition.Z] = Round[ROOT_POSITION.Z]) { break }
Sleep(0.0)
Deve ser modificado para:
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, um aviso era gerado sempre que separadores misturados eram detectados, começando em 28.20
. Agora, isso não é permitido na versão mais recente da linguagem Verse.
Alterações do especificador exclusivo
Classes com o especificador <unique>
agora exigem o efeito de construção <allocates>
. Por exemplo, a class<unique><computes>
não é mais permitida.
Qualificadores locais de função
O qualificador (local:)
pode ser aplicado a identificadores dentro de funções para desambiguá-los de outros identificadores.
For example:
ExternallyDefinedModuleB<public> := module:
ShadowX<public>:int = 10 # adicionado somente após a publicação de `ModuleC`
ModuleC := module:
using{ExternallyDefinedModuleB}
FooNoLocal():float=
ShadowX:float = 0.0
ShadowX
O código acima produziria um erro de sombreamento, pois ShadowX
é ambíguo (é de ExternallyDefinedModuleB.ShadowX
ou ShadowX
dentro de FooNoLocal
?)
Para resolver isso, você pode usar o qualificador (local:)
para ter clareza sobre qual ShadowX
está sendo referenciado, como no exemplo abaixo:
ExternallyDefinedModuleA<public> := module:
ShadowX<public>:int = 10 # adicionado somente após a publicação de `ModuleB`
ModuleB := module:
using{ExternallyDefinedModuleA}
FooLocal():float=
(local:)ShadowX:float = 0.0 #O qualificador `local` pode ser usado aqui para desambiguar
(local:)ShadowX
Anteriormente, gerávamos um aviso quando detectávamos que você estava usando a palavra local
como identificador de definição de dados, pois agora essa é uma palavra-chave reservada. Na versão mais recente da linguagem, o uso de local
resulta em um erro e, se você quiser usar o identificador local
como um identificador de definição de dados normal, seu uso deverá ser explicitamente qualificado.
Aqui está outro exemplo de um qualificador local:
MyModule := module:
X:int = 1
Foo((local:)X:int):int = (MyModule:)X + (local:)X
Neste exemplo, se não especificássemos o qualificador (local:)
, o X
em Foo (X:int)
ocultaria a definição X:int = 1
diretamente acima, já que os dois identificadores X
estão no mesmo escopo. Portanto, usar o qualificador (local:)
nos permite diferenciar os dois, tornando o X
na cláusula de parâmetro de argumento de Foo
específico apenas dentro do escopo de Foo
. O mesmo se aplica aos identificadores X
no corpo de Foo
.
Campos públicos em structs
Todos os campos em struct
s agora devem ser públicos. Por padrão, esse também é o caso a partir da V1 (não é mais necessário usar <public>
).
A V1 também adiciona a capacidade de comparar dois struct
s. Se todos os campos de um struct forem comparáveis, você poderá usar =
para comparar duas instâncias do struct campo por campo. Por exemplo:
vector3i := struct{X:int, Y:int, Z:int}
vector3i{X:=0, Y:=0, Z:=0} = vector3i{X:=0, Y:=0, Z:=0} # tem êxito
vector3i{X:=0, Y:=0, Z:=0} = vector3i{X:=0, Y:=0, Z:=1} # falha porque Z é diferente entre as duas instâncias