A partire dal 1° novembre 2024 con la release 32.00, abbiamo intenzione di stabilire la prima versione del linguaggio Verse. Ti consigliamo di aggiornare il tuo progetto sia per motivi di stabilità sia in modo che sia più facile aggiornare il codice in modo incrementale quando arriveranno futuri aggiornamenti del linguaggio Verse. Questo aggiornamento è facoltativo; la versione attuale del progetto continuerà a funzionare anche con la versione precedente di Verse. Detto questo, in futuro potresti dover aggiornare il progetto a una versione più recente di Verse se desideri caricare una nuova iterazione.
Sin dalla sua prima versione pubblica, abbiamo continuato ad aggiungere e far evolvere il linguaggio Verse, con tali modifiche che sono state presentate agli utenti con la massima trasparenza senza richiedere aggiornamenti a una nuova versione del linguaggio. Prevediamo che questa tendenza continuerà: la maggior parte delle modifiche al linguaggio saranno retrocompatibili con le precedenti versioni del linguaggio e verranno presentate agli utenti con le nuove release di UEFN.
Tuttavia, alcune modifiche al linguaggio non sono compatibili con le versioni precedenti e potrebbero richiedere modifiche al codice per la compilazione. Le modifiche non compatibili con le versioni precedenti saranno applicate solo aggiornando il progetto per utilizzare la nuova versione del linguaggio.
Vengono mostrati avvisi ogni volta che si salva codice non compatibile, indicando che il comportamento è deprecato nelle versioni più recenti. Ad esempio, continuare a utilizzare pratiche di codifica non compatibili con la nuova versione di Verse genererà avvisi sul codice.
Se il tuo progetto viene compilato in V0 senza alcun avviso di deprecazione, puoi eseguire l'aggiornamento a V1 senza apportare modifiche al comportamento del codice. Quando apri un progetto V0 nella versione di UEFN 32.00 e viene compilato senza errori o avvisi, l'editor ti chiede se desideri eseguire l'aggiornamento.

Se per qualsiasi motivo desidererai eseguire l'upgrade o il downgrade in un secondo momento, potrai sempre farlo nelle impostazioni del tuo progetto.
Click image to enlarge.
Puoi anche aprire i file di progetto dalla cartella Progetti di Fortnite e modificare la versione Verse dei file .uplugin .
Click image to enlarge.
La maggior parte delle deprecazioni ha aperto la strada a futuri miglioramenti del linguaggio e non offre ancora alcun vantaggio agli utenti. Due eccezioni sono i qualificatori locali e il confronto delle struct.
Modifiche nella V1
Errore nel set
L'espressione eseguita da un set
non può più avere un esito negativo. In precedenza, il codice si presentava così:
F():void=
var X:int = 0
set X = FailableExpression[]
Se fosse permesso, X
sarebbe stato impostato su qualsiasi valore di FailableExpression
valutato con un avviso. Nella V1, questo non è permesso.
Per correggere il codice, devi assicurarti che l'espressione non possa avere esito negativo. Una strategia possibile per garantirlo è applicare la modifica seguente:
var X:int = 0
Value:= FailableExpression[] or DefaultValue
set X = Value
Errore nelle chiavi letterali della mappa
In precedenza, l'utilizzo di chiavi letterali in una mappa poteva causare errori:
map{ExpressionThatCannotFail=>Value}
Un semplice esempio è map{ (0 = 0) =>0 }
, in cui 0 = 0
non ha esito positivo. Questa modalità non è più valida.
Alternare i separatori punto e virgola/virgola/nuova riga in un blocco
In precedenza, era permesso alternare punti e virgola, virgole e nuove righe per separare le sottoespressioni e il risultato era un codice come quello mostrato di seguito:
A,
B
for (A := 0..2):
# more code here
Internamente veniva trasformato in codice come mostrato di seguito:
block:
A
B
for (A := 0..2):
# more code here
Ciò significava che entrambe le definizioni di A
nel blocco di codice non entravano in conflitto tra loro, poiché veniva creato implicitamente un blocco con un ambito separato.
Tuttavia, si tratta di un comportamento errato che è stato corretto nell'ultima versione del linguaggio Verse. Ora, lo stesso codice tratta ogni sottoespressione separatamente, garantendo il risultato seguente:
A
B
for (A := 0..2):
# more code here
Ciò significa che la prima A e la seconda definizione di A := 0..2
ora si sovrappongono, rendendo il significato ambiguo.
Per risolvere questo problema, i creatori (e tutti coloro che si affidano a questo comportamento) devono smettere di alternare punto e virgola/comma/nuova riga per separare le sottoespressioni all'interno del loro intero codice Verse.
Example:
PropPosition := Prop.GetTransform().Translation,
if(Round[PropPosition.Z] = Round[ROOT_POSITION.Z]) { break }
Sleep(0.0)
Dovrebbe essere modificato in:
PropPosition := Prop.GetTransform().Translation # note the trailing comma here has been removed
if(Round[PropPosition.Z] = Round[ROOT_POSITION.Z]) { break }
Sleep(0.0)
In precedenza, a partire dalla versione 28.20, veniva generato un avviso ogni volta che venivano rilevati separatori misti. Nella versione più recente del linguaggio Verse, ciò non è più consentito.
Modifiche allo specificatore univoco
Le classi con lo specificatore <unique>
richiedono ora l'effetto di costruzione <allocates>
. Ad esempio, class<unique><computes>
non è più permessa.
Qualificatori funzione-luogo
Il qualificatore (local:)
può essere applicato agli identificatori all'interno delle funzioni per distinguerli da altri identificatori.
For example:
ExternallyDefinedModuleB<public> := module:
ShadowX<public>:int = 10 # aggiunto solo dopo la pubblicazione di `ModuleC`
ModuleC := module:
using{ExternallyDefinedModuleB}
FooNoLocal():float=
ShadowX:float = 0.0
ShadowX
Il codice precedente produrrebbe un errore di sovrapposizione, dal momento cheShadowX
è un parametro ambiguo (proviene da ExternallyDefinedModuleB.ShadowX
o da ShadowX
all'interno di FooNoLocal
?)
Per risolvere questo errore, puoi utilizzare il qualificatore (local:)
per chiarire a quale ShadowX
si riferisce, come nell'esempio seguente:
ExternallyDefinedModuleA<public> := module:
ShadowX<public>:int = 10 # aggiunto solo dopo la pubblicazione di `ModuleB`
ModuleB := module:
using{ExternallyDefinedModuleA}
FooLocal():float=
(local:)ShadowX:float = 0.0 #Il qualificatore `local` può essere utilizzato qui per stabilire una distinzione tra i parametri
(local:)ShadowX
In precedenza, veniva mostrato un avviso se la parola local
veniva utilizzata come identificatore per definire dati, poiché rappresentava una parola chiave riservata. Nell'ultima versione del linguaggio, l'uso di local
genera un errore. Per utilizzare local
come identificatore per definire dati, è necessario qualificarlo esplicitamente.
Ecco un altro esempio di qualificatore locale:
MyModule := module:
X:int = 1
Foo((local:)X:int):int = (MyModule:)X + (local:)X
In questo esempio, se non si specifica il qualificatore (local:)
, la X
in Foo(X:int)
va a sovrappore la definizione X:int = 1
, poiché entrambi gli identificatori X
occupano lo stesso ambito. Pertanto, l'utilizzo del qualificatore (local:)
ci permette di disambiguare i due, rendendo la X
nella clausola del parametro dell'argomento di Foo
specifica solo all'interno dell'ambito di Foo
stesso. Lo stesso vale anche per gli identificatori X
nel corpo di Foo
.
Campi pubblici nelle struct
Tutti i campi nelle struct
devono ora essere pubblici. Per impostazione predefinita, questa è la configurazione standard a partire dalla V1. (l'utilizzo di <public>
non è più necessario).
V1 consente ora anche di confrontare due struct
. Se tutti i campi di una struct sono confrontabili, puoi utilizzare =
per confrontare due sue rispettive istanze campo per campo. Ad esempio:
vector3i := struct{X:int, Y:int, Z:int}
vector3i{X:=0, Y:=0, Z:=0} = vector3i{X:=0, Y:=0, Z:=0} # Ha esito positivo
vector3i{X:=0, Y:=0, Z:=0} = vector3i{X:=0, Y:=0, Z:=1} # Ha esito negativo perché Z è diverso tra le due istanze