Ab dem 1.11.2024 in der Version 32.00 stabilisieren wir die Verse-Sprache auf Version 1. Wir empfehlen dir, dein Projekt zu aktualisieren, um die Stabilität zu gewährleisten und es einfacher zu machen, deinen Code schrittweise zu aktualisieren, wenn zukünftige Versionen der Verse-Sprache veröffentlicht werden. Dieses Upgrade ist optional; deine aktuelle Version des Projekts funktioniert weiterhin mit einer älteren Verse-Version. Abgesehen davon wird es in Zukunft möglicherweise einen Punkt geben, an dem du dein Projekt auf eine neuere Verse-Version aktualisieren musst, wenn du eine neuere Iteration davon hochladen möchtest.
Seit der ersten Veröffentlichung der Verse-Sprache haben wir die Verse-Sprache kontinuierlich weiterentwickelt, und diese Änderungen wurden transparent für die Benutzer eingeführt, ohne dass ein Upgrade auf eine neue Sprachversion erforderlich war. Wir rechnen damit, dass dies auch weiterhin so bleiben wird, da die meisten Sprachänderungen auf eine Weise durchgeführt werden, die mit vorherigen Versionen der Sprache abwärtskompatibel ist, und wir diese Änderungen mit neuen Versionen von UEFN für unsere Nutzer bereitstellen werden.
Einige Sprachänderungen sind jedoch nicht abwärtskompatibel und erfordern möglicherweise Änderungen an deinem Code, damit der Code kompiliert werden kann. Solche abwärtsinkompatiblen Änderungen werden nur ausgelöst, wenn der Benutzer sein Projekt aktualisiert, um die neue Sprachversion zu verwenden.
Jedes Mal, wenn du Code speicherst, der nicht abwärtskompatibel ist, werden Warnungen angezeigt, die darauf hinweisen, dass dein Codeverhalten in neueren Versionen der Sprache veraltet ist. Wenn du beispielsweise weiterhin Programmiermethoden verwendest, die nicht mit der neuen Verse-Sprachversion kompatibel sind, kommt es zu Warnungen für deinen Code.
Wenn dein Projekt in V0 ohne Verfallswarnungen kompiliert wird, kannst du auf V1 aktualisieren, ohne Änderungen am Verhalten deines Codes vorzunehmen. Wenn du ein V0-Projekt in UEFN 32.00 öffnest und es ohne Fehler oder Warnungen kompiliert wird, fragt der Editor, ob du ein Upgrade durchführen möchtest.
Wenn du später aus irgendwelchen Gründen ein Upgrade oder Downgrade durchführen möchtest, kannst du dies in deinen Projekt-Einstellungen tun.
Click image to enlarge.
Du kannst auch Projektdateien aus dem Fortnite-Projekte-Ordner öffnen und die Verse-Version der .uplugin-Dateien ändern.
Click image to enlarge.
Die meisten zurückgezogenen Features machen den Weg für zukünftige Sprachverbesserungen frei und bieten den Nutzern noch keine Vorteile. Zwei Ausnahmen sind lokale Qualifizierer und der Strukturvergleich.
Änderungen in V1
Fehlschlag in Set
Der Ausdruck, den ein set ausführt, darf nicht mehr fehlschlagen. Zuvor war der Code
F():void=
var X:int = 0
set X = FailableExpression[]
zulässig, und X wäre auf den Wert von FailableExpression gesetzt worden, der mit einer Warnung ausgewertet wurde. In V1 ist dies nicht mehr zulässig.
Um deinen Code zu korrigieren, musst du sicherstellen, dass der Ausdruck nicht fehlschlagen kann. Eine Möglichkeit, dies zu tun, ist mit der folgenden Änderung:
var X:int = 0
Value:= FailableExpression[] or DefaultValue
set X = Value
Fehler in literalen Map-Schlüsseln
Zuvor konnten literale Schlüssel in einer Map fehlschlagen:
map{ExpressionThatCannotFail=>Value}
Ein einfaches Beispiel ist map{ (0 = 0) =>0 }, wobei 0 = 0 fehlschlägt. Das ist nicht mehr erlaubt.
Vermischen von Semikolon/Komma/Zeilenumbruch-Trennzeichen für Blöcke
Bisher war das Vermischen von Semikolons/Kommas/Zeilenumbrüchen zur Trennung von Teilausdrücken zulässig und konnte zu Code wie folgt führen:
A,
B
for (A := 0..2):
# more code here
Wird intern auf Code optimiert, wie unten angezeigt:
block:
A
B
for (A := 0..2):
# more code here
Das bedeutete, dass die beiden Definitionen von A im Codeblock nicht im Konflikt zueinander standen, da ein impliziter Block erstellt wurde, der über einen eigenen separaten Bereich verfügte.
Dies ist jedoch ein fehlerhaftes Verhalten und wurde in der neuesten Verse-Sprachversion behoben. Jetzt behandelt der gleiche Code jeden Teilausdruck separat, was zu folgendem Ergebnis führt:
A
B
for (A := 0..2):
# more code here
Das bedeutet, dass das erste A und die zweite Definition von A := 0..2 einander überlagern und die Bedeutung mehrdeutig ist.
Um dies zu beheben, müssen beide Creators (und alle, die sich auf dieses Verhalten stützen), damit aufhören, Semikolons/Kommas/Zeilenumbrüche in ihrem Verse-Code zu vermischen, um Teilausdrücke zu trennen.
Example:
PropPosition := Prop.GetTransform().Translation,
if(Round[PropPosition.Z] = Round[ROOT_POSITION.Z]) { break }
Sleep(0.0)
Sollte wie folgt geändert werden:
PropPosition := Prop.GetTransform().Translation # note the trailing comma here has been removed
if(Round[PropPosition.Z] = Round[ROOT_POSITION.Z]) { break }
Sleep(0.0)
Zuvor wurde eine Warnung erzeugt, wenn gemischte Trennzeichen erkannt wurden, beginnend mit 28.20. Dies ist jetzt in der neuesten Verse-Sprachversion nicht mehr zulässig.
Änderungen am eindeutigen Spezifizierer
Klassen mit dem Spezifizierer <unique> erfordern nun den Konstruktionseffekt <allocates>. Zum Beispiel ist class <unique><computes> nicht mehr erlaubt.
Funktionslokale Qualifizierer
Der Qualifizierer (local:) kann auf Bezeichner innerhalb von Funktionen angewendet werden, um sie von anderen Bezeichnern zu unterscheiden.
For example:
ExternallyDefinedModuleB<public> := module:
ShadowX<public>:int = 10 # erst hinzugefügt, nachdem `ModuleC` veröffentlicht wurde
ModuleC := module:
using{ExternallyDefinedModuleB}
FooNoLocal():float=
ShadowX:float = 0.0
ShadowX
Der obige Code würde einen Überlagerungsfehler erzeugen, da ShadowX mehrdeutig ist (ist es aus ExternallyDefinedModuleB.ShadowX oder das ShadowX innerhalb von FooNoLocal?)
Um dies zu lösen, kannst du den Qualifizierer (local:) verwenden, um klar zu machen, auf welches ShadowX verwiesen wird, wie in dem folgenden Beispiel:
ExternallyDefinedModuleA<public> := module:
ShadowX<public>:int = 10 # erst hinzugefügt, nachdem `ModuleB` veröffentlicht wurde
ModuleB := module:
using{ExternallyDefinedModuleA}
FooLocal():float=
(local:)ShadowX:float = 0.0 #Der Qualifizierer `local` kann hier verwendet werden, um eine Mehrdeutigkeit zu beheben
(local:)ShadowX
Bisher haben wir eine Warnung ausgegeben, wenn wir entdeckt haben, dass du das Wort „local“ als Datendefinitionsbezeichner verwendest, da dies nun ein reserviertes Schlüsselwort ist. In der neuesten Sprachversion führt die Verwendung von local zu einem Fehler, und wenn du den Bezeichner local als normalen Datendefinitionsbezeichner verwenden möchtest, muss seine Verwendung explizit qualifiziert werden.
Hier ist ein weiteres Beispiel für einen lokalen Qualifizierer:
MyModule := module:
X:int = 1
Foo((local:)X:int):int = (MyModule:)X + (local:)X
Wenn wir in diesem Beispiel den Qualifizierer (local:) nicht angeben würden, würde das X in Foo(X:int) die Definition X:int = 1 direkt oben überlagern, da sich beide X -Bezeichner im selben Bereich befinden. Die Verwendung des Qualifizierers (local:) erlaubt es uns also, die beiden zu unterscheiden, indem wir das X in der Argumentparameterklausel von Foo spezifisch für nur innerhalb des Geltungsbereichs von Foo machen. Das Gleiche gilt auch für die X-Bezeichner im Körper von Foo.
Öffentliche Felder in Strukturen
Alle Felder in structs müssen nun öffentlich sein. Standardmäßig ist dies auch jetzt ab V1 der Fall (die Verwendung von <public> ist nicht mehr notwendig).
V1 fügt auch die Möglichkeit hinzu, zwei structs zu vergleichen. Wenn alle Felder einer Struktur vergleichbar sind, kannst du = verwenden, um zwei Instanzen der Struktur feldweise zu vergleichen. Zum Beispiel:
vector3i := struct{X:int, Y:int, Z:int}
vector3i{X:=0, Y:=0, Z:=0} = vector3i{X:=0, Y:=0, Z:=0} # erfolgreich
vector3i{X:=0, Y:=0, Z:=0} = vector3i{X:=0, Y:=0, Z:=1} # schlägt fehl, weil Z zwischen den beiden Instanzen unterschiedlich ist