Zum Inhalt springen

Skeleton-Walkthrough

Dieser Abschnitt beschreibt die grundlegende Struktur einer LightScript-Integration und behandelt wichtige technische Anforderungen, reale Beispiele, Namenskonventionen und Effizienzhinweise. Er führt durch die Update-Schleife, das Meter-Verhalten, die Logik zur Effektauslösung und hebt häufige Fallstricke hervor. Ob beim Debuggen, beim Aufbau von Grund auf oder bei der Pflege fremden Codes – dieser Leitfaden betont Klarheit, Stabilität und Leistung als Kernstandards hochwertiger Integrationen.

Dieser Abschnitt bietet einen schnellen Überblick über die Einrichtung eines LightScripts aus Wartungsperspektive, mit Fokus darauf, wo typischerweise Probleme auftreten und wie Bugs erkannt und behoben werden. Es wird zunächst kurz eine ideale LightScript-Struktur durchgegangen, dann die Fehlerbehebung behandelt und mit einer FAQ abgeschlossen.

Das grundlegende Skeleton erfordert einen <head>, <body> und <script>. Alle Meter- und Benutzersteuerelement-Deklarationen gehören in den <head>. Alle Canvas-Deklarationen gehören in den <body>. Alles andere sollte im <script>-Abschnitt platziert werden.

Der <head> ist einer der kritischsten und komplexesten Teile eines LightScripts. Ein fehlerhaftes Benutzersteuerelement oder ein fehlerhafter Meter hier kann Absturzschleifen verursachen oder sich selbst sowie alle danach deklarierten Meter deaktivieren.

Beim Erstellen von Metern muss sichergestellt werden:

  • Perfekte Syntax (um Abstürze und fehlerhafte Meter zu vermeiden)
  • Keine doppelten Meter-Namen (Duplikate werden überschrieben)
  • Keine Meter, die über Bildschirmgrenzen hinausgehen (verursacht Abstürze und Fehler)
  • Keine fehlenden oder überzähligen Optionen in Metern (führt zu Abstürzen)
  • Alle Meter enthalten Auflösungsanpassungen (gewährleistet konsistentes Verhalten)

Was Auflösungen betrifft, sind die häufigsten Seitenverhältnisse:

  • 16:9 (3840x2160, 2560x1440, 1920x1080, 1600x900, 1366x768, 1360x768, 1280x720)
  • 16:10 (2560x1600, 1920x1200, 1680x1050, 1440x900, 1280x800)
  • 21:9 (5120x2160, 3440x1440)

Standardmäßig wird die Auflösung 2560x1440 verwendet.

Alle LightScripts müssen die Seitenverhältnisse 16:9, 16:10 und 21:9 unterstützen. Obwohl 4:3 keinen signifikanten Anteil der Nutzerbasis ausmacht, sollte es für zukünftige Kompatibilität berücksichtigt werden.

Hier ist ein Beispiel für die Struktur eines Meters mit mehreren Auflösungseinstellungen:

Die Standardposition und -größe der Meter gelten für alle anderen Auflösungen innerhalb desselben Seitenverhältnisses. Wenn die Meter beispielsweise ursprünglich für 1600x900 angepasst wurden, sollten sie auf allen anderen 16:9-Auflösungen korrekt funktionieren. Es gibt jedoch Ausnahmen. Fortnite hat mehrere unterschiedliche Meter-Positionen sogar innerhalb desselben Seitenverhältnisses, und manche Seitenverhältnisse selbst können irreführend sein. Zum Beispiel wird 1366x768, eine weltweit häufige Auflösung, oft als 16:9 aufgeführt, ist aber kein echtes 16:9-Verhältnis – was nicht ungewöhnlich ist. Ähnlich verhält es sich mit Ultrawidescreen-Verhältnissen wie 21:9, die selten ihren nominellen Abmessungen entsprechen. In der Erfahrung als Integrationsentwickler ist noch keine exakte 21:9-Auflösung begegnet worden, obwohl sie so bezeichnet werden. Deshalb muss jede Ultrawidescreen-Auflösung individuell erstellt, getestet und konfiguriert werden.

Alle Anpassungen müssen zwischen den öffnenden <meta>- und schließenden </meta>-Tags platziert werden; andernfalls funktionieren sie nicht. Wenn der Standard-Meter auf 16:9 basiert und konsistent über diese Auflösungen hinweg funktioniert, müssen keine Anpassungen für andere 16:9-Auflösungen hinzugefügt werden. Es müssen jedoch Einträge für jede Auflösung in anderen Seitenverhältnissen (wie 16:10 und 21:9) hinzugefügt werden, auch wenn das Verhältnis konsistent ist.

Schließlich erfordert jeder Meter außer den OCR-Metern einen HSL-Bereich zum Auslösen. Diese Bereiche können durch folgende Faktoren erschwert werden:

  • Transparente UI-Elemente
  • Farbverläufe in Farbbereichen
  • Bildverzerrungseffekte
  • Öffnung von Ingame-Menüs
  • UI-Anpassungen pro Auflösung
  • Controller- vs. Tastaturnutzung
  • Videoaufnahmen, die kompressionsbezogene Pixelfehler einführen können

Grundlegende Anweisungen zu HSL und normierten Koordinaten werden in den Entwicklerdokumenten behandelt und hier nicht wiederholt. Das Testen dieser Meter wird im Abschnitt “Identifizierung von Problemen” besprochen, aber es ist wichtig, Folgendes zu betonen: Der Testaufwand zur perfekten Überprüfung aller Meter berechnet sich als (Anzahl der Meter) × (Anzahl der Auflösungsanpassungen) × (Anzahl der Spielmodi) × (Anzahl der spielbaren Charaktere) × (Länge eines durchschnittlichen Spiels). Dies kann sich leicht zu Stunden der Überprüfung pro Spiel summieren, insbesondere wenn Übungsmodi oder andere Workarounds nicht verfügbar sind.

HALTE METER EFFIZIENT – unser Standard ist Perfektion.

Das <body>-Tag ist der Ort, an dem das eigentliche Canvas-Element deklariert wird. Es sollte immer mehr oder weniger wie das folgende Beispiel aussehen. Die eigentliche Canvas-id kann geändert werden, aber sicherstellen, dass sie im Skript korrekt abgerufen wird.

Spar dir etwas Zeit und kopiere dieses Beispiel.

Vier Dinge müssen in diesem Tag bei jeder Integration geschehen:

  • Das Canvas wird abgerufen und zur Erstellung des 2D-Kontexts verwendet.
  • Die erste Update-Schleife setzt Meter-Werte und ruft sich dann unbegrenzt neu auf, um sie aufrechtzuerhalten.
  • Die Update-Schleife hält die Variablen der Benutzersteuerelemente aktuell.
  • Meter führen ihre Callback-Funktionen aus, wenn sie stabil sind.

Das grundlegende Code-Skeleton ist bereits eingerichtet. Der nächste Schritt besteht darin, die Ausführungsschleife durchzugehen, die Effekte von Anfang bis Ende auslöst.

  1. Das Videospiel-UI zeigt Informationen in Form von farbigen Balken, Schaltflächen, Textfeldern usw. an. SignalRGB erfasst diese Daten mehrmals pro Sekunde, aber die tatsächliche Erfassungsrate hängt stark von der Effizienz des Codes ab. Zu beachten: Eine einzelne Schleife oder eine nicht deklarierte Variable kann das gesamte Skript unterbrechen und sogar SignalRGB zum Absturz bringen. Schlimmer noch: Es ist leicht, Code zu schreiben, der technisch funktioniert, aber so ineffizient ist, dass er Informationen nur mit 1–2 FPS erfasst.
  2. Jeder im <head> deklarierte Meter muss so klein und effizient wie möglich sein, um den Overhead zu reduzieren. Berechnungen frühzeitig und häufig durchführen; ein Meter, der 25% des Bildschirms einnimmt, ist niemals effizient. Bei OCR-Metern einzelne Buchstaben statt ganzer Wörter erfassen. Bei Lebens- und Manaleisten nur die wesentlichen Segmente überwachen. METER SO KLEIN WIE MÖGLICH HALTEN.
  3. Meter erfassen Informationen, die mit jeder Schleife aktualisiert werden.
  4. Früher wurde die Meter-Klassendefinition behandelt, die Meter-Daten speichert und einen Callback auslöst, wenn das Informationsarray stabil wird. Am Anfang des Skripts alle Meter in einem Block deklarieren. Sie können organisiert oder alphabetisch geordnet werden; sie sollten nur nicht über Tausende von Zeilen verteilt werden. Irgendwann müssen Stabilitätswerte angepasst werden, und es ist Zeitverschwendung, sich zu erinnern, wo sie platziert wurden.
  5. Innerhalb der Update-Funktion empfangen diese Meter in jeder Schleife Werte aus der Bildschirmleselogik. Ihre interne Logik bewertet die Stabilität und löst, wenn stabil, die zugehörige Callback-Funktion aus.
  6. Diese Callback-Funktionen sollten im Skript, aber außerhalb der Update-Funktion deklariert werden. Darin wird der Zustand der Meter-Werte (value, decreased, increased, diff) geprüft und anhand dieser bestimmt, ob eine Effektanimation abgespielt werden soll. Diese Strukturierung des Codes, anstatt alles direkt in die Update-Schleife zu stecken, ermöglicht den Aufbau skalierbarer Integrationen.

Nachdem die allgemeine Idee bekannt ist, wird schnell ein reales Beispiel einer Schleife durchgegangen.

  • Das Spiel League of Legends wird gespielt, das verfügbare Skills mit einem hellen gelben Highlight umgibt.
  • In jeder Schleife nimmt der spezifische Skill-Meter diese Farbe als Wert “1” auf, weil er den HSL-Bereich des Meters vollständig erfüllt.
  • Diese “1” wird an die Meter-Instanz übergeben, die dem Bildschirmlesemeter zugeordnet ist, und in das Informationsarray dieses Meters eingefügt.
  • Wenn jeder Wert in diesem Array eine “1” ist, gilt er als stabil und aktiviert die zugehörige Effekt-Callback-Funktion. Diese Callback-Funktion würde auch aktiviert werden, wenn jeder Wert “0” oder “.1” wäre; dem Meter geht es nur um Stabilität. Ein wichtiger Hinweis ist, dass die Callback-Funktion nicht kontinuierlich aktiviert wird, wenn der Meter konstant stabil beim gleichen Wert ist – nur Stabilität mit einem NEUEN Wert aktiviert den Callback.
  • Sobald die Callback-Funktion ausgeführt wird, werden einige bedingte Prüfungen durchgeführt – in diesem Fall muss nur überprüft werden, ob der Meter.value “0” ist, was bedeutet, dass ein Skill verwendet wurde.
  • Da der Meter-Wert “1” ist, schlägt diese Prüfung fehl und der Skill-Effekt wird nicht abgespielt.
  • Einige Sekunden später wird der Skill aktiviert und der gelbe Highlight um die Schaltfläche verschwindet.
  • Der neue Meter-Wert ist 0, der an seine Meter-Klasse übergeben wird.
  • Sobald Stabilität erreicht ist, aktiviert der Callback die Bedingung und der Skill-Effekt wird abgespielt. Die Latenz hängt vollständig von der Länge des Meter-Arrays ab, das bei der Deklaration festgelegt wird. Mehr Länge bedeutet mehr Latenz und weniger Fehlauslösungen; daher sollte getestet werden, bis ein gutes Gleichgewicht gefunden ist.

Bildschirmlesemeter sollten einfache, klare und beschreibende Namen haben, immer mit einem Kleinbuchstaben beginnend. Einen Lebensbalken-Meter “healthBar” zu nennen ist ausgezeichnet. Zwei Meter “healthBarRed” und “healthBarGreen” zu nennen, wenn sie verschiedene Farben im selben Bereich verfolgen, ist ebenfalls gut. Aber einen kleinen Meter, der nur während des Ultimativen eines Helden erscheint, “hrO21_yes” zu nennen, bereitet jedem, der den Code reparieren muss, nur Schmerz und Leid. Herauszufinden, was ein schlecht benannter, winziger Meter verfolgt, kann buchstäblich eine Stunde des Starrens auf einzelne Pixel in Anspruch nehmen – also diesen Fehler vermeiden.

Meter-Klassen-Instanzen sollten großgeschrieben sein und mit dem Wort Meter enden. Beispiele wie “Q_Meter”, “TookDamageMeter” und “TowerDestroyedMeter” sind alle einwandfrei. Diese sollten klar von den im <head>-Abschnitt deklarierten Metern unterscheidbar sein.

Effektfunktionen sollten ebenfalls so einfach und beschreibend wie möglich benannt werden. Manche Spiele haben Hunderte dieser Funktionen; andere haben weniger als zehn. Wenn mehrere Helden einzigartige Skills haben, den Namen des Helden als Präfix einfügen, wie “SonaQ”, “ChamberE” oder “AshUlt”. In League of Legends beispielsweise gibt es Funktionen wie “DragonEffect”, “TowerEffect” und “Q_Effects”, die mehrere Bedingungen enthalten und von mehreren Metern verwendet werden. Diese Art der Benennung hilft daher auch bei der Optimierung für Skalierbarkeit.

Wörter nicht falsch schreiben. Bei Unsicherheit über die Schreibweise nachschlagen. Namen müssen klar und lesbar sein, unabhängig davon, wer am Code arbeitet oder wie viel Zeit vergangen ist. Namen alphabetisch zu ordnen hilft bei der schnellen Suche, besonders wenn dieser Abschnitt häufig bearbeitet wird. Obwohl dieses Maß an Organisation für die Ausführung des Codes nicht erforderlich ist, macht es einen großen Unterschied für Wartungsentwickler.