Wenn Sie Spiele entwickeln, stoßen Sie oft auf Situationen, in denen Sie einen bestimmten Codeblock mehrmals ausführen möchten, aber nicht sofort. Dies ist besonders häufig bei Animationen, Spezialeffekten oder beim Erstellen komplexer Spielabläufe. In diesen Fällen benötigen Sie eine Schleife mit Wartezeit – eine Schleife, die zwischen den Iterationen eine Pause einlegt. GDevelop bietet mehrere Möglichkeiten, dies zu erreichen, aber die falsche Methode kann zu Leistungsproblemen und einem trägen Spiel führen. Dieser Artikel führt Sie durch verschiedene Techniken, um Schleifen mit Wartezeit in GDevelop zu erstellen, ohne Ihr Spiel zu verlangsamen.
Das Problem mit einfachen Schleifen und dem Haupt-Thread
Bevor wir uns mit den Lösungen befassen, ist es wichtig zu verstehen, warum einfache Schleifen Ihr Spiel lahmlegen können. Wenn Sie eine Standard-Programmierschleife (wie eine `for`- oder `while`-Schleife) in der Ereignisliste von GDevelop verwenden, führt das Spiel diese Schleife im Haupt-Thread aus. Der Haupt-Thread ist für alle Aufgaben verantwortlich, die zur Ausführung Ihres Spiels erforderlich sind, einschließlich der Verarbeitung von Eingaben, dem Aktualisieren der Spielwelt und dem Rendern von Grafiken. Wenn eine Schleife zu lange läuft, blockiert sie den Haupt-Thread, was dazu führt, dass das Spiel nicht mehr reagiert oder ruckelt.
Stellen Sie sich vor, Sie haben eine Schleife, die 100 Mal ausgeführt werden muss, und jede Iteration dauert nur eine Millisekunde. Das mag nicht viel erscheinen, aber insgesamt blockiert die Schleife den Haupt-Thread für 100 Millisekunden. In einem Spiel, das idealerweise 60 Frames pro Sekunde (FPS) rendern soll, entspricht dies dem Auslassen von etwa sechs Frames. Dies kann zu spürbaren Rucklern und einem schlechten Spielerlebnis führen.
Technik 1: Verwenden von Timern
Die empfohlene Methode zum Erstellen von Schleifen mit Wartezeit in GDevelop ist die Verwendung von Timern. Timer sind Objekte, die im Hintergrund laufen und nach einer bestimmten Zeit ein Ereignis auslösen können. Wir können diese Funktion nutzen, um eine Schleife zu simulieren, ohne den Haupt-Thread zu blockieren.
So funktioniert das Prinzip:
- Erstellen Sie einen Timer: Erstellen Sie zunächst einen Timer, der in Ihrem Spiel spezifisch ist. Sie können einen globalen Timer, einen Szenen-Timer oder einen Objekt-Timer verwenden, je nachdem, wie oft die Schleife ausgeführt werden soll und welchen Umfang sie hat.
- Starten Sie den Timer: Verwenden Sie die Aktion „Timer starten oder zurücksetzen”, um den Timer mit der gewünschten Wartezeit zu starten.
- Überprüfen Sie den Timer: Verwenden Sie die Bedingung „Zeitüberschreitung des Timers”, um zu überprüfen, ob der Timer abgelaufen ist. Wenn der Timer abgelaufen ist, führen Sie den Codeblock aus, den Sie wiederholt ausführen möchten.
- Zurücksetzen des Timers: Nach der Ausführung des Codeblocks setzen Sie den Timer mit der Aktion „Timer starten oder zurücksetzen” zurück. Dies startet den Timer von neuem und löst den Codeblock erneut aus, wenn er abgelaufen ist.
- Schleifensteuerung: Sie benötigen eine Möglichkeit, die Schleife zu stoppen, sobald sie die gewünschte Anzahl an Iterationen erreicht hat. Hierfür können Sie eine Variable (z. B. „Schleifenzähler”) verwenden. Erhöhen Sie den Zähler in jedem Durchlauf der Schleife und stoppen Sie den Timer, wenn der Zähler einen bestimmten Wert erreicht.
Beispiel:
Angenommen, Sie möchten ein Objekt (z. B. eine Explosion) 5 Mal alle 0,5 Sekunden blinken lassen.
Sie würden folgende Ereignisse erstellen:
Bedingung: Zu Beginn der Szene
Aktion: Variable "BlinkZaehler" = 0
Aktion: Timer "BlinkTimer" starten oder zurücksetzen (0.5 Sekunden)
Bedingung: Zeitüberschreitung von Timer "BlinkTimer"
Variable "BlinkZaehler" < 5
Aktion: Sichtbarkeit des Objekts Explosion umschalten (wenn sichtbar, unsichtbar machen; wenn unsichtbar, sichtbar machen)
Aktion: Variable "BlinkZaehler" = Variable "BlinkZaehler" + 1
Aktion: Timer "BlinkTimer" starten oder zurücksetzen (0.5 Sekunden)
Bedingung: Variable "BlinkZaehler" >= 5
Aktion: Timer "BlinkTimer" stoppen
In diesem Beispiel verwenden wir einen Timer namens „BlinkTimer” und eine Variable namens „BlinkZaehler”, um zu steuern, wie oft das Objekt blinkt. Der Timer löst das Ereignis alle 0,5 Sekunden aus, und die Variable „BlinkZaehler” verfolgt, wie oft das Objekt bereits geblinkt hat. Sobald der Zähler 5 erreicht hat, wird der Timer gestoppt, wodurch die Schleife beendet wird.
Technik 2: Verwenden von verzögerten Aktionen
GDevelop bietet eine weitere Möglichkeit, verzögerte Aktionen auszuführen, ohne den Haupt-Thread zu blockieren: die Verwendung der Funktion „Aktion verzögern”. Diese Funktion ermöglicht es Ihnen, eine oder mehrere Aktionen nach einer bestimmten Verzögerung auszuführen. Obwohl sie nicht direkt für komplexere Schleifen gedacht ist, kann sie für einfache, einmalige verzögerte Ereignisse nützlich sein.
So können Sie die „Aktion verzögern”-Funktion verwenden:
- Wählen Sie die Aktion aus: Bestimmen Sie die Aktion(en), die Sie verzögern möchten.
- Verwenden Sie die „Aktion verzögern”-Aktion: In GDevelop finden Sie die Option „Aktion verzögern” unter den Aktionen. Geben Sie die Verzögerung in Sekunden an.
Beispiel:
Sie möchten, dass ein Textobjekt 2 Sekunden nach dem Start der Szene verschwindet.
Bedingung: Zu Beginn der Szene
Aktion: Verzögere: 2 Sekunden: Lösche das Objekt "TextObjekt"
Diese Methode ist nützlich für einmalige Ereignisse, aber für komplexere Schleifen mit mehreren Iterationen ist die Verwendung von Timern die effizientere und flexiblere Lösung.
Technik 3: Verwenden von Zustandsautomaten (für komplexe Abläufe)
Für komplexere Spielabläufe, die mehrere verzögerte Aktionen und Bedingungen umfassen, kann ein Zustandsautomat eine gute Lösung sein. Ein Zustandsautomat ist ein Verhaltensmuster, das ein Objekt oder eine Szene in verschiedenen Zuständen speichern und zwischen diesen wechseln kann, basierend auf bestimmten Ereignissen und Bedingungen.
So können Sie einen Zustandsautomaten für Schleifen mit Wartezeit verwenden:
- Definieren Sie die Zustände: Identifizieren Sie die verschiedenen Zustände, die Ihre „Schleife” durchlaufen muss. Jeder Zustand kann eine andere Aktion oder eine Reihe von Aktionen darstellen.
- Erstellen Sie Variablen zur Steuerung des Zustands: Verwenden Sie Variablen, um den aktuellen Zustand des Zustandsautomaten zu verfolgen.
- Verwenden Sie Timer, um Übergänge auszulösen: Verwenden Sie Timer, um Übergänge zwischen den Zuständen auszulösen. Wenn ein Timer abgelaufen ist, ändern Sie den Zustand des Zustandsautomaten und führen Sie die entsprechenden Aktionen für den neuen Zustand aus.
- Fügen Sie Bedingungen hinzu: Verwenden Sie Bedingungen, um sicherzustellen, dass die richtigen Aktionen im richtigen Zustand ausgeführt werden.
Beispiel:
Stellen Sie sich vor, Sie erstellen ein Spiel, in dem ein Gegner in regelmäßigen Abständen angreift. Der Gegner kann sich in einem der folgenden Zustände befinden: „Warten”, „Angreifen”, „Abkühlen”.
// Zu Beginn der Szene
Aktion: Variable "GegnerZustand" = "Warten"
Aktion: Timer "AngriffsTimer" starten oder zurücksetzen (3 Sekunden)
// Zustand: Warten
Bedingung: Variable "GegnerZustand" = "Warten"
Zeitüberschreitung des Timers "AngriffsTimer"
Aktion: Variable "GegnerZustand" = "Angreifen"
Aktion: Animation "Angreifen" abspielen
Aktion: Timer "AbkuehlTimer" starten oder zurücksetzen (1 Sekunde)
// Zustand: Angreifen
Bedingung: Variable "GegnerZustand" = "Angreifen"
Zeitüberschreitung des Timers "AbkuehlTimer"
Aktion: Variable "GegnerZustand" = "Abkühlen"
Aktion: Timer "WarteTimer" starten oder zurücksetzen (2 Sekunden)
// Zustand: Abkühlen
Bedingung: Variable "GegnerZustand" = "Abkühlen"
Zeitüberschreitung des Timers "WarteTimer"
Aktion: Variable "GegnerZustand" = "Warten"
Aktion: Timer "AngriffsTimer" starten oder zurücksetzen (3 Sekunden)
Dieser Zustandsautomat verwendet Timer, um zwischen den verschiedenen Zuständen des Gegners zu wechseln. Dies ermöglicht es dem Gegner, in regelmäßigen Abständen anzugreifen, ohne den Haupt-Thread zu blockieren.
Best Practices für das Erstellen von Schleifen mit Wartezeit
Hier sind einige Best Practices, die Sie beim Erstellen von Schleifen mit Wartezeit in GDevelop beachten sollten:
- Vermeiden Sie lange Wartezeiten: Vermeiden Sie Wartezeiten, die zu lange dauern, da dies immer noch zu Rucklern führen kann, auch wenn Sie Timer verwenden. Teilen Sie lange Wartezeiten in kleinere auf und verwenden Sie mehrere Timer, falls erforderlich.
- Optimieren Sie Ihren Code: Stellen Sie sicher, dass der Code, den Sie in der Schleife ausführen, so effizient wie möglich ist. Vermeiden Sie unnötige Berechnungen oder Operationen, die die Leistung beeinträchtigen können.
- Verwenden Sie Objektpools: Wenn Sie Objekte in der Schleife erstellen und zerstören, sollten Sie die Verwendung von Objektpools in Betracht ziehen. Objektpools können die Leistung verbessern, indem sie die Häufigkeit der Objekterstellung und -zerstörung reduzieren.
- Profilieren Sie Ihren Code: Verwenden Sie den Profiler von GDevelop, um Leistungsprobleme in Ihrem Code zu identifizieren. Der Profiler kann Ihnen helfen, die Bereiche zu identifizieren, in denen Sie Ihren Code optimieren müssen.
- Wählen Sie die richtige Technik: Die beste Technik zum Erstellen von Schleifen mit Wartezeit hängt von den spezifischen Anforderungen Ihres Spiels ab. Für einfache Schleifen können Timer ausreichend sein. Für komplexere Abläufe kann ein Zustandsautomat die bessere Wahl sein.
Schlussfolgerung
Das Timing ist in der Spieleentwicklung entscheidend. Das Erstellen von Schleifen mit Wartezeit ist eine gängige Anforderung, aber es ist wichtig, dies auf eine Weise zu tun, die die Leistung Ihres Spiels nicht beeinträchtigt. Durch die Verwendung von Timern, verzögerten Aktionen und Zustandsautomaten können Sie Schleifen mit Wartezeit erstellen, die reibungslos laufen und Ihr Spiel responsiv halten. Denken Sie daran, Ihren Code zu optimieren und ihn zu profilieren, um Leistungsprobleme zu identifizieren und zu beheben. Mit den richtigen Techniken können Sie beeindruckende Spezialeffekte und komplexe Spielabläufe erstellen, ohne Ihre Spieler zu frustrieren.