Baue ein Metroidvania in Godot! | Thomas Yanuziello | Skillshare

Playback-Geschwindigkeit


1.0x


  • 0.5x
  • 0.75x
  • 1x (normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

Baue ein Metroidvania in Godot!

teacher avatar Thomas Yanuziello, Indie Game Developer

Schau dir diesen Kurs und Tausende anderer Kurse an

Erhalte unbegrenzten Zugang zu allen Kursen
Lerne von Branchenführern, Ikonen und erfahrenen Experten
Wähle aus einer Vielzahl von Themen, wie Illustration, Design, Fotografie, Animation und mehr

Schau dir diesen Kurs und Tausende anderer Kurse an

Erhalte unbegrenzten Zugang zu allen Kursen
Lerne von Branchenführern, Ikonen und erfahrenen Experten
Wähle aus einer Vielzahl von Themen, wie Illustration, Design, Fotografie, Animation und mehr

Einheiten dieses Kurses

    • 1.

      0-0 Trailer

      2:01

    • 2.

      0-1 Herunterladen

      2:34

    • 3.

      0-2 Redakteur

      4:42

    • 4.

      0-3 Szenen

      6:48

    • 5.

      0-4 Physik

      4:51

    • 6.

      0-5 Skripte

      5:43

    • 7.

      0-6 Spiel

      5:44

    • 8.

      1-1 CharakterKörper

      5:15

    • 9.

      1-2 Eingabekarte

      8:47

    • 10.

      1-3 Bewegung

      7:15

    • 11.

      1-4 Springen

      7:23

    • 12.

      1-5 Sturz

      7:25

    • 13.

      1-6 Laufen

      4:40

    • 14.

      1-7 Kojote

      8:41

    • 15.

      2-1 Sprite

      7:36

    • 16.

      2-2 Animations-Player

      9:56

    • 17.

      2-3 Animationsbaum

      10:02

    • 18.

      2-4 Soundeffekte

      8:58

    • 19.

      2-5 Animierter Sprite

      7:54

    • 20.

      2-6 Instanziierung

      11:27

    • 21.

      Audiobus 2-7

      6:13

    • 22.

      3-1 Kachelkarte

      8:05

    • 23.

      3-2 Gelände

      8:15

    • 24.

      3-3 Kamera

      6:46

    • 25.

      3-4 Blick nach vorne

      9:24

    • 26.

      3-5 Nach oben schauen

      10:41

    • 27.

      3-6 Grenzen

      11:05

    • 28.

      3-7 Parallaxe

      10:06

    • 29.

      4.1 Inhalt

      6:58

    • 30.

      4-2 Zimmer

      8:29

    • 31.

      4-3 Parallaxe

      10:06

    • 32.

      4-4 Übergang

      7:38

    • 33.

      4-5 Ansichtsfenster

      7:05

    • 34.

      4-6 Sichtbarkeit

      7:49

    • 35.

      4-7 Karte

      7:46

    • 36.

      5-1 HUD

      9:38

    • 37.

      5-2 Messgerät

      10:27

    • 38.

      5-3 Symbol

      8:00

    • 39.

      5-4 Zähler

      8:40

    • 40.

      5-5 Verletzungsbox

      10:57

    • 41.

      5-6 Daten

      6:10

    • 42.

      5-7-Datei

      8:27

    • 43.

      6-1 Doppelsprung

      10:37

    • 44.

      6-2 Wandfolie

      10:16

    • 45.

      6-3 Wandsprung

      10:28

    • 46.

      6-4 Strich

      10:45

    • 47.

      6-5 Abklingzeit

      11:34

    • 48.

      6-6 Hüte

      13:32

    • 49.

      6-7 Geschoss

      18:21

    • 50.

      7-1 Tempo

      12:03

    • 51.

      7-2 Unsichtbare Wände

      6:41

    • 52.

      7-3 Kantenerkennung

      9:24

    • 53.

      7-4 Fliegen

      11:48

    • 54.

      7-5 Kriecheln

      14:44

    • 55.

      7-6 Sehkraft

      12:48

    • 56.

      7-7 Aggression

      14:25

    • 57.

      8-1 Kombi-Gruppe

      12:21

    • 58.

      8:2 Treffer

      11:35

    • 59.

      8-3 Saft

      12:51

    • 60.

      8-4 Schütteln

      7:39

    • 61.

      8-5 Todesfälle

      13:28

    • 62.

      8-6 Chef 1

      15:37

    • 63.

      8-7 Chef 2

      10:13

    • 64.

      8-8 Chef 3

      13:48

    • 65.

      9-1 Punkt speichern

      11:55

    • 66.

      9-2 Metroidvania

      10:45

    • 67.

      9-3 Abkürzung

      13:19

    • 68.

      9-4 Karte

      11:19

    • 69.

      9-5 Musik

      8:14

    • 70.

      9-6 Endlicher Boss

      9:54

    • 71.

      9:7 Finale

      5:42

  • --
  • Anfänger-Niveau
  • Fortgeschrittenes Niveau
  • Fortgeschrittenes Niveau
  • Jedes Niveau

Von der Community generiert

Das Niveau wird anhand der mehrheitlichen Meinung der Teilnehmer:innen bestimmt, die diesen Kurs bewertet haben. Bis das Feedback von mindestens 5 Teilnehmer:innen eingegangen ist, wird die Empfehlung der Kursleiter:innen angezeigt.

6

Teilnehmer:innen

--

Projekte

Über diesen Kurs

Erfahren Sie, wie Sie ein Metroidvania-Spiel in Godot von Grund auf erstellen.  Geben Sie Ihren Spielern freischaltbare Fähigkeiten, mit denen sie schrittweise auf die Spielwelt zugreifen und diese erkunden können, eine Karte, die ihren Standort anzeigt, und speichern Sie Punkte, um ihren Fortschritt zu verfolgen.

In diesem Kurs lernen Sie, wie:
Verwenden der Godot-Spiel-Engine zum Erstellen von Spielen
Schreiben von Skripten in GDScript
Objektorientierter Programmierung
Entwurfsprinzipien komplexer Projekte in einzelne Komponenten aufteilen.

Das Erstellen eines kompletten Metroidvania-Spiels selbst kann eine gewaltige Aufgabe sein, aber dieser Kurs zeigt Ihnen, wie Sie es in kleinere Teile zerlegen, die viel einfacher zu verwalten sind. Gleichzeitig lernen Sie die Designstruktur, die alle Teile zusammenfügt.

Dieser Kurs richtet sich an Teilnehmer:innen aller Kenntnisstufen.
Wenn Sie Anfänger sind, wird empfohlen, dass Sie den Kurs genau wie gezeigt befolgen.  Jede Codezeile wird auf dem Bildschirm eingegeben und jeder Schritt des Prozesses wird demonstriert.
Für Schüler auf mittlerer Stufe können Sie andere Ressourcen verwenden oder einige der Spielmechaniken anpassen, um dem bereitgestellten Inhalt eine eigene Note zu verleihen.
Fortgeschrittene Teilnehmer:innen sollten in der Lage sein, ihre eigenen Ressourcen zum Design und Erstellen ihres eigenen Metroidvania-Spiels zu verwenden. Dabei wird dieses Projekt als Vorlage für die Gesamtstruktur und Inspiration dient.

Alle in den Videos verwendeten Ressourcen werden bereitgestellt, damit Sie mitverfolgen können. Sie können jedoch auch andere Ressourcen verwenden oder eigene erstellen, wenn Sie möchten.

Triff deine:n Kursleiter:in

Teacher Profile Image

Thomas Yanuziello

Indie Game Developer

Kursleiter:in

Skills dieses Kurses

Entwicklung Sonstiges zur Entwicklung
Level: All Levels

Kursbewertung

Erwartungen erfüllt?
    Voll und ganz!
  • 0%
  • Ja
  • 0%
  • Teils teils
  • 0%
  • Eher nicht
  • 0%

Warum lohnt sich eine Mitgliedschaft bei Skillshare?

Nimm an prämierten Skillshare Original-Kursen teil

Jeder Kurs setzt sich aus kurzen Einheiten und praktischen Übungsprojekten zusammen

Mit deiner Mitgliedschaft unterstützt du die Kursleiter:innen auf Skillshare

Lerne von überall aus

Ob auf dem Weg zur Arbeit, zur Uni oder im Flieger - streame oder lade Kurse herunter mit der Skillshare-App und lerne, wo auch immer du möchtest.

Transkripte

1. 0-0 Trailer: Willkommen zu meinem Kurs zum Erstellen Ametrovinien in der Gadot-Game-Engine Mein Name ist Thomas Ionizlo und ich werde dein Lehrer sein. Ich habe einen Bachelor-Abschluss in Informatik und unterrichte seit über fünf Jahren Spieleentwicklung auf mehreren Plattformen Ich habe einen kompletten Satz von Inhalten beigefügt, darunter Sprites, Soundeffekte und Musik, mit denen Sie mitverfolgen können , oder Sie können Ihre eigenen Ressourcen verwenden, wenn Sie möchten Dieser Kurs wird dir helfen, dich mit der GDOGame-Engine vertraut zu machen Es ist ein sehr effizienter Arbeitsablauf für die Erstellung von Spielen und die native Skriptsprache Du lernst, wie du Szenen mithilfe der verschiedenen Knoten von Gado erstellen und bearbeiten und ihr Verhalten mithilfe von Skripten ändern Beim Schreiben dieser Skripte lernst du, wie du objektorientierte Programmierprinzipien anwendest objektorientierte Programmierprinzipien um deinen Code präzise, skalierbar und für andere Projekte wiederverwendbar zu halten , skalierbar und für andere Projekte wiederverwendbar Am wichtigsten ist, dass Sie lernen, ein komplexes Projekt dieser Größenordnung zu strukturieren , indem Sie es in seine einzelnen Komponenten zerlegen in seine einzelnen Komponenten zerlegen Wir beginnen damit, einen 2D-Plattformcharakter zu erstellen und zu animieren Erstellen Sie dann eine Umgebung , in der der Charakter die Kamera des Spiels erkunden und bewegen Als Nächstes ermöglichen wir dem Charakter, zwischen verschiedenen Räumen zu wechseln und die Welt auf eine Karte zu zeichnen , damit der Spieler deine Welt erkunden kann. Nachdem wir den Fortschritt des Spielers gespeichert und geladen haben, zeichnen wir ein Head-up-Display. Füge dann unsere freischaltbaren Fähigkeiten hinzu, darunter einen Doppelsprung, einen Wandsprung, einen Sprung und das Abfeuern eines Projektils Schließlich werden wir einige Gegner für den Kampf und einen Bosskampf hinzufügen und den Fortschritt des Spielers im Spiel verfolgen . ob du neu in der Spieleentwicklung bist, die Gadot-Game-Engine noch nicht kennst oder Metroid Venias noch nicht kennst, diesem Kurs lernst du alles, was du wissen musst, um ein komplettes Spiel von Grund auf zu entwickeln Wenn du Hilfe benötigst, ist unser Discord-Server voller anderer Studenten und angehender Spieleentwickler , die alle deine Fragen beantworten können Klicke auf den Link in meinem Profil, um Mitglied zu werden. Sie können sich die ersten beiden Abschnitte des Kurses kostenlos ansehen, und ich habe einen weiteren Kurs , der die Grundlagen der GD-Script-Programmierung ebenfalls völlig kostenlos behandelt . Sobald Sie bereit sind, können wir anfangen lernen, wie man eine Metrovnia in Cado baut 2. 0-1 Herunterladen: Hallo Freunde. Um an diesem Kurs teilnehmen zu können, benötigen Sie die Godot-Engine Öffnen Sie einen beliebigen Webbrowser , gehen Sie zu godot.org und laden Sie die neueste Version herunter, die zum Zeitpunkt der Aufnahme dieses Videos Die Nutzung der Engine ist kostenlos, Sie können jedoch optional spenden, um die Entwicklung zu unterstützen, wenn Sie möchten Nachdem der Download abgeschlossen ist, müssen Sie die Dateien aus dem komprimierten Ordner extrahieren sie dann an einem sicheren Ort auf Ihrem Computer speichern Um den Editor auszuführen, müssen Sie lediglich die größere Datei ausführen, die nicht in der Konsole endet Sie müssen sich keine Gedanken über Installer oder Launcher machen. Sie Godot zum ersten Mal öffnen, Ihre Projektliste leer und Sie werden gefragt, ob Sie einige der verfügbaren Beispielprojekte erkunden möchten einige der verfügbaren Beispielprojekte Wir werden das ignorieren und unser erstes Projekt erstellen, das ein neues Fenster öffnet Hier können wir entscheiden, wo das Projekt gespeichert werden soll. Der Standardspeicherort befindet sich im Dokumentenordner, aber es ist eine gute Idee, einen separaten Unterordner für Ihre Godot-Projekte zu erstellen einen separaten Unterordner für Ihre Godot-Projekte zu Als Nächstes können wir unserem Projekt einen Namen geben. Mach dir darüber jetzt nicht zu viele Gedanken. Sie können es später jederzeit ändern. Außerdem wird ein neuer Unterordner mit demselben Namen erstellt , der alle Dateien enthält , die sich auf dieses Projekt beziehen können drei verschiedene Renderer ausgewählt werden, jeweils für unterschiedliche Zwecke optimiert Ich empfehle, alle Ihre Projekte zunächst mit dem Kompatibilitätsrenderer zu starten, da dieser am besten für Web-Builds geeignet ist . Wechseln Sie Ihren Renderer erst später wenn Sie eine bessere Unterstützung für qualitativ bessere visuelle Effekte benötigen für qualitativ bessere visuelle Effekte Die Versionskontrolle mit Gi Hub wird automatisch unterstützt und ich empfehle dringend, zu lernen, wie man sie benutzt dieses Projekt erstellen, wird es automatisch geöffnet, damit wir es bearbeiten können. Ich werde den Editor jedoch schließen und erneut öffnen. Unser Projekt ist jetzt in der Projektliste enthalten, und wir können es öffnen, indem wir entweder darauf doppelklicken oder es aus der Liste auswählen und auf die Schaltfläche Bearbeiten klicken Wir haben jetzt Zugriff auf den Godot und können mit der Bearbeitung unseres ersten Projekts beginnen Im nächsten Video werden wir das Layout des Editorfensters untersuchen Wir sehen uns im nächsten Video. 3. 0-2 Redakteur: Hallo Freunde. Bevor wir mit der Bearbeitung unseres Projekts beginnen, müssen wir uns mit dem Layout des Godot Editor-Fensters vertraut machen mit dem Layout des Godot Editor-Fensters Der Großteil des Fensters ist mit einer Drei-D-Ansicht der aktuellen Szene gefüllt einer Drei-D-Ansicht der aktuellen Szene Dieses Projekt wird in zwei D nicht in drei D angezeigt. Mit den Schaltflächen oben im Fenster können wir die Ansicht zwischen drei D und zwei D umschalten zwischen drei D und zwei D . In zwei D haben wir die X-Achse rot, die Y-Achse grün und ein blaues Rechteck, das den Viewport zeigt, oder was tatsächlich auf dem Bildschirm gezeichnet wird , wenn das Spiel ausgeführt Beachten Sie, dass sich das Darstellungsfenster unterhalb der X-Achse befindet wobei Y gleich Null ist, was dem oberen Bildschirmrand entspricht Die Y-Achse ist invertiert, sodass positive Y-Werte Y-Achse nach unten und nicht nach oben verschoben werden Links oben befindet sich eine Registerkarte für die Struktur der aktuellen Szene, die derzeit leer ist und uns auffordert, einen Wurzelknoten für diese Szene zu erstellen Da unser Spiel aus zwei D bestehen wird, lassen Sie uns eine Szene mit zwei D erstellen. Der Szenen-Tab zeigt jetzt unseren Szenen-Stammknoten, einen Knoten zwei D. Wir werden im nächsten Video mehr über Szenen und Knoten erfahren. Dieses Dock enthält auch den Tab Import, dem wir die Importeinstellungen für importierte Dateien wie Grafiken und Audio ändern können , die wir in unserem Projekt verwenden werden . Diese Dateien werden im Projektdateisystem gespeichert und organisiert, das wir unten links sehen können. Derzeit enthält unser Projekt nur eine Datei, nämlich das Gadot-Symbol Auf der Registerkarte Dateisystem können wir unsere Projektdateien organisieren, indem wir Ordner erstellen und sie mithilfe des Filters durchsuchen zur Registerkarte Szene zurückkehren Wenn wir zur Registerkarte Szene zurückkehren und eine Notiz ausgewählt haben, werden ihre Eigenschaften Registerkarte Inspektor auf der rechten Seite angezeigt. Wir können die Kategorien dieser Eigenschaften erweitern und ihre Werte hier bearbeiten. Dieses Dock enthält auch die Registerkarte „Knoten“, die eine Liste der Signale enthält, die dieser Knoten aussenden kann, sowie die Gruppen, zu denen er gehört. Die Registerkarte Verlauf enthält eine Liste aller Änderungen, die wir in der aktuellen Szene oder für das gesamte Projekt vorgenommen haben . Sie können alle Änderungen sehen, die wir vorgenommen haben. Außerdem habe ich den Editor Fontie bearbeitet Das untere Dock ist derzeit ausgeblendet, aber wir können auf die Ausgabeschaltfläche klicken, um es zu erweitern Die Ausgabe zeigt uns auch die Änderungen, die wir am Projekt vorgenommen haben, und zeigt auch die Textausgabe aus unserem Spiel an, was für das Debuggen sehr nützlich ist Wir können hier manuell Nachrichten ausgeben, aber der Editor gibt auch hier Warnungen und Fehler Der Debugger verfügt über eine Vielzahl nützlicher Tools, denen wir herausfinden können, was unser Spiel verlangsamt oder zum Absturz bringt Es gibt auch Tabs speziell für Audio, Animation und Shader. Weitere Tabs werden hier bei Bedarf hinzugefügt. Wir können dieses Dock zusammenklappen indem wir auf die aktuell ausgewählte Registerkarte Wenn Sie auf die drei Punkte klicken, können diese Docks Ihren Bedürfnissen entsprechend neu angeordnet werden, je nachdem, wie Sie denken , dass dies für Ihren Arbeitsablauf am besten für Ihren Die einzelnen Tabs können auch zwischen den Dokumenten gezogen werden. Wenn Sie ein Layout gefunden haben , das für Sie gut geeignet ist, können Sie es im Editor-Menü speichern Sie können auch eine Vielzahl von Editor-Einstellungen ändern , um den Editor an Ihre Bedürfnisse anzupassen Wenn wir irgendwann ein Spiel zum Laufen haben, können wir das über die Schaltflächen in der oberen rechten Ecke tun Entweder das Spiel von Anfang an spielen oder nur die aktuelle Szene ausführen, das Spiel pausieren oder beenden Im nächsten Video lernen wir, wie man eine Szene erstellt. Wir sehen uns im nächsten Video. 4. 0-3 Szenen: Hallo Freunde. Nun, da wir mit dem Layout des Editors vertraut sind, fangen wir an, unsere erste Szene zu bearbeiten. Wir beginnen mit einem Klick auf zwei D-Szenen und machen den Wurzelknoten unserer Szene zu einem Knoten zwei D. Ein Knoten zwei D steht eigentlich für nichts in unserem Spiel. Es ist nur eine zweidimensionale Transformation. Eine Transformation ist eine Kombination aus Position, Drehung und Maßstab. Godot enthält auch eine Schrägkomponente in zwei D-Transformationen. Wenn wir tatsächlich etwas zeichnen wollen, müssen wir unserer Szene einen weiteren Knoten hinzufügen Entweder klicken wir mit der rechten Maustaste auf den Wurzelknoten und wählen Kind hinzufügen oder klicken Sie auf die Plus-Schaltfläche, Kind hinzufügen oder klicken Sie auf die Plus-Schaltfläche, um unserer Szene einen untergeordneten Knoten hinzuzufügen. Es gibt viele verschiedene Arten von Knoten, die alle unterschiedlichen Zwecken dienen. Die gebräuchlichste Art, etwas in zwei D-Spielen zu zeichnen , ist die Verwendung eines Sprites Also fügen wir unserer Szene einen Sprite-Zwei-D-Knoten hinzu. Knotentypen erben von anderen Knotentypen. Ein Sprite-2-D-Node ist also auch ein Node-2-D-Node und ein Canvas-Element und ein Basisknoten. Er hat dieselben Eigenschaften, die von diesen Typen geerbt wurden , und dieselben Eigenschaften, die von diesen Typen geerbt wurden , einige weitere eigene Der Sprite-Two-D-Knoten wird als untergeordnetes Element des Wurzelknotens hinzugefügt, was durch den Einzug gekennzeichnet Die Szenen sind in einer Hierarchie organisiert beginnen mit einem einzelnen Wurzelknoten verzweigen sich dann in eine beliebige Anzahl Diese untergeordneten Knoten können auch ihre eigenen untergeordneten Knoten haben , die den Szenenbaum bilden Wir können Zweige des Baums oder den gesamten Baum zusammenklappen , indem wir auf den Pfeil neben ihnen klicken, und sie erneut erweitern. Der Sprite-Knoten zeichnet immer noch nichts, weil ihm nicht gesagt wurde, was er zeichnen soll ihn auswählen, können wir seine Eigenschaften im Inspektor sehen, wo er tatsächlich Eigenschaften hat, die von Node, Canvas-Element und Knoten D übernommen wurden . Unter dem Abschnitt Sprite Two D hat er auch eine Textureigenschaft, die derzeit leer ist Wir können eine Texturdatei laden oder das GAD-Symbol aus dem Dateisystem-Tab in das Texturfeld ziehen GAD-Symbol aus dem Dateisystem-Tab in , um es zu füllen Und jetzt zeichnet der Sprite Two D-Knoten Textur des GADO-Symbols als Sprite Lassen Sie uns diesen Sprite-2-D-Node im Szenenbaum duplizieren , indem wir mit der rechten Maustaste klicken und Duplizieren auswählen oder den Knoten auswählen und Strg oder Command D drücken . Das Duplikat hat dieselben Eigenschaften wie der ursprüngliche Knoten und wird umbenannt, indem eine steigende Zahl an seinen Namen angehängt Geschwister im Szenenbaum dürfen nicht denselben Namen haben Wir können eines unserer Sprites in der Szenenansicht verschieben , indem wir es einfach ziehen Dadurch wird ihre Eigenschaft für transformierte zwei D-Positionen im Inspektor automatisch aktualisiert ihre Eigenschaft für transformierte zwei D-Positionen im Wir können das Sprite auch drehen, skalieren und neigen, wenn wir wollen Als Nächstes ziehen wir diesen Sprite Tu Di-Knoten auf den anderen und weisen ihn als untergeordneten Knoten des anderen Sprite Tu Di-Knotens zu, was durch eine weitere Einrückungsebene weisen ihn als untergeordneten Knoten des anderen Sprite Tu Di-Knotens zu, was durch eine weitere Einrückungsebene gekennzeichnet ist Wenn wir nun den übergeordneten Sprite Tu Di-Knoten auswählen und seine Transformationseigenschaften bearbeiten, werden diese Änderungen Die eigenen Transformationseigenschaften des Kindes werden in Bezug auf die Eigenschaften des Elternteils definiert Diese hierarchische Struktur der Szenen und die Vererbung von Eigenschaften ermöglichen es uns, komplexe Szenen mit mehreren verschiedenen Komponenten zu erstellen komplexe Szenen mit mehreren verschiedenen Komponenten Wir können der Szene eine beliebige Anzahl verschiedener Knoten verschiedener Typen hinzufügen , z. B. einen Audio-Stream-Player mit zwei D-Knoten und einen GPU-Partikel mit zwei D-Knoten Nun kann diese Szene mit zwei D-Szenen etwas zeichnen, Geräusche und Partikel aussenden , und all diese Komponenten erben ihre Transformationsposition vom Wurzelknoten Um die Sache zu vereinfachen, sollte die Transformation eines Wurzelknotens immer alle Standardwerte haben und nur untergeordnete Knoten enthalten, deren Transformationen bearbeitet Wir können Knoten umbenennen, was besonders nützlich ist der Wurzelknoten einer Szene beschreibt , worum es sich handelt Nennen wir es so etwas wie Roboter. Dann können wir diese Szene als Szenendatei in unserem Projekt speichern Szene als Szenendatei in unserem Projekt und sie erhält automatisch den gleichen Namen wie der Stammknoten. Erstellen Sie dann eine neue Zwei-D-Szene und stellen Sie sich vor, dass dies einen Raum darstellt, in dem sich der Roboter befindet. Unsere Roboterszene kann der Szene als einzelner Knoten hinzugefügt werden . Wir können sogar mehrere Roboter haben, wenn wir wollen. Im Kontext dieser größeren Szene können wir nun die Transformationseigenschaften eines Roboters bearbeiten , um ihn zu bewegen, drehen, zu skalieren, zu neigen usw. Lassen Sie uns diese Szene in Room umbenennen und speichern. Wenn wir zur Roboterszene zurückkehren und die untergeordneten Knoten des Roboters bearbeiten, werden diese Änderungen auf alle Instanzen des Roboters in anderen Szenen angewendet . der Raumszene muss es nicht Bei der Raumszene muss es nicht darum gehen, wie der Roboter gebaut ist, sondern nur darum, wo er sich im Raum befindet. Konstruktion von Szenen aus einzelnen Komponenten ermöglicht es uns, die Details einzelner Objekte geheim zu halten die Details einzelner Objekte geheim und vor größeren Bereichen zu verbergen Außerdem können wir auf einfache Weise mehrere Kopien derselben Sache erstellen, aber mit nur einer Quelle für das Objekt, das bearbeitet werden muss Der Aufbau eines kompletten Spiels besteht darin viele kleinere Szenen zu erstellen, die einzelne Spielobjekte, Charaktere und Orte darstellen , und dann mehrere dieser Szenen miteinander zu kombinieren , um eine größere Szene zu erstellen , während das Spiel läuft. Im nächsten Video werden wir untersuchen, wie die Engine nützliche integrierte Knotentypen für die Simulation von Physik bereitstellt Knotentypen für die Simulation von Physik Wir sehen uns im nächsten Video. 5. 0-4 Physik: Hallo Freunde. Nachdem wir nun verstanden haben, wie Szenen konstruiert werden, werden wir uns ansehen, wie Game-Engines integrierte Funktionen bereitstellen , um die Spieleentwicklung erheblich zu vereinfachen. Wir können die Roboter loswerden und diese Szene aus dem Projekt löschen. Beginnen wir damit, unserer Szene einen starren Körper hinzuzufügen. Im Kontext der Physik ist ein Körper jedes Objekt, das mit anderen Objekten kollidieren kann und Masse besitzt Ein starrer Körper steht für ein festes Objekt. Er wird durch äußere Kräfte wie die Schwerkraft beeinflusst, kollidiert mit anderen festen Objekten, verformt sich aber nicht oder Es wird seine Form behalten. Dieser starre Körper benötigt eine Form , bei der es sich um einen weiteren Knoten handelt, der als direktes Kind des starren Körpers hinzugefügt werden muss . Dieser Formknoten weiß nicht, welche Form er bis wir ihm im Inspektor eine Formressource geben. Aus der Drop-down-Liste können wir einige verschiedene Optionen auswählen. Ich mache eine rechteckige Form. Jetzt hat dieser starre Körper eine Form, aber es wird eigentlich nichts gezeichnet. Also fügen wir ihm einen Sprite-Zwei-D-Knoten hinzu und lassen ihn die Godot-Symboltextur zeichnen Das Sprite und die Kollisionsform stimmen nicht überein. also den Kollisionsformknoten auswählen, können wir ihn so anpassen, dass er besser zum Sprite passt, indem wir auf die roten Punkte klicken und sie ziehen oder indem wir seine Eigenschaften im Inspektor bearbeiten Halten Sie die Alt-Taste gedrückt während der Knoten für den starren Körper ausgewählt ist , und positionieren Sie ihn so , dass er sich irgendwo in der oberen Bildschirmmitte befindet Drücken Sie dann die Taste „ Aktuelle Szene ausführen“ oder drücken Sie F sechs als Tastenkombination. Die Spiel-Engine wendet automatisch Kräfte auf den starren Körper an, um reale Physik wie die Schwerkraft zu simulieren . Die Masse- und Gravitationsskala können im Inspektor schnell angepasst werden, um das Verhalten des starren Körpers zu optimieren Wir können ihm sogar ein physikalisches Material geben , um ihm Reibung oder Sprungkraft hinzuzufügen, seinen Massenschwerpunkt anzupassen und viele andere Optionen Lassen wir zunächst diese einfache Box mit einem Boden kollidieren. Sehr robuste Objekte, die wir nicht bewegen möchten, bestehen normalerweise aus einem statischen Körper statt aus einem starren Körper Ein statischer Körper kann immer noch mit anderen Körpern kollidieren, aber er bewegt sich durch diese Kollision nicht und wird nicht durch Kräfte wie die Schwerkraft beeinflusst Ein statischer Körper benötigt auch eine Kollisionsform. Aus dem Drop-down-Menü wähle ich Weltgrenze aus. Im Gegensatz zu anderen Formen erstreckt sich eine Weltgrenze bis ins Unendliche. In zwei D wird dies als Linie dargestellt. Der Pfeil in den beiden D-Ansichten zeigt von der Grenze weg. Standardmäßig wird eine Geschossdecke erstellt. die Position des statischen Körperknotens an den unteren Rand des Viewports verschieben des statischen Körperknotens an den unteren Rand des , wird verhindert der starre Körper über diese Weltgrenze fällt Lassen Sie uns den starren Körper duplizieren und sehen, wie er sich verhält, wenn er mit einem anderen starren Körper kollidiert Wir können auf einen Knoten klicken und seinen Typ ändern. Lassen Sie uns also diesen starren Körper in einen statischen Körper umwandeln. Positionieren und drehen Sie ihn dann so, dass der starre Körper in der Luft mit ihm kollidiert. Denken Sie daran, Knoten umzubenennen, nachdem Sie ihren Typ geändert haben, damit Sie wissen, um welchen Typ es sich Sie können es aber auch an dem Symbol neben ihrem Namen erkennen. Wenn wir das alles selbst manuell programmieren würden, würde es eine Menge Arbeit erfordern, diese Sprites zu zeichnen, zu berechnen, wie sie von Kräften beeinflusst werden, herauszufinden, wann sie miteinander kollidieren, und festzustellen, wie sich das auf ihr Verhalten auswirkt Neben der Physik helfen uns Game-Engines dabei, einen Großteil der Funktionen zu automatisieren , die in den meisten Spielen üblich sind drastisch zu beschleunigen und zu vereinfachen Im nächsten Video erfahren wir, wie man Skripte an Knoten anhängt, um ihr Verhalten zu bearbeiten Wir sehen uns im nächsten Video. 6. 0-5 Skripte: Hallo Freunde. Die Game-Engine bietet uns zwar viele integrierte Funktionen, wir können aber auch unsere eigenen hinzufügen, indem wir Skripte an Knoten anhängen Wenn ich einen beliebigen Knoten im Szenenbaum auswähle, verwende ich den statischen Körper , der eine schwebende Box ist Wir können entweder mit der rechten Maustaste klicken und das angehängte Skript auswählen oder die Schaltfläche für das angehängte Skript drücken. Dies öffnet ein neues Fenster. Das Skript erbt automatisch den Knotentyp, an den es angehängt ist, und wir können unser Skript bei Bedarf von einer Vorlage aus starten. Wir werden auch einen Namen für das Skript angeben , der seinen Zweck widerspiegeln sollte Ich nenne mein Script Spin und den Ordner, in dem es gespeichert ist. Wenn Sie auf die Schaltfläche Erstellen klicken, wechselt die Ansicht automatisch zur Skriptansicht, sodass wir mit der Bearbeitung des Skripts beginnen können. Die Vorlage beginnt mit zwei Funktionen: Bereit und Bearbeitung. Jeder Text, der dem Octothorp-Symbol folgt, ist ein Kommentar. Es wird nicht von der Engine verwendet und dient nur zu unserem Vorteil, um uns zu helfen, das Skript besser zu verstehen Wie in diesen Kommentaren beschrieben, wird die Ready-Funktion automatisch aufgerufen wenn dieser Knoten den Szenenbaum zum ersten Mal betritt, was ein bisschen irreführend ist Aber vorerst wird es bedeuten, wann das Spiel zum ersten Mal startet. Der Prozess wird dagegen bei jedem Frame aufgerufen, während das Spiel läuft Bei den Standardprojekteinstellungen ist das 60 Mal pro Sekunde. Eine Funktionsdeklaration beginnt mit dem Schlüsselwort funk, gefolgt vom Namen der Funktion. Diese Funktionsnamen beginnen mit einem Unterstrich Weise kennzeichnet Gudo Funktionen als privat, was bedeutet, dass sie nur im Kontext dieses Skripts verwendet werden dürfen den Funktionsnamen folgen Klammern, die Parameter für die Funktion enthalten , falls vorhanden Die Prozessfunktion hat einen Parameter, Delta, der die Anzahl der Sekunden angibt, die seit dem vorherigen Frame vergangen sind den meisten Fällen handelt es sich also um ein Sechzigstel, nimmt aber manchmal zu, wenn die Verarbeitung eines Frames länger dauert als erwartet Auf die Parameter folgt ein Bindestrich, der größer als ein Pfeil ist, dann der Rückgabetyp der Funktion, die in beiden Fällen ungültig sind, was bedeutet, dass sie keinen Wert zurückgeben Die Angabe von Rückgabetypen ist optional, und diese können entfernt werden, wenn Sie dies bevorzugen Der Inhalt einer Funktion ist um einen Tabulator eingerückt, ohne dass geschweifte Klammern erforderlich sind einen Tabulator eingerückt, ohne dass geschweifte Klammern erforderlich Beide Funktionen enthalten nur das Schlüsselwort pass, was im Grunde nichts tun bedeutet Aber wir können diese Anweisung durch etwas anderes ersetzen . Um zu sehen, wie das funktioniert, ändern wir Hauptteil der Ready-Funktion so, dass sie etwas tut. Die Druckfunktion gibt alles, was wir wollen, im Ausgabefeld aus , wenn das Spiel läuft. Wir können Funktionen aufrufen, indem wir ihren Namen gefolgt von Klammern angeben ihren Namen gefolgt von Klammern Dann können wir innerhalb der Klammern Argumente angeben, können wir innerhalb der Klammern Argumente angeben der Funktionen entsprechen In Anführungszeichen können wir alles schreiben, was wir wollen, Beispiel Ready to Spin Alles, was wir in Anführungszeichen setzen , wird als Zeichenfolge bezeichnet, kurz für Zeichenfolge. in der Prozessfunktion Lassen Sie uns in der Prozessfunktion dasselbe tun, aber dieses Mal den Wert von Delta ausgeben. Lassen Sie uns auch das tun, wofür dieses Skript gedacht war, und den Wert der Rotation dieses Knotens ändern, indem wir ihn mithilfe des Plus-Gleichheits-Operators um Delta erhöhen Der Plus-Gleichheitsoperator nimmt den Wert von Delta und addiert ihn zum Wert der Rotation Weisen Sie das Ergebnis dann auch der Rotation zu. Wenn wir die Szene ausführen, können wir sehen , dass sich die Kiste dreht. das Spiel beenden, können wir in der Ausgabe sehen , dass die Bereitschaftsnachricht zuerst gedruckt wurde, nur einmal, gefolgt von vielen Zahlen, von denen die meisten eine 60. sind Wie funktioniert das? Sowohl Ready als auch Process sind Funktionen von Node, was bedeutet, dass jeder Knoten in unserem Szenenbaum diese Funktionen bereits hat, aber sie tun nichts. Unser Skript überschreibt die Definitionen dieser Funktionen für einen bestimmten Knoten , an den dieses Skript angehängt ist Wir können in unserem Skript sehen, wenn eine Funktion eine Funktionsdefinition überschreibt , wenn ein blauer Pfeil davor steht Wenn wir das Spiel starten, rekonstruiert die Engine den Szenenbaum für diese Szene, beginnend mit der Wurzel, und fügt jeweils einen Knoten von oben nach Die Ready-Funktion für jeden Knoten wird aufgerufen , nachdem er zum Szenenbaum hinzugefügt wurde, aber auch, nachdem alle seine untergeordneten Knoten hinzugefügt wurden und ihre Ready-Funktionen zuerst aufgerufen wurden Das bedeutet, dass Eltern sich darauf verlassen können, dass ihre Kinder zum Szenenbaum hinzugefügt werden, bevor sie als bereit betrachtet werden. Wenn der gesamte Szenenbaum fertig ist, beginnen die Prozessframes. Der Prozess wird auf jedem Knoten im Szenenbaum von oben nach unten in sequentieller Reihenfolge aufgerufen im Szenenbaum von oben nach unten in sequentieller Reihenfolge Im Gegensatz zu Ready lassen Eltern ihre Kinder nicht zuerst verarbeiten wir nun ein grundlegendes Verständnis davon haben , wie Godot funktioniert, werden wir im nächsten Video damit beginnen, das Projekt für die Entwicklung unseres Spiels einzurichten Wir sehen uns im nächsten Video. 7. 0-6 Spiel: Hallo Freunde. Bevor wir mit unserem Spielprojekt beginnen, müssen wir ein paar Dinge vorbereiten. Zuerst können wir entweder alles löschen oder ein neues Projekt starten, damit wir einen Neuanfang haben. Ich werde alles außer der Bodenkollision entfernen. Benennen Sie dann diese Szene und ihren Stammknoten in Game um. Die Spielszene wird eine zentrale Szene sein , in der das gesamte Hauptspiel stattfindet. Der Stammknoten des Spiels wird zwei untergeordnete Hauptzweige haben, einen Knoten für die Weltumgebung und einen Knoten auf der Canvas-Ebene. Diese stellen eine klare Unterscheidung dar zwischen dem, was in der Spielwelt existiert, wie dem Level, in dem der Spieler gerade spielt, allen Charakteren, Gegenständen usw., und dem, was außerhalb dieser Welt ausschließlich zum Vorteil des Spielers existiert , d. h. Informationen, die auf einem Head-up-Display oder einer Benutzeroberfläche angezeigt werden Head-up-Display oder einer Benutzeroberfläche Der Weltumgebungsknoten wird mehrere Kinder haben. Ein oder mehrere Knoten für die aktuellen Levels, die geladen sind Im Moment stellen wir das einfach als statisches Body-Tutti dar Ein Tutti-Knoten für den Körper eines Charakters wird am häufigsten für den Spielercharakter verwendet und ein Kamera-Tutti-Knoten, der normalerweise dem Spieler folgt Ich setze die Position der Bodenkollision wieder auf den Ursprung der Szene zurück Wenn sich in der Szene ein Kameraknoten befindet, das blaue Rechteck nicht mehr dar, welcher Teil der Welt auf dem Bildschirm dargestellt wird. Stattdessen wird das Sichtfenster der Kamera in Magenta angezeigt, derzeit am Ursprung zentriert ist. Der Boden wird sich also in der Mitte der Kameraansicht befinden. der Leinwandebene werden Kinder für Dinge wie die Anzeige der Spielerinformationen auf dem Bildschirm, in Menüs usw. vorhanden sein. Diese werden alle mit Kontrollknoten dargestellt. Der Canvas- und der Kontrollknoten werden weiterhin das blaue Rechteck als Viewport verwenden das blaue Rechteck als Viewport um ihre Positionen auf dem Bildschirm zu ordnen Das funktioniert, während der Spieler das Spiel spielt, so, dass die Kamera die Welt betrachtet und zeichnet, was sie sieht, alle Kinder des Weltenumgebungsknotens Nachdem die Kamera ein rechteckiges Toti-Bild der Welt gerendert hat , zeichnet die Canvas-Ebene ihre Kinder darüber, sodass der typische Gameplay-Bildschirm entsteht , den wir gewohnt sind Diese beiden Branchen weisen noch einen weiteren klaren Unterschied auf. Die Welt muss angehalten werden, die Canvas-Ebene jedoch nicht Wenn Sie also den Spielknoten im Inspektor unter Knoten, Erweiterung Prozess auswählen, wird der zugehörige Prozessmodus auf „Immer“ geändert Der Node World Environment wird auf Pausble gesetzt und die Canvas-Ebene wird als Standard-Inherit-Ebene beibehalten Er erbt den Prozessmodus seines übergeordneten Knotens , also des Spielknotens, und wird es auch immer Da der voreingestellte Prozessmodus „Vererben“ ist, alle untergeordneten Elemente der Welt-Umgebung, was pausibel ist, wohingegen untergeordnete Elemente der Canvas-Ebene die Always-Verarbeitung Wenn wir in einem neuen Projekt zum ersten Mal auf die Schaltfläche „Projekt ausführen“ klicken, werden wir aufgefordert, die Hauptszene festzulegen Wir können die aktuelle Szene oder eine andere Szene aus dem Projekt auswählen. die Spielszene gerade geöffnet ist, können wir sie vorerst als Hauptszene festlegen und sie später ändern, wenn wir eine Titelszene haben. Dies kann in den Projekteinstellungen unter den Ausführungseinstellungen geändert werden. Es ist auch eine gute Idee, Ihre Anzeigeeinstellungen festzulegen , bevor Sie beginnen. Wählen Sie also Fenster aus. Hier können wir die Breite und Höhe des Viewports in Pixeln einstellen und Höhe des Viewports in Pixeln Ich finde, dass 12 × 80 × 720 eine gute Größe für die meisten Spiele sind, und sie ist mit den meisten Plattformen kompatibel unter Stretch den Stretch-Modus von deaktiviert auf Canvas-Elemente ändern , wird sichergestellt, dass zwei D-Knoten entsprechend dem Spielfenster dehnen oder verkleinern Da ich Pixelkunst verwenden werde, ändere ich den Skalierungsmodus von Fractional auf Pixel werden also nur doppelt oder halb so groß, wodurch Pixel mit gemischter Größe vermieden werden Unter „ Texturen rendern“ ändere ich außerdem den Standard-Texturfilter von „linear“ auf „Am ähnlichsten“. Dadurch werden meine Pixelgrafiken genau so dargestellt, wie sie sind, und verhindert, dass sie verschwommen Nachdem Sie die Projekteinstellungen geschlossen haben, müssen Sie möglicherweise eine Aktualisierung auslösen , indem Sie einfach das Ansichtsfenster zoomen oder schwenken , um das blaue Rechteck oder die Kamera zu erzwingen , ihre Größe selbst oder Jetzt können wir damit beginnen, das Projekt in seine einzelnen Komponenten zu zerlegen in seine einzelnen Komponenten und sie nacheinander anzugehen. Im nächsten Abschnitt werden wir einen grundlegenden Tutti-Plattform-Charakter erstellen , den der Spieler kontrollieren kann Wir sehen uns im nächsten Video. 8. 1-1 CharakterKörper: Hallo Freunde. In diesem Abschnitt werden wir einen 2D-Plattform-Charakter bauen , den der Spieler kontrollieren kann Falls deine Spielszene noch nicht über einen Charakterkörper mit zwei Dnode verfügt, solltest du jetzt einen hinzufügen Der Charakterkörper zwei D ist kein Körper im Sinne einer Person, sondern ein physischer Körper, wie der starre Körper oder der statische Körper Im Gegensatz zu starren Körpern wird auf einen Charakterkörper nicht automatisch die Schwerkraft ausgeübt automatisch die Schwerkraft ausgeübt, sondern er reagiert im Gegensatz zu einem statischen Körper auf Kollisionen im Gegensatz zu einem statischen Körper Der Körperknoten der Figur benötigt also auch eine Kollisionsform als untergeordnetes Objekt mit einer Formressource, die ihm mitteilt, welche Form er hat Die meisten Spiele verwenden eine Kapsel, um einen Charakter darzustellen, aber es werden auch Rechtecke und Kreise verwendet Vorerst verwende ich ein Rechteck mit Abmessungen 128 mal 128 Wir können jederzeit die Kollisionsform ändern oder die Größe nachdem wir eine Zeichnung des Charakters erstellt haben , auf der er später basieren soll Zusätzlich zur Kollisionsform benötigen wir auch einen Sprite-Knoten, um den Charakter zu zeichnen Es ist wichtig, keinen animierten Sprite-Knoten zu verwenden animierten Sprite-Knoten da dies nicht der beabsichtigte Zweck ist Animierte Sprite-Knoten dienen nur zum Zeichnen einfacher animierter Sobald Sie andere Knoten mit Ihren Animationen wie Sounds, Partikeln oder Funktionen synchronisieren müssen , benötigen Sie mehr Flexibilität, als der Animated Sprite-Node Im Moment verwende ich einfach das Godot-Symbol als Textur des Charakters, das 128 mal 128 Pixel groß ist und der Kollisionsform entspricht Lassen Sie uns den Toti-Knoten des Charakters in den Namen des Charakters umbenennen Toti-Knoten des Charakters in den Namen des Charakters Wir haben zwar nicht die Absicht mehrere Kopien dieses Charakters zu haben, aber es ist trotzdem eine gute Idee seine Struktur in einer separaten, von der Spielszene isolierten Szene zusammenzustellen von der Spielszene isolierten Szene Das können wir erreichen, indem wir mit der rechten Maustaste auf den Knoten dann Zweig als Szene speichern auswählen. Lassen Sie uns einen neuen Unterordner für Szenen erstellen, einen weiteren darin für Charaktere, speichern wir ihn dann unter dem Namen dieses Charakters In der Spielszene wird dieser Charakter jetzt als ein einziger Knoten mit einem Klapperbrettsymbol dargestellt , was uns darauf hinweist, dass es sich um Alle untergeordneten Knoten sind versteckt und befinden sich jetzt in der Wir können die Charakterszene öffnen indem wir auf das Schindelsymbol klicken. In der Szene des Charakters empfiehlt es sich, den Ursprung des Charakters so zu betrachten , dass er sich im Mittelpunkt zwischen seinen Füßen befindet, als ob die X-Achse der Boden Dadurch wird sichergestellt, dass alle Charaktere unabhängig von ihrer Größe ihren Ausgangspunkt gemeinsam haben . Lassen Sie uns also die Sprite- und Kollisionsformknoten entlang der Y-Achse nach oben verschieben Kollisionsformknoten entlang der Y-Achse nach oben Zusätzlich zur Kollisionsform und den Sprite-Knoten benötigt unser Charakter einen Animationsspieler, um die Sprite-Animationen abzuspielen Außerdem gibt es einen Animationsbaum, mit dem Sie steuern können , welche Animation zu einem bestimmten Zeitpunkt abgespielt wird einem Audio-Stream-Player mit zwei D-Knoten können wir auch Soundeffekte abspielen. Möglicherweise möchten wir auch einen GPU-Partikelemitter verwenden, um Partikeleffekte für Dinge wie Schritte und Sprünge zu erzeugen Dinge wie Schritte und Jeder dieser Knoten wird in einem eigenen Video behandelt , um sie genauer zu erklären Vorerst ist es wichtig zu verstehen, wie eine Szene alles im Spiel darstellen kann , wobei ihre eigene Szene über viele untergeordnete Knoten verfügt , die zu ihrer Erstellung verwendet werden. den Wurzelknoten dieser Szene wird normalerweise ein Skript angehängt. Je nachdem, wie Sie Ihre Dateien organisieren möchten, möchten Sie dieses Skript möglicherweise in demselben Ordner wie die Szene speichern , an die es angehängt ist , oder in einem separaten Ordner speziell für Drehbücher. Sie sollten Ihre Skripte nach ihrem Verwendungszweck benennen und dabei einen möglichst vagen Namen angeben Dieses Skript wird nicht spezifisch für meinen Kindercharakter sein, sondern sollte so geschrieben sein, dass es für jeden Charakter gelten kann , zumindest vorerst Der Zweck des Skripts wird darin bestehen, nicht nur den Körperknoten des Charakters selbst zu kontrollieren, sondern auch die Operationen aller untergeordneten Knoten so durchzuführen, dass sie so harmonisch funktionieren, wie es für die Knoten so durchzuführen, dass sie so harmonisch funktionieren, Erstellung unseres Charakters erforderlich Dieses Skript, das an den Stammknoten unserer Charakterszene angehängt ist, ist auch von der Spielszene aus zugänglich und dient zwei weiteren Zwecken. Es verschleiert die Verarbeitung der einzelnen Komponenten der Charakterszene und bietet gleichzeitig eine übersichtliche und übersichtliche Oberfläche für Interaktion mit anderen Skripten und Objekten in der Darauf wird im weiteren Verlauf dieses Abschnitts näher eingegangen Nachdem wir nun eine grundlegende Charakterstruktur erstellt haben, müssen wir vom Spieler Feedback erhalten, um sie kontrollieren zu können. Wir sehen uns im nächsten Video. 9. 1-2 Eingabekarte: Hallo Freunde. In diesem Video werden wir Eingaben vom Spieler entgegennehmen und sie an den Charakter senden. Da ich das Skript für den Tu Di-Knoten meines Charakters anhand einer Vorlage erstellt habe , es bereits Code, der Eingaben entgegennimmt und den Charakter nach links oder rechts bewegt. Wenn wir die Spielszene ausführen, der Charakter durch Drücken der linken und rechten wird der Charakter durch Drücken der linken und rechten Pfeiltasten bewegt, aber das fühlt sich nicht sehr gut und ist nicht sehr gut implementiert. Der Kommentar sagt uns sogar , dass wir zumindest die linken und rechten Benutzeroberflächenaktionen durch unsere eigenen benutzerdefinierten Gameplay-Aktionen ersetzen sollten die linken und rechten Benutzeroberflächenaktionen . Dazu öffnen wir die Projekteinstellungen und wechseln dann zur Eingabekarte. In das Feld „Neue Aktion hinzufügen “ geben wir den Namen unserer Aktion ein, beginnend mit „Nach links bewegen“. Dies darf keine Leerzeichen enthalten und wird normalerweise in kleinen Schlangenbuchstaben geschrieben, wobei alle Kleinbuchstaben durch Unterstriche getrennt sind Drücken Sie die Eingabetaste oder klicken Sie auf die Schaltfläche Hinzufügen, um die Eingabeaktion hinzuzufügen, und machen Sie dann eine weitere Aktion, um nach rechts zu gehen Und wir werden später auch einen für Jump benötigen. rechts neben jeder dieser Aktionen auf die Plus-Schaltfläche, Klicken Sie rechts neben jeder dieser Aktionen auf die Plus-Schaltfläche, um dieser Eingabeaktion ein Ereignis hinzuzufügen. Dies ist die Taste, die gedrückt wird, um sie auszulösen. Das Listen-Feld erkennt automatisch Eingabeereignisse, oder Sie können die verfügbaren Eingabeereignisse durchsuchen. Um mich nach links zu bewegen, verwende ich die linke Pfeiltaste, bewege ich mich mit der rechten Pfeiltaste nach rechts und springe mit der Z-Taste. Wir können jeder Aktion mehrere verschiedene Ereignisse hinzufügen, was bedeutet, dass wir Controller-Unterstützung einfach hinzufügen können , indem wir zusätzliche Ereignisse für den Controller hinzufügen. Ich verwende das Steuerkreuz nach links und rechts, um den Charakter zu bewegen, sowie den linken Stick nach links und rechts und auch die untere Taste zum Springen. Wenn Sie fertig sind, schließen Sie die Projekteinstellungen. In diesem Video werden wir nur diese eine Zeile ändern, in der wir Eingaben abrufen, und, was noch wichtiger ist, sie in ein separates Skript verschieben Es empfiehlt sich, dass alle Ihre Skripte nur einem einzigen Zweck dienen Dieses Skript wird nur verwendet, um einen Charakter zu steuern, nicht um Eingaben vom Spieler zu erhalten. dem Szenenbaum einen neuen Knoten hinzufügen, kann dieser einfach ein normaler Knoten sein, da er nichts anderes tut, als unser Skript auszuführen. Nennen wir es Player. Hängen Sie dann ein neues Skript an. Es gibt mehrere Möglichkeiten, Eingaben zu empfangen. Am gebräuchlichsten ist es, die Eingabefunktion zu überschreiben. Funktionsüberschreibungen müssen exakt mit der überschriebenen Funktion übereinstimmen Der Name muss also exakt dieselbe Schreibweise, dieselben Parametertypen und denselben Rückgabetyp Die Eingabefunktion hat einen Parameter, ein Eingabeereignis, dem wir einen beliebigen Namen geben können. Aber ich bevorzuge es, ihre Standardnamen zu verwenden, und es gibt nichts zurück. Die Eingabefunktion wird in jedem Frame aufgerufen , wenn ein Eingabeaktionsereignis eingetreten ist, egal ob es sich dabei um das Drücken einer Taste, Neigen eines Analogsticks oder das Bewegen der Maus Innerhalb dieser Eingabefunktion können wir über seinen Namen auf das Eingabeereignis zugreifen und auf seinen Inhalt mit einem Punkt Wir wollen eine Funktion des Eingabeereignisses namens Is action pressed aufrufen . Beim Aufrufen einer Funktion müssen auf den Funktionsnamen Klammern folgen In den Klammern geben wir Argumente für die Funktion an, die ihren Parametern entsprechen In diesem Fall eine Zeichenfolge, der Name der Eingabeaktion, die wir überprüfen Also schreiben wir Sprünge in Anführungszeichen und achten darauf, dass Groß- und Kleinschreibung der Eingabeaktion, die wir in den Projekteinstellungen erstellt haben, exakt übereinstimmen Kleinschreibung der Eingabeaktion, die . Diese Funktion gibt einen booleschen Wert zurück, entweder true, wenn die Taste gedrückt wurde, oder false, wenn sie nicht Indem wir diese Funktion hinter das Schlüsselwort if setzen, gefolgt von einem Doppelpunkt, können wir eine neue Einrückungsebene für unser Skript erstellen Alles, was wir hier eingeben, wird nur ausgeführt, wenn das Ergebnis der I-Anweisung wahr ist, also nur, wenn die Taste gedrückt wurde Vorerst drucken wir einfach das Wort Jump aus. Wenn wir das Spiel ausführen und eines der Eingabeereignisse drücken, die wir als Sprungeingabeaktion angegeben haben, werden wir sehen, dass der Sprung im Ausgabefenster gedruckt wird. Wir brauchen die Ready-Funktion nicht, also entfernen wir sie. Für Dinge wie Bewegung, insbesondere bei der Verwendung von Controllern mit Analogsticks, kann es nützlich sein, innerhalb der Prozessfunktion nach dieser Eingabe zu suchen . Genau wie beim Zeichenskript müssen wir den Eingabe-Singleton verwenden Diese Singleton-Klasse hat eine Funktion namens get axis. Die G-Achsenfunktion erfordert zwei Parameter, eine negative und eine positive Aktion Links wird immer als negativ und rechts als positiv betrachtet , was der X-Achse in unseren beiden D-Welten entspricht. Also schreiben wir die Namen unserer Eingabeaktionen wir in den Projekteinstellungen erstellt haben, in Anführungszeichen, bewegen uns nach links und nach rechts. Diese Funktion gibt eine Dezimalzahl zwischen minus eins und positiv zurück , die angibt, wie weit der linke Stick in eine angibt, wie weit der linke Stick der beiden Richtungen geneigt ist, oder einfach eine negative oder positive Zahl, wenn Sie Tasten oder Knöpfe verwenden Da der Wert Null, was bedeutet, dass keine Eingabe erfolgt, immer noch eine gültige Eingabe ist, möchten wir diese Information immer bei jedem Frame an den Spieler senden diese Information immer bei jedem Frame an den Spieler Hier ist also keine If-Aussage erforderlich. Lassen Sie uns einfach den Wert ausdrucken hier zurückgegeben wird , damit wir ihn sehen können. Beim Ausführen des Spiels wird die Zahl Null wiederholt gedruckt. Wenn ich die linke oder rechte Pfeiltaste, die Richtungstasten auf meinem Controller drücke oder den linken Analogstick neige, ändert sich der Wert zwischen negativ und positiv Falls Sie jemals weitere Informationen einer dieser Klassen oder Funktionen benötigen, können Sie auf deren Dokumentation zugreifen, indem die Strg- oder Befehlstaste gedrückt halten und auf sie klicken das Zeichenskript von zuvor öffnen, haben wir eine Variable namens direction die in der Prozessfunktion deklariert wird. Lassen Sie uns das auskommentieren und diese Variable in den globalen Bereich unseres Skripts verschieben , indem sie stattdessen oben im Skript deklarieren Wenn wir zum Spielerskript zurückkehren, in dem wir Bewegungseingaben erhalten haben , um diese Informationen von einem Skript an ein anderes weiterzugeben , benötigen wir einen Verweis auf das andere Skript Im Spielerskript werden wir eine Variable erstellen, die einen Verweis auf den Körper eines Charakters enthält . Indem wir vor der Variablendeklaration ein Export-Tag hinzufügen, die Variable vom Inspektor aus zugänglich und wir können ihren Wert als unseren Charakter zuweisen. Anstatt den Wert von input dot get axis auszudrucken , senden wir ihn an das Zeichen, indem ihn der Richtungsvariablen des Zeichens zuweisen Wenn wir das Spiel starten, überprüft der Player-Node jedem Frame den Status unserer Eingaben „Zug nach links“ und „ Zug nach rechts Weisen Sie das dann der Richtungsvariablen des Charakters zu. Die Funktion zur Verarbeitung von Zeichenskripten überprüft die Richtungsvariable jedem Frame und verwendet diese, um das Zeichen nach links und rechts zu bewegen. Unser Spieler gibt jetzt Eingaben , um unseren Charakter zu bewegen. Wir sehen uns im nächsten Video. 10. 1-3 Bewegung: Hallo Freunde. In diesem Video werden wir die Bewegung der Charaktere verbessern , indem wir Physik anwenden. Im Zeichenskript können wir sehen, dass die Standardvorlage prüft, ob der Wert von direction Null ist. Null wird als falsch behandelt und jeder andere Wert ist wahr. Wenn also ein Richtungswert angegeben wird, der nicht Null ist, die X-Geschwindigkeit des Charakters auf Richtung multipliziert mit Geschwindigkeit gesetzt Oder wenn die Richtung Null ist, dann bewegt sich der Wert der X-Geschwindigkeit des Charakters mit der Geschwindigkeit gegen Null Das Ergebnis ist, dass die Geschwindigkeit der Figur entweder Null oder Geschwindigkeit ist, außer wenn der Analogstick geneigt Das ist nicht sehr realistisch und fühlt sich nicht sehr gut an. Diese Werte für Geschwindigkeit und Sprunggeschwindigkeit sind ebenfalls als Konstanten definiert, die sich im Gegensatz zu Variablen niemals ändern dürfen Das ist problematisch, und wir sollten das ändern, wenn wir wollen, dass sich die Charaktere in unserem Spiel jemals mit unterschiedlichen Geschwindigkeiten bewegen mit unterschiedlichen Geschwindigkeiten Wir werden uns später mit dem Springen befassen. Beachten Sie auch, dass diese Werte in Pixeln gemessen werden, sodass sie je nach Größe Ihres Charakters variieren. Lassen Sie uns zunächst unsere Geschwindigkeitskonstante durch eine Bewegungsgeschwindigkeitsvariable vom Typ Float ersetzen . Ich stelle meins auf 256 Pixel pro Sekunde ein. Es ist eine gute Idee, Variablen und Funktionen in Bereiche zu unterteilen, die öffentlich und privat sein sollen , indem privaten Namen ein Unterstrich vorangestellt alles Private soll nur innerhalb dieses Skripts selbst zugegriffen werden, im Gegensatz zur Richtungsvariablen, auf die vom Gegensatz zur Richtungsvariablen, Player-Skript aus zugegriffen und sie geändert wird , also öffentlich ist Im physikalischen Prozess werden wir die Geschwindigkeitskonstante durch unsere Bewegungsgeschwindigkeitsvariable ersetzen . Und jetzt funktioniert alles genauso wie zuvor, außer dass die Geschwindigkeit etwas langsamer ist. Wenn wir vor dieser Variablendeklaration ein Export-Tag hinzufügen , können wir dessen Wert im Inspektor ändern. Dies ist eine großartige Möglichkeit, den Wert zu testen und zu optimieren, damit er sich genau richtig anfühlt Da können wir unser Spiel ausführen, schauen, ob es sich gut anfühlt, es dann ändern und erneut testen Ein weiterer Vorteil ist, dass, wenn wir mehrere Charaktere haben , die dasselbe Skript verwenden, jeder seinen eigenen Wert für diese Variable haben kann. Normalerweise bewegen sich Charaktere jedoch nicht sofort mit maximaler Geschwindigkeit vom Stillstand zur Bewegung. Stattdessen wird bei ihnen im Laufe der Zeit eine gewisse Beschleunigung angewendet, bevor sie ihre Höchstgeschwindigkeit erreichen Dies kann erreicht werden, indem eine weitere Variable namens Beschleunigung deklariert wird, ebenfalls schwimmend ist und in Pixeln pro Quadratsekunde gemessen wird in Pixeln pro Quadratsekunde gemessen Wenn das einfacher ist, können Sie davon ausgehen, dass der Wert ein Vielfaches Ihrer Wenn meine Beschleunigung doppelt so hoch ist wie meine Geschwindigkeit, dann erreiche ich die Höchstgeschwindigkeit in einer halben Sekunde. Oder wenn es die Hälfte meiner Geschwindigkeit ist, dauert es 2 Sekunden, bis ich die Höchstgeschwindigkeit erreicht habe. Um die Beschleunigung in den physikalischen Prozess einzubeziehen, müssen wir lediglich den Wert unserer aktuellen X-Geschwindigkeit in Richtung Geschwindigkeit multipliziert mit der Richtung bei einer Beschleunigungsrate verschieben den Wert unserer aktuellen X-Geschwindigkeit in Richtung Geschwindigkeit multipliziert mit Richtung bei einer Beschleunigungsrate Aber das wird alles auf einmal in einem einzigen Frame passieren. Um die Geschwindigkeit im Laufe der Zeit anzupassen, müssen wir das tun, was die Vorlage hier tut , indem sie die Schwerkraft anwendet und mit Delta multipliziert. Da Delta die Anzahl der Sekunden ist , die seit dem vorherigen Frame vergangen sind, normalerweise eine 60stel-Sekunde, führt dies dazu, dass die Beschleunigungsrate über die Zeit und nicht auf einmal angewendet wird über die Zeit und nicht auf einmal angewendet Die Funktion move toward nimmt den Inhalt des ersten Parameters, bewegt ihn um den Betrag des dritten Parameters in Richtung des Werts des zweiten Parameters und gibt das Ergebnis zurück Sie ändert den Wert des ersten Parameters nicht, also müssen wir ihn so zuweisen, dass er den vorherigen Wert unserer X-Geschwindigkeit überschreibt den vorherigen Wert unserer X-Geschwindigkeit Die Funktion „Verschieben und Verschieben ist in der Klasse D für Charakterkörper 2 definiert und führt alle schwierigen Berechnungen für uns durch. Dabei werden die Geschwindigkeit der Figur, äußere Kräfte wie die Schwerkraft und Kollisionen mit anderen physikalischen Körpern berücksichtigt äußere Kräfte wie die Schwerkraft und dann entschieden, wo sich die Figur in den einzelnen Bildern befinden soll wir das Spiel jetzt ausführen, schrittweise beschleunigt, bevor wir unsere Höchstgeschwindigkeit erreichen Außerdem können wir den Wert unserer Beschleunigung im Inspektor anpassen unserer Beschleunigung im Inspektor es sich so anfühlt , wie wir es möchten Wir können diese Kommentare entfernen. Dieselbe Logik kann auf die Verzögerung angewendet werden, indem einfach eine weitere Variable hinzugefügt Dieser Wert ist normalerweise viel höher als die Beschleunigung. Der Code im Physikprozess verwendet bereits Move Toward. Wir müssen nur Geschwindigkeit durch Verzögerungszeiten Delta ersetzen Verzögerungszeiten Es gibt jedoch einen anderen Zeitpunkt , an dem wir vielleicht die Verzögerung anwenden möchten , außer wenn der Spieler keine Eingabe macht, wenn er sich umdrehen und in die andere Richtung gehen möchte umdrehen und in die andere Richtung gehen Wir können unsere I-Erklärung erweitern, um diesen Fall zu berücksichtigen. Nachdem wir überprüft haben, ob die Richtung nicht Null ist, wenn unsere X-Geschwindigkeit Null ist, steht der Charakter still, dann wollen wir trotzdem beschleunigen. Aber wenn die Richtungssünde der gleiche ist wie der Sinus der X-Geschwindigkeit, dann versucht der Spieler, sich in die gleiche Richtung zu bewegen, in die er sich bereits bewegt, und wir wollen weiter beschleunigen, bis die Geschwindigkeit steigt Die Sinusfunktion wandelt jede Zahl in negative Eins, Null oder positive Eins um, was den Vergleich, ob diese beiden Werte beide positiv oder beide negativ sind, einfacher Wir können Bedingungen mit oder kombinieren. Wenn also einer dieser Werte wahr ist, dann ist die gesamte Aussage wahr. Wenn beide falsch sind, wollen wir umkehren, was bedeutet, dass wir eine Verzögerung anstelle von Beschleunigung anwenden , was zu einer viel schnelleren Wende führt, als dies bei einer Beschleunigung der Fall wäre , wenn der Wert der Verzögerung Wenn wir das ausprobieren, sollte es sich jetzt viel realistischer anfühlen, unseren Charakter nach links und rechts zu bewegen , und wir können die Werte für unsere Geschwindigkeit, Beschleunigung und Verzögerung einfach im Inspektor anpassen Beschleunigung und Wir sehen uns im nächsten Video. 11. 1-4 Springen: Hallo Freunde. In diesem Video werden wir die Implementierung des Sprungs verbessern. Bevor wir mit dem Springen beginnen, bewege ich die Kamera entlang der Y-Achse nach oben sodass sich der Boden am unteren Bildschirmrand befindet, nicht in der Mitte. Das Vorlagenskript für unseren Charakter hat bereits eine Sprungtaste in der Benutzeroberfläche , mit Ausnahme der Leertaste, die die Y-Geschwindigkeit des Charakters auf Sprunggeschwindigkeit setzt. Aber in einem früheren Video haben wir bereits unsere eigene Sprungtaste hinzugefügt . Im Gegensatz zu Schwerkraft oder Beschleunigung, die mit Delta multipliziert und über mehrere Frames auf den Charakter angewendet werden, wird diese Sprunggeschwindigkeit sofort auf den Charakter Beim Ausführen des Spiels können wir die Leertaste drücken, um zu springen, aber es gibt mehrere Probleme Der Sprung ist immer gleich hoch und das Zeichenskript sucht nach Eingaben. Lassen Sie uns dies zunächst aus dem physikalischen Prozess des Charakters entfernen und es stattdessen einer öffentlichen Funktion zuweisen. Wir nennen es Sprung. dann im Spielerskript Wenn wir dann im Spielerskript die Sprungtaste drücken, anstatt Jump zu drucken, können wir dem Charakter sagen, dass er stattdessen springen soll. Zugriff auf den Inhalt des Charakters mit einem Punkt, gefolgt vom Namen der Funktion, und die Funktion hat keine Parameter, also nichts in Klammern Aber jetzt erlauben wir dem Charakter , jederzeit zu springen, wenn die Taste gedrückt wird, auch wenn er sich nicht auf dem Boden Wir müssen zuerst überprüfen, ob der Charakter auf dem Boden ist , bevor wir ihn springen lassen. Diese Funktion auf dem Boden ist in der Klasse D des Charakters Body Two definiert. Jetzt kann der Charakter nur springen, wenn er sich auf dem Boden befindet, aber der Sprung hat immer dieselbe Höhe. In den meisten Spielen springt der Charakter höher, die Taste gedrückt hält, als wenn er einfach gedrückt würde. Manchmal können wir messen, wie lange die Sprungtaste gedrückt gehalten wird, bevor wir sie loslassen, diese Information dann über den Sprungfunktionsaufruf weiterleiten , um die Sprungkraft anzupassen. Aber vor allem bei zwei D-Plattformspielen erwarten wir normalerweise, dass Sprünge sofort passieren, wenn wir die Taste drücken, was bedeutet, dass wir nicht warten können bis die Taste gedrückt gehalten oder losgelassen wird Stattdessen ist es üblicher, davon auszugehen, dass der Sprung die volle Sprunghöhe erreicht, und ihn dann abzubrechen wenn der Spieler die Taste vorzeitig loslässt So wie wir im Skript des Spielers auf das Drücken einer Taste reagiert haben, können wir auch darauf reagieren, dass sie losgelassen wird. Mit dem Schlüsselwort if wird dies nur überprüft, wenn die vorherigen Bedingungen falsch waren. Dadurch entfällt die Notwendigkeit , zu überprüfen, ob die Taste gleichzeitig gedrückt und losgelassen wurde gleichzeitig gedrückt und losgelassen Wenn die Sprungtaste losgelassen wird, können wir eine andere Funktion aufrufen, um den Sprung abzubrechen und ihn zu verkürzen Zurück im Zeichenskript müssen wir die abgebrochene Sprungfunktion deklarieren, die keine Parameter benötigt und keinen Wert zurückgibt. Eine einfache Möglichkeit, dies zu tun, wäre, Y-Geschwindigkeit des Charakters auf Null zu setzen, aber das kann sich ziemlich unnatürlich anfühlen , wenn es mitten in der Luft zum Stillstand kommt Also teile ich stattdessen die Y-Geschwindigkeit durch zwei. Aber wir wollen, dass das nur passiert, wenn die Geschwindigkeit des Charakters derzeit kleiner als Null ist, das heißt, er bewegt sich nach oben und nur, wenn seine Geschwindigkeit kleiner als Null ist, weil er gesprungen Wenn es einen anderen Grund gäbe warum sich der Charakter nach oben bewegt, aber nicht gesprungen ist, würden wir nicht zulassen wollen , dass er einen Sprung abbricht und seine Geschwindigkeit verringert Wir können das kontrollieren, indem wir eine neue Variable deklarieren. Wir nennen es Is Jumping vom Typ Boolean, was natürlich standardmäßig auf False Wenn wir diese Variable auf true setzen, wenn der Charakter springt, können wir überprüfen, ob der Charakter springt, bevor wir ihm erlauben, den Sprung abzubrechen Falls sie den Sprung nicht abbrechen, müssen wir die Variable is jump automatisch wieder auf false setzen automatisch wieder auf false Im physikalischen Prozess können wir also überprüfen, ob die Figur springt und ob ihre Y-Geschwindigkeit größer oder gleich Null ist, was bedeutet, dass die Figur fällt oder sich zumindest nicht nach was bedeutet, dass die Figur oben bewegt, dann können wir auf Falsch springen setzen, weil es für die Figur zu spät ist , die Taste loszulassen, um diesen Sprung abzubrechen. Das funktioniert hervorragend, aber jetzt möchten wir vielleicht anpassen, wie hoch die Figur springen kann. Das Vorlagenskript deklariert die Sprunggeschwindigkeit als Konstante. Genau wie bei der Bewegungsgeschwindigkeit können wir sie in eine Variable umwandeln Aber zu wissen, wie viel Geschwindigkeit erforderlich ist um eine bestimmte Höhe zu erreichen, ist nicht sehr intuitiv, und aus gestalterischer Sicht ist es oft besser, genau kontrollieren zu können , wie hoch ein Charakter springen kann. Lassen Sie uns also eine weitere Variable namens Sprunghöhe als Ganzzahl deklarieren . Dies wird in Pixeln gemessen. Ich setze meins auf 256, was der doppelten Höhe des Charakters entspricht. Mit dem Tag on ready können wir mit etwas Mathematik die Sprungkraft berechnen, die erforderlich ist, um genau diese Höhe zu erreichen. Das Tag on ready führt diese Zeile des Skripts aus, wenn der Knoten bereit ist, bevor die Ready-Funktion ausgeführt Skripts aus, wenn der Knoten bereit ist wird. Ich bin kein Physiker, daher könnte ich nicht erklären , warum diese Gleichung funktioniert, aber sie funktioniert Nimm einfach die Quadratwurzel der Schwerkraft multipliziert mit der Sprungkraft mal zwei Dann multipliziere das alles auch mit minus eins, da das Minus entlang der Y-Achse nach oben zeigt Um dies zu tun, müssen wir die Schwerkraft, die auf das Zeichen ausgeübt wird, als dezimale Zahl im Wasser kennen das Zeichen ausgeübt wird, als . also eine weitere Variable mit dem Tag on ready deklariert wird, muss sich diese über der Jump-Force-Variablen befinden, also wird sie zuerst gesetzt Wir können die Schwerkraft aus den Projekteinstellungen ermitteln Wir müssen nur den Pfad zu der gewünschten Einstellung in einer Zeichenfolge angeben. Wenn der Charakter springt, setzen wir schließlich seine Y-Geschwindigkeit auf diese berechnete Sprungkraft Jetzt kann der Spieler kontrollieren, wie hoch er springen möchte. Und wir können die maximale Sprunghöhe eines Charakters ganz einfach im Inspektor bearbeiten . Wir sehen uns im nächsten Video. 12. 1-5 Sturz: Hallo Freunde. In diesem Video passen wir an, wie sich der Charakter in der Luft fühlt und steuert Unser Charakter kann jetzt höher springen, fühlt sich aber sehr schwebend und der Charakter kann seine Bewegung in der Luft genauso einfach kontrollieren wie am Vielleicht möchtest du das für dein Spiel, aber oft hat der Spieler in der Luft weniger Kontrolle über den Charakter Im Charakterskript können wir diese alten Konstanten entfernen, können wir diese alten Konstanten entfernen da sie nirgends mehr verwendet werden Da unser Skript mehrere Dinge tut, den Charakter nach links und rechts bewegt und springt, wäre es eine gute Idee, es zu organisieren Ich lasse meine Variablen für Bewegungsgeschwindigkeit, Beschleunigung, Verzögerung und Richtung gruppieren und mache dasselbe mit Variablen , die sich auf das Springen beziehen Wir können sogar Kategorien für unsere Variablen erstellen, indem das Export-Kategorie-Tag und den Namen der Kategorie als Zeichenfolge angeben Lassen Sie uns eine separate Kategorie für Variablen haben auf die Fortbewegung beziehen, und eine weitere für das Springen Dadurch werden dem Inspektor Header hinzugefügt, sodass unsere exportierten Variablen in diese Kategorien unterteilt werden Unsere Kategorie „Springen“ hat nur eine Variable, aber wir werden weitere hinzufügen, angefangen mit einem Gravitationsmultiplikator Dies wird ein Float sein und ich gebe ihm den Standardwert eins Multiplizieren Sie dann unsere Schwerkraft mit dem Schwerkraftmultiplikator , nachdem Sie ihn aus den Projekteinstellungen abgerufen Da diese Zahl zur Berechnung der Sprungkraft verwendet wird , die erforderlich ist, um unsere gewünschte Sprunghöhe zu erreichen, ändert sich die Sprunghöhe des Charakters nicht und die Kraft wird automatisch erhöht, und die Kraft wird automatisch um dies zu kompensieren die Projekteinstellungen öffnen und unter Physik zwei D nachschauen, unter Physik zwei D nachschauen, ist die Standardgravitation auf 980 Pixel pro Quadratsekunde eingestellt Wir können hier die Schwerkraft für das gesamte Projekt ändern , was sich auf alle unsere physikalischen Körper auswirkt Wir möchten vielleicht, dass sich einige Dinge schwerer oder leichter anfühlen als andere, und eine einfache Möglichkeit, dies zu tun, besteht darin, ihre eigene individuelle Schwerkraft mit einer anderen Zahl zu multiplizieren . Gravitationsmultiplikator unseres Charakters erhöhen springt er schneller und der Charakter fühlt sich schwerer den Schwerkraftmultiplikator verringern , fühlen sie sich leichter und Als Nächstes können wir die Kontrolle des Spielers über den Charakter verringern , indem wir mehr Multiplikatoren verwenden, allgemein als Luftsteuerung und Luftbremsen bezeichnet Luftregelung wird verwendet, wenn der Spieler in der Luft Bewegungseingaben gibt und Luftbremsen wenn er in der Luft keinen Bewegungseinfluss gibt. Ich setze beide Werte auf 0,5, was bedeutet, dass die Beschleunigung und Verzögerung des Charakters halbiert werden Im weiteren Verlauf des physikalischen Prozesses können wir alles, was passiert, besser organisieren, indem wir es in verschiedene Funktionen unterteilen: eine Funktion, die nur aufgerufen wird, wenn der Charakter auf dem Boden befindet, und eine, wenn sie nicht auf dem Boden ist Wir werden den Wert von Delta an beide Funktionen weitergeben. eine separate Bodenphysik-Funktion definieren, können wir uns jetzt darauf konzentrieren, nur die entsprechende Physik anzuwenden die entsprechende Physik , wenn sich der Charakter am Boden befindet. Erstellen Sie dann eine weitere Funktion für die Luftphysik und verwenden Sie diese Funktion, um den Charakter anders zu steuern , als wenn er sich am Boden befindet. Hier werden wir die Schwerkraft anwenden. Kopiere dann auch die Steuerung für den Charakter sich bewegt und nicht bewegt, aus der Bodenphysik. Umdrehen ist in der Luft weniger wichtig da es keinen Boden gibt, der für Reibung sorgt Es wäre also nicht sinnvoll, sich schneller umzudrehen Wir müssen lediglich die natürliche Beschleunigung des Charakters mit dem Multiplikator für die Luftregelung und seine Verzögerung mit dem Multiplikator für die Druckluftbremsen multiplizieren Eine andere Methode besteht darin, dass Sie die Luftregelung und die Druckluftbremsen als alternative Werte betrachten könnten , die Beschleunigung und Verzögerung ersetzen, anstatt sie als Multiplikatoren zu , die Beschleunigung und Verzögerung ersetzen, anstatt Vielleicht möchtest du auch erwägen, eine Endgeschwindigkeit hinzuzufügen, je nachdem, wie stark der Charakter auf langen Strecken fallen wird und ob der Spieler in solchen Situationen eine bessere Kontrolle haben muss Eine Endgeschwindigkeit ist die maximale Geschwindigkeit, mit der sich ein Objekt durch die Luft bewegen kann, da die Luftwiderstandskraft irgendwann der Schwerkraft entspricht und sich gegenseitig ausgleicht. Da wir noch keine richtige Umgebung haben , um das zu testen, können wir nur die Sprunghöhe des Charakters auf einen sehr hohen Wert einstellen , vielleicht sogar die Kamera herauszoomen, damit wir weiter oben sehen können. Aber wir können sehen, dass sich der Charakter sehr schnell bewegt, wenn er großen Entfernungen folgt, und es ist für den Spieler sehr schwierig , es mit Genauigkeit zu kontrollieren. Lassen Sie uns also eine weitere Variable für unsere Endgeschwindigkeit exportieren . In der Erdatmosphäre erreicht ein Mensch beim Fallschirmspringen eine Endgeschwindigkeit von etwa 54 Metern/Sekunde Wenn 100 Pixel 1 Meter sind, dann sind das 5.400 Pixel pro Um diesen Grenzwert in der Luftphysik-Funktion anzuwenden, können wir einfach die Min-Funktion verwenden, um entweder die aktuelle Y-Geschwindigkeit des Zeichens oder die Endgeschwindigkeit zurückzugeben entweder die aktuelle Y-Geschwindigkeit des Zeichens oder die Endgeschwindigkeit , je nachdem, welcher Wert niedriger ist Weisen Sie dann den zurückgegebenen Wert der Y-Geschwindigkeit des Zeichens zu Jetzt können wir einfach einschränken, wie schnell der Charakter im Inspektor fallen darf , sodass der Spieler mehr Kontrolle wenn er langen Strecken folgt. Ich setze meinen vorerst auf 4.096. Ich sehe dich im nächsten Video. 13. 1-6 Laufen: Hallo Freunde. In diesem Video fügen wir eine Run-Taste hinzu , die der Spieler gedrückt halten kann, um seine Bewegungsgeschwindigkeit zu ändern. Zuerst setze ich den Zoom der Kamera und positioniere sie dort, wo sie vorher war. Die Bewegungsgeschwindigkeit des Charakters beim Spielen mit der Tastatur ist immer gleich, aber wir können die Bewegungsgeschwindigkeit anpassen indem wir den Analogstick nur teilweise neigen In manchen Spielen reicht das aus, damit der Spieler entweder laufen oder rennen In anderen gibt es jedoch eine spezielle Run-Taste die der Spieler gedrückt halten kann, um schneller voranzukommen. die Projekteinstellungen öffnen, können wir unserer Eingabe-Map eine Run-Schaltfläche hinzufügen. Ich verwende die Umschalttaste oder die rechte Taste auf meinem Controller. Im Player-Skript verwenden wir dieselben Funktionen wie beim Sprung, um zu überprüfen, ob die Run-Taste gedrückt oder losgelassen wurde. Wenn die Run-Taste gedrückt wird, können wir dem Charakter sagen, dass er rennen soll, und wenn wir ihn loslassen, können wir ihm sagen, dass er laufen soll. Wenn wir schon hier sind, können wir mit der Warnung umgehen, dass die Prozessfunktion den Wert von Delta nicht wirklich verwendet. Um eine bestehende Funktion zu überschreiben, müssen die Parameter exakt übereinstimmen, sodass wir Delta nicht vollständig entfernen können. Stattdessen würde es die Godot-Engine vorziehen, dass wir diesen Parameter als unbenutzt markieren diesen Parameter als unbenutzt indem wir seinem Namen einen Unterstrich voranstellen Alternativ können wir das Warnfenster öffnen und auf Ignorieren klicken, um der Engine mitzuteilen, dass sie diese Warnung ignorieren soll Jetzt benötigt das Zeichenskript diese öffentlichen Funktionen: Run und Walk. Wir beginnen damit, zwei weitere exportierte Variablen in der Kategorie Fortbewegung hinzuzufügen , eine Gehgeschwindigkeit und eine Laufgeschwindigkeit Anschließend kann der Tag der Bewegungsgeschwindigkeit von Export auf Bereit geändert und der Wert standardmäßig der Gehgeschwindigkeit zugewiesen den Funktionen Gehen und Laufen eine Deklaration geben , keine Parameter akzeptieren und keine Werte zurückgeben, müssen wir nur den Wert der Bewegungsgeschwindigkeit auf Laufgeschwindigkeit oder Gehgeschwindigkeit setzen . Dann erledigt der physikalische Prozess den Rest indem er den aktuellen Wert der Bewegungsgeschwindigkeit verwendet. Das ist alles, was Sie brauchen, um die Bewegungsgeschwindigkeit unseres Charakters zu ändern , während Sie eine Taste gedrückt halten. Wir könnten dies leicht rückgängig machen sodass der Charakter standardmäßig läuft, aber beim Gehen eine Taste gedrückt halten, indem wir einfach den Standardwert für die Bewegungsgeschwindigkeit auf Laufgeschwindigkeit ändern und das Spielerskript die entgegengesetzten Funktionen aufrufen lassen. Da diese Lektion so kurz war, bereite ich mich auch auf das nächste Video vor, indem ich einen Block hinzufüge dem der Charakter mithilfe eines statischen Körperknotens abspringen kann. A Wir sehen uns im nächsten Video. 14. 1-7 Kojote: Hallo Freunde. In diesem Video helfen wir dem Spieler, indem wir Funktionen zur Barrierefreiheit hinzufügen , die es unserem Charakter leichter machen , ihn zu kontrollieren Ich setze zunächst die Sprunghöhe des Charakters wieder auf einen vernünftigen Wert zurück In den meisten D-Plattformspielen ermöglicht das Spiel dem Spieler, für kurze Zeit die Sprungtaste zu drücken , nachdem sein Charakter von einem Felsvorsprung gegangen ist und auch, wenn er fällt und fast landet In beiden Fällen die Funktion ist auf dem Boden den Wert false zurück, aber es würde dem Spieler ein besseres Gefühl geben, wenn er trotzdem einen Sprung ausführen darf Um diese Funktionen hinzuzufügen, ändern wir zunächst den Rückgabetyp der Sprungfunktion von „ Nichts“ in einen booleschen Wir geben also true zurück, wenn der Sprung erfolgreich war, oder false, wenn er es nicht war Auf diese Weise kann das Spielerskript darauf reagieren, dass die Sprungtaste zu früh gedrückt wird , und den Sprung erneut versuchen , nachdem der Charakter auf dem Boden gelandet zum Spielerskript wechseln, des Charakters reagieren, anstatt nur die Punktsprungfunktion des Charakters aufzurufen können wir auf den Rückgabewert des Charakters reagieren, anstatt nur die Punktsprungfunktion des Charakters aufzurufen, indem wir ihn in eine if-Anweisung einfügen Wenn Jump den Wert true zurückgibt, müssen wir nichts tun, aber wenn es falsch zurückgibt, können wir davon ausgehen, dass der Spieler springen möchte, wenn es möglich wird, falls das relativ bald passiert. Wenn also nicht jump, wenn jump falsch zurückgegeben hat, dann werden wir diese Sprungeingabe für ein kurzes Zeitfenster zwischenspeichern . Der einfachste Weg, die Zeit im Auge zu behalten , ist die Verwendung eines Timer-Knotens. Wir können ihn als untergeordnetes Element des Player-Knotens hinzufügen, oder da der Player-Knoten keinen bestimmten Typ hat, für den wir ihn verwenden, können wir seinen Typ so ändern, dass er der Timer selbst ist. Wenn wir uns seine Eigenschaften im Inspektor ansehen, können wir festlegen, wie lang der Timer sein soll, also das Zeitfenster dem die Eingabe zwischengespeichert wird , und seine One-Shot-Eigenschaft auf true setzen Das bedeutet, dass der Timer, wenn er einmal gestartet ist, nur bis zum 01 Mal herunterzählt Das Standardverhalten wäre, wiederholt bis Null herunterzuzählen. Als Nächstes deklarieren wir eine neue Variable. Wir nennen sie gepufferte Eingabe vom Typ Callable. Callable ist eine Klasse, die einen Funktionsaufruf mit Argumenten enthält . Wenn unser Sprung also fehlschlägt, möchten wir unsere gepufferte Eingabe auf einen Zeichen-Punktsprung ohne Klammern setzen , da wir die Funktion jetzt nicht aufrufen, sondern sie in einer Variablen speichern Und starte auch den Timer. Da wir den Typ dieses Knotens in einen Timer geändert haben, müssen wir den Typ des Knotens, den dieses Skript am Anfang des Skripts erweitert, ändern Knotens, den dieses Skript am Anfang des Skripts erweitert , um auf Funktionen der Timer-Klasse zugreifen zu können . dann in der Prozessfunktion Wenn dann in der Prozessfunktion dieser Timer läuft nicht gestoppt ist, rufen Sie die gepufferte Eingabe Wenn die gepufferte Eingabe den Wert true zurückgibt, war sie erfolgreich und wir können die Zeit anhalten Wenn die gepufferte Eingabe falsch zurückgegeben hat, kann dies in diesem Frame noch nicht geschehen, und wir werden es im nächsten Frame erneut versuchen bis der Timer abgelaufen ist oder der Vorgang erfolgreich ist Zu Testzwecken verwenden wir auch einige Print-Anweisungen, um auszudrucken wann der Sprung gepuffert ist, wann die gepufferte Eingabe fehlschlägt und Wenn wir das Spiel starten und die Sprungtaste früh drücken, wird die Sprungeingabe zwischengespeichert Es schlägt ein paar Mal dann erfolgreich, wenn der Charakter auf den Boden Wenn wir die Sprungtaste drücken während sich der Charakter weit oben in der Luft befindet, wird die Eingabe gepuffert, aber sie schlägt fehl, bis der Timer abgelaufen ist , und ist nie Sobald wir mit der Leistung unserer Eingabepufferung zufrieden sind , können wir diese Druckanweisungen entfernen oder auskommentieren Als Nächstes wollen wir dem Charakter ermöglichen, zu springen, wenn er kürzlich von einem Felsvorsprung heruntergelaufen wird allgemein als Coyote Time bezeichnet und bezieht sich dabei auf Wiley Coyote bezieht sich dabei auf In der Charakterszene können wir einen Timer-Knoten hinzufügen und ihn in Coyote umbenennen Wie beim Eingangspuffer-Timer wird es sich um einen One-Shot-Timer handeln, und wir können die Dauer des Timers anpassen die Charakterszene im Charakterskript geöffnet ist, können wir einen Verweis auf einen beliebigen untergeordneten Knoten abrufen indem wir die Strg- oder Befehlstaste gedrückt halten, dann auf den Knoten klicken und ihn in das Skript ziehen Dadurch wird automatisch eine Variable mit demselben Namen erstellt und ihr Wert mithilfe des Tags on ready festgelegt . Dabei wird die Notation des Knotenpfads verwendet, die mit dem 1$-Zeichen beginnen Verwendung dieser Notation im Dollarzeichen setzt voraus, dass dieser Knoten mit dem exakten Knotenpfad relativ zu dem Knoten existieren muss mit dem exakten Knotenpfad relativ zu dem Knoten existieren , an den dieses Skript angehängt ist. Andernfalls wird ein Fehler verursacht. Diese Kojotenzeit ist jedoch eine Funktion, die im Allgemeinen nur für den Spielercharakter gilt Möglicherweise möchten wir diesen Knoten nicht in jeder Charakterszene haben in jeder Charakterszene Wir können also die Funktion get node or null verwenden , die denselben Knotenpfad als String-Argument weitergibt. Diese Funktion gibt entweder einen Verweis auf den Knoten zurück, der diesem Knotenpfad folgt , oder null, wenn er nicht existiert, ohne Fehler zu verursachen. In der Sprungfunktion überprüfen wir nun, ob ein Sprung möglich ist , entweder ob sich der Charakter auf dem Boden befindet oder ob der Charakter einen Kojoten-Timer hat und der Kojoten-Timer nicht gestoppt ist Boden befindet oder ob der Charakter einen Kojoten-Timer hat und der Kojoten-Timer Bei Logikoperationen und wird vor oder sofern du keine Klammern verwendest , ausgewertet In Bezug auf die A-Anweisung wird die linke Seite vor der rechten Seite geprüft. Wenn also der Coyote-Timer nicht existiert, wird die A-Aussage als falsch angesehen Es wird also nicht geprüft, ob der Coyote-Timer auf der rechten Seite läuft oder nicht Coyote-Timer auf der rechten Seite läuft Jetzt müssen wir nur noch den Coyote-Timer starten. Dazu müssen wir wissen, wann der Charakter einen Felsvorsprung verlässt Ich betrachte das als Teil der Kategorie Springen, und wir werden zwei neue Variablen deklarieren Ist auf Floor, um den Rückgabewert der Funktion I on floor für diesen Frame zu speichern den Rückgabewert der . diese Weise können wir diese Prüfung einmal pro Frame durchführen und die Ergebnisse speichern , sodass wir sie mehrmals verwenden können , sodass wir sie mehrmals verwenden können. Dadurch müssen wir die Funktion nicht mehrmals pro Frame aufrufen und war auf Floor, was den Wert von is on floor aus dem vorherigen Frame enthält. Während des physikalischen Prozesses setzen wir den Wert von was on floor auf is on floor dann is on floor auf den von der Funktion is on floor zurückgegebenen Wert. Alle anderen Aufrufe der Funktion is on floor können stattdessen unsere Variable verwenden , um effizienter zu sein. Wenn die Figur dann im vorherigen Bild auf dem Boden war und sich nicht auf dem Boden dieses Frames befindet und ihre Y-Geschwindigkeit größer oder gleich Null ist, was bedeutet, dass sie nicht gesprungen ist, ist die einzig logische Schlussfolgerung, dass diese Figur von einem Felsvorsprung die einzig logische Schlussfolgerung gegangen ist oder Boden, auf dem sie stand, verschwunden ist, und das ist genau der Moment wann der Coyote-Timer starten sollte. Zu Testzwecken fügen wir Print-Anweisungen hinzu, damit wir wissen, wann der Coyote-Timer startet und wann ein Coyote-Sprung ein Coyote-Sprung Dazu ist eine redundante if-Anweisung erforderlich, wir jedoch später entfernen werden Okay. Ich lasse das Spiel laufen, um es zu testen. Wir können von einem Felsvorsprung heruntergehen und sehen, dass der Coyote-Timer Wenn wir die Sprungtaste drücken während der Coyote-Timer läuft, darf der Charakter trotzdem einen Sprung Wir haben jetzt eine solide Toti-Plattform und Im nächsten Abschnitt werden wir den Charakter zeichnen und animieren Wir sehen uns im nächsten Abschnitt. 15. 2-1 Sprite: Hallo Freunde. In diesem Abschnitt nehmen wir unser einfaches Gadot-Symbol und polieren es zu einem vollständig animierten Charakter Dafür benötigen wir Assets, Bilder und Audiodateien Die Dateien, die ich verwende sind enthalten, wenn du sie verwenden möchtest, aber ich empfehle fortgeschrittenen Schülern deine eigenen oder andere kostenlose Dateien zu verwenden. Bevor wir mit dem Import von Assets beginnen, ist es eine gute Idee, einen separaten Ordner für sie zu erstellen . Wir können auch verschiedene Unterordner für verschiedene Arten von Assets wie Spritesheets und Soundeffekte erstellen verschiedene Arten von Assets wie Spritesheets und Soundeffekte Klicken Sie auf den Ordner in dem sich Ihre importierten Assets befinden sollen, klicken Sie dann einfach auf die Assets und ziehen Sie sie in das Gadot-Fenster Der Importvorgang erfolgt automatisch und sie werden in den ausgewählten Ordner sortiert Wenn sie sich nicht im richtigen Ordner befinden, können Sie sie jederzeit in die Registerkarte Dateisystem ziehen , um sie ebenfalls neu zu organisieren Dadurch wird jedoch ein erneuter Import ausgelöst. Daher ist es besser, sie zunächst in den richtigen Ordner zu importieren , insbesondere bei größeren Dateien Öffne deine Charakterszene , falls sie nicht schon geöffnet ist. Diese Elemente zum Zeichnen der Figur zu verwenden , könnte so einfach sein wie das Ersetzen des Gadot-Symbols durch Ihre importierte Bilddatei wenn Ihre Assets nur ein Sprite pro Datei haben Die von mir verwendeten Elemente sind in einem Spritesheet organisiert, sodass es mehrere Sprites in einer einzigen Textur gibt, was ich nicht zeichnen Mithilfe der Dropdownliste können wir andere Arten von Texturen auswählen, und die für die Verwendung eines Spritesheets wird Atlas-Textur genannt auf die Atlas-Textur klicken, um sie zu erweitern können wir sie direkt hier im Inspektor bearbeiten Das Spritesheet als Atlas zuweisen. Wir können dann die Region des Atlas bearbeiten, die anhand der Atlas-Textur gezeichnet wird Wenn wir einen Bereich des Spritesheets auswählen, den wir verwenden möchten, können wir die Auto-Slice-Funktion verwenden, um ein einzelnes Sprite oder ein einzelnes Pixel auszuwählen ein einzelnes Sprite oder ein einzelnes Pixel , um auf einen bestimmten Bereich zu klicken und ihn zu ziehen Da diese Sprites alle gleichmäßig groß und gleichmäßig verteilt sind, verwende ich diesen Bereich mit 32 mal 36 Pixeln Wenn Sie das Sprite ändern, sich Breite und Höhe Nur die X- und Y-Position werden um einheitliche Werte erhöht Das macht es viel einfacher , den Charakter zu animieren. Bevor Sie sich dazu entscheiden, eine Reihe von Elementen zum Animieren einer Figur zu verwenden , kann es sich lohnen, Ihr Spritesheet so zu bearbeiten, dass dieser gleichmäßige Abstand eingehalten wird, um Zeit und Mühe zu sparen Ich bewege das Sprite nach unten, sodass es auf der X-Achse liegt. Seine Y-Position entspricht jetzt der Hälfte der Höhe der Sprite-Region. Da wir nun eine genaue visuelle Darstellung unseres Charakters haben , können wir die Kollisionsform besser anpassen Wir können die untergeordneten Knoten neu anordnen, um die Kollisionsform über dem Charakter-Sprite zu zeichnen die Kollisionsform über dem , um die Sache zu vereinfachen Ich verwende eine Kapselform und mache sie groß genug um den Kopf, aber nicht die Ohren und den Körper einzuschließen, aber nicht unbedingt die Arme, den Schwanz oder Dies wird verwendet, um mit der Umgebung zu kollidieren, sodass alles, was sich außerhalb der Kollisionsform mit den Wänden, der Decke oder dem Boden überlappt Achte darauf, dass deine Kollisionsform und dein Sprite um die Y-Achse zentriert bleiben und bequem auf der X-Achse sitzen , als wäre es der Boden Wenn sich die Größe deines Charakters erheblich ändert, wirst du wahrscheinlich die Werte seiner Variablen für Dinge wie Bewegungsgeschwindigkeit und Sprunghöhe ändern seiner Variablen für Dinge wie Bewegungsgeschwindigkeit und Sprunghöhe Wir können auch mathematische Gleichungen in diese Felder eingeben , und die Engine bestimmt das Ergebnis für uns. Aber ich ordne die Kollisionsform so an, dass sie sich wieder hinter dem Sprite Wenn das Zeichen auf der Y-Achse zentriert ist, links oder rechts müssen wir lediglich den Wert der Variablen „Horizontal umkehren“ im Sprite-Two-D-Knoten ändern, damit der Charakter nach Variablen „Horizontal umkehren“ im Sprite-Two-D-Knoten ändern, damit der zum Zeichenskript wechseln, nehmen wir einen Verweis auf den Sprite-Two-D-Knoten und speichern ihn in einer Variablen, indem wir die Strg- oder Befehlstaste gedrückt halten und ihn in das Skript ziehen Dann deklarieren wir eine öffentliche Funktion namens face left, keine Parameter akzeptiert und keinen Wert zurückgibt Die aktuelle Absicht besteht zwar darin, diese Funktion nur privat in diesem Skript zu verwenden, Sie können sich wahrscheinlich vorstellen, dass es in einem öffentlichen Kontext nützlich sein könnte , einem Charakter zu sagen , dass er in eine Richtung schauen soll. Um nach links zu schauen, müssen wir lediglich den Wert der Eigenschaft Flip H des Sprites auf true Wir könnten auch eine andere Funktion namens face right schreiben, aber die Funktion würde nur den Wert dieser Variablen wieder auf False setzen den Wert dieser Variablen wieder auf False Manchmal ist es einfacher, unsere Funktionen zu schreiben , um flexibler zu sein. Anstatt sowohl die Funktionen „Gesicht links“ als auch „Gesicht nach rechts“ zu verwenden, können wir der Funktion „Gesicht links“ einen Parameter geben , mit dem sie beide Funktionen ausführen kann. Ich nenne sie einfach left und gebe ihr den Standardwert true. Wenn Sie einem Parameter einen Standardwert geben, ist er optional. Diese Funktion mit dem Namen face left kann also ohne Angabe von Argumenten aufgerufen werden, und wir gehen davon aus, dass sie nach links zeigen wollen. Wir können dann den Wert von flip H auf den Wert von left setzen. Damit das Zeichen nach rechts zeigt, müssen wir nur face left aufrufen, aber false als Argument angeben , anstatt eine völlig andere Funktion aufzurufen. die Richtung eines Charakters in der Physik Wenn die Richtung eines Charakters in der Physik negativ ist, möchte er nach links schauen. Und wenn es positiv ist, dann wollen sie nach links schauen, nicht nach links, sondern nach rechts. Wenn die Richtung Null ist, sie weiterhin in dieselbe Richtung wie im vorherigen Bild. Um meinen kleinen Charakter besser sehen zu können, zoome ich die Kamera um den Faktor vier und positioniere sie neu, sodass sich der Boden am unteren Bildschirmrand befindet O. Wenn wir auf „Abspielen“ klicken, wird der Charakter gezeichnet und sein Sprite wird umgedreht, sodass er in die richtige Richtung zeigt, aber er wird immer noch nicht animiert Ich möchte, dass mein Charakter schneller ist, also werde ich seine Werte in der Charakterszene erhöhen Werte in der Charakterszene Wir sehen uns im nächsten Video. 16. 2-2 Animations-Player: Hallo Freunde. In diesem Video werden wir unserem Charakter Animationen hinzufügen. Wenn dein Charakter keinen Animations-Player-Knoten hat, solltest du jetzt einen hinzufügen. Wenn der Animations-Player-Knoten ausgewählt ist, sollte der Animations-Tab automatisch erweitert werden. Wenn sie nicht geöffnet ist, können Sie sie öffnen , indem Sie auf die Animationsschaltfläche klicken. Das Animationsfenster ist derzeit leer, da noch keine Animationen vorhanden sind. auf die Schaltfläche Animation klicken, wählen wir Neu aus, um eine neue Animation zu erstellen und sie als inaktiv zu bezeichnen. Wenn eine Animation ausgewählt ist, gibt es jetzt eine Zeitleiste, die in Sekunden gemessen wird. Wenn Sie möchten, können Sie die Sekunden in Bilder pro Sekunde ändern die Sekunden in Bilder pro Sekunde Die Zeitleiste wird dann stattdessen in Bildern angezeigt. die Frames sehr nahe beieinander liegen, Da die Frames sehr nahe beieinander liegen, zoome ich heran, um die Frames weiter voneinander entfernt anzuzeigen . Wir können auch die Bildrate ändern. Ich stelle meins auf 12 Bilder pro Sekunde ein. Es ist auch hilfreich, mit diesem Schalter das Einrasten auf den Timeline-Cursor anzuwenden mit diesem Schalter das Einrasten auf den Timeline-Cursor Wenn wir jetzt durch die Animationszeitleiste blättern, wird sie automatisch auf das nächste Bild ausgerichtet In diesem Bereich können wir der Animation Spuren hinzufügen, indem wir auf die Plus-Schaltfläche klicken Am gebräuchlichsten ist ein Eigenschaften-Track, mit dem wir jede Eigenschaft eines beliebigen Knotens im Szenenbaum im Laufe der Zeit bearbeiten können . Der Knoten, den wir animieren wollen, ist der Sprite-Ti-Knoten, genauer gesagt seine Textureigenschaft Dadurch wird der Animations-Timeline eine Spur hinzugefügt , und auf dieser Spur können wir Keyframes hinzufügen, um der Eigenschaft zu diesem Zeitpunkt einen neuen Wert zuzuweisen der rechten Maustaste auf die Spur klicken, können wir Key einfügen auswählen, um dieser Spur einen Keyframe hinzuzufügen Standardmäßig entspricht der Wert dieses Keyframes dem aktuellen Wert. Dies ist dieselbe Textur, auf die wir ihn im vorherigen Video eingestellt haben Das ist gut genug für einzelne Sprite-Dateien, da wir hier einfach die Textur ändern können Aber da ich ein Spritesheet verwende, möchte ich die Textur eigentlich nicht ändern Ich möchte nur den Bereich der Textur ändern , der verwendet wird Es gibt mehrere Möglichkeiten, dies zu tun. Eine Möglichkeit besteht darin, auf die Eigenschaftenspur zu klicken und ihren Eigenschaftsnamen zu bearbeiten, indem Sie einen Doppelpunkt und das Wort Region nach der Textur hinzufügen. Dadurch wird der Animation mitgeteilt , dass ich die Bereichseigenschaft der Textur bearbeiten möchte , nicht die Textur selbst. Ich setze die Animation zurück, sodass sie vorerst leer ist. Stellen Sie sicher, dass der Animation-Player-Knoten in der Szenenstruktur ausgewählt ist, und wählen Sie dann den Sprite Two D-Knoten die Atlas-Textureigenschaft erweitern, können wir ihre Eigenschaften in einem verschachtelten Fenster sehen mit der Maus über den Eigenschaftsnamen der Region fahren, wird im Popup-Fenster der Name der Immobilie angezeigt Dies ist hilfreich, um sicherzustellen, dass Sie die genaue Groß- und Kleinschreibung und Schreibweise kennen , wenn Sie versuchen, über den Code oder den Namen des Animationstracks darauf zuzugreifen, wie wir es gerade getan haben Die zweite Methode zum Hinzufügen von Eigenschaftstracks zu einer Animation, die viel einfacher ist, besteht jedoch Eigenschaftstracks zu einer Animation, darin die Tastentaste rechts neben der Eigenschaft zu verwenden. Diese Schaltfläche ist nur verfügbar, wenn der Animation-Player-Knoten zuvor in der Szenenstruktur ausgewählt wurde . Eine Animation ist gerade geöffnet, und dann wird ein anderer Knoten in der Szenenstruktur ausgewählt. Wenn Sie auf diese Schaltfläche klicken, wird der aktuellen Animation an der Position des Timeline-Cursors ein Keyframe hinzugefügt der aktuellen Animation an der Position des Timeline-Cursors wir zum ersten Mal einen Keyframe für eine Eigenschaft hinzufügen , für die es derzeit keine Spur in der Animation gibt, fragt uns Godot, ob wir dafür eine Spur erstellen möchten Und wenn wir diesen Track zur Reset-Animation hinzufügen wollen , werden wir zu beiden Ja sagen Dadurch wird der Track zur Animation hinzugefügt und gleichzeitig der erste Keyframe Wenn Sie auf den Namen der inaktiven Animation klicken , um das Drop-down-Menü zu erweitern, wird auch die Reset-Animation erstellt Weise speichert GoDo die Standardwerte der Eigenschaften Auf diese Weise können Probleme beim Ausführen von Animationen im Editor und beim dauerhaften unbeabsichtigten Ändern der Eigenschaftswerte vermieden beim Ausführen von Animationen im Editor und beim dauerhaften unbeabsichtigten Ändern der Eigenschaftswerte Godot setzt alle Eigenschaften auf die in dieser Reset-Animation angegebenen Standardwerte zurück die in dieser Reset-Animation angegebenen Standardwerte Um dies reibungsloser zu gestalten, versuchen Sie, Animationen immer Eigenschaftenspuren hinzuzufügen , wenn sie sich in ihrem Standardstatus befinden Jetzt sind wir bereit, den eigentlichen Animationsprozess zu starten. Sie sollten entweder eine Texturspur zum Ändern einzelner Sprites oder eine Texturbereichsspur zum Ändern von Sprites innerhalb eines Spritesheets Ihre Assets können auch unterschiedliche Spritesheets für unterschiedliche Animationen verwenden unterschiedliche Spritesheets für unterschiedliche diesem Fall benötigen Sie außerdem einen Track sowohl für die Atlas-Textur als auch für den Texturbereich Alles, was wir tun müssen, ist, in der Timeline einen Frame vorwärts zu scrubben , dann entweder den Wert der Textur oder des Texturbereichs zu bearbeiten und auf die Tastentaste zu klicken , um einen weiteren Keyframe hinzuzufügen und Da ich weiß, dass alle meine Sprites dieselbe Größe und gleichmäßige Abstände haben, kann ich das noch einfacher machen, indem ich einfach neue Keyframes einfüge, als die X-Eigenschaft manuell zu bearbeiten und sie für jedes Bild zu erhöhen Wenn wir diese Animation testen, die Engine davon aus, dass wir die Werte dieser Eigenschaften zwischen den Keyframes verknüpfen möchten Werte dieser Eigenschaften zwischen den Keyframes verknüpfen Da die Bildrate des gesamten Spiels 60 Bilder pro Sekunde beträgt, beträgt diese Animation jedoch 12 Bilder pro Sekunde Die Engine erzeugt vier zusätzliche Frames zwischen jedem Keyframe, um einen reibungsloseren Übergang zu erzielen Offensichtlich ist das nicht das, was wir bei einer Sprite-Animation wollen, also müssen wir den Aktualisierungsmodus für diesen Track von kontinuierlich auf diskret umstellen diesen Track von kontinuierlich Jetzt ändert sich die Eigenschaft nur, wenn die Animation ein Keyframe trifft, und der Wert wird sofort geändert Die Animation ist zu lang, daher müssen wir die Anzahl der Frames der Animation so einstellen , dass sie nach dem letzten Keyframe endet Diese Animation muss ebenfalls wiederholt werden. Klicken Sie also auf die Schaltfläche für die Animationsschleife Klicken Sie also auf die Schaltfläche für die Animationsschleife , sodass das Looping-Symbol blau ist Wenn du noch einmal darauf klickst, wird es auf Ping Pong gesetzt, was eine andere Art von Looping ist Bei Charakteranimationen wollen wir generell Vorwärtsschleifen Es ist eine gute Idee, die zurückgesetzten Animationsspuren auch auf diskret zu setzen, falls Sie damit einen Charakter per Skript zurücksetzen möchten damit einen Charakter per Skript zurücksetzen Diese inaktive Animation ist jetzt abgeschlossen, und wir können mit der Erstellung der restlichen Animationen fortfahren , die wir für unsere Plattform und unseren Charakter benötigen. auf die Animationsschaltfläche klicken, können wir eine neue Animation hinzufügen und von vorne beginnen, oder wir können diese inaktive Animation duplizieren und als Vorlage verwenden. Da ich weiß, dass meine Sprites gleichmäßig verteilt sind, muss ich nur die Y-Eigenschaften meiner Keyframes bearbeiten, um von Idle- zu Walk-Frames zu wechseln Wir können Schlüssel kopieren und einfügen, um die Arbeit zu vereinfachen. Eine Linie, die zwei Schlüssel verbindet , bedeutet, dass sich die Werte zwischen ihnen nicht ändern. Wenn ich die laufende Animation mache, verdoppele ich einfach die Bildrate. Wir können Tasten anklicken und ziehen , um sie entlang der Timeline zu bewegen. Ich muss auch springende und fallende Animationen erstellen. Je nachdem, welche Elemente Sie verwenden, müssen Sie möglicherweise unterschiedliche Animationen erstellen. Möglicherweise benötigen Sie beispielsweise Animationen für Starthilfen, Idle-Jump, Fall-Idle-Animationen oder Landing-Animationen. Stellen Sie sicher, dass Sie wissen , welche Animationen wiederholt werden müssen und welche nicht. Jetzt hat der Charakter alle Animationen, aber sie stecken in der inaktiven Animation fest. Also müssen wir dem Charakter sagen, wann er zu anderen Animationen wechseln soll. Wir sehen uns im nächsten Video. 17. 2-3 Animationsbaum: Hallo Freunde. In diesem Video steuern wir mithilfe eines Animationsbaums, welche Animation im Animation-Player abgespielt wird . Wenn deine Charakterszene keinen Animationsbaumknoten hat, solltest du jetzt einen hinzufügen. Der Animationsbaum dient dazu, den Animations-Player zu steuern und zu entscheiden, welche Animation zu einem bestimmten Zeitpunkt abgespielt werden soll. also der Animationsbaumknoten Wenn also der Animationsbaumknoten im Szenenbaum im Inspektor ausgewählt ist, setzen wir seine Animations-Player-Eigenschaft auf unseren Animations-Player-Knoten . Die Eigenschaft tree root ist eine Ressource, die verwendet wird, um zu bestimmen, welche Animation vom Animations-Player-Knoten abgespielt wird . auf das Drop-down-Menü klicken, wir auf das Drop-down-Menü klicken, stehen uns hierfür verschiedene Optionen zur Verfügung, von denen die meisten besser geeignet sind wenn Sie drei D - oder Bone-Animationen verwenden, denen häufig mehrere Animationen miteinander kombiniert werden. Da es sich um ein einfaches Zwei-D-Sprite handelt, verwenden wir eine Zustandsmaschine auf unsere neue Zustandsmaschine klicken, öffnen wir den Animationsbaum am unteren Rand des Editorfensters mit einer Zustandsmaschine, die zur Bearbeitung geöffnet Unsere Zustandsmaschine hat derzeit einen Startknoten und einen Endknoten. Diese sind nicht identisch mit den Knoten im Szenenbaum, sondern sind Knoten im Kontext eines Knotengraphen. Wir können in einen leeren Bereich klicken, um weitere Knoten hinzuzufügen. Fügen wir die inaktive Animation als Knoten hinzu. Wir können auf diese Knoten klicken und sie verschieben , um sie nach Belieben zu organisieren. Ihre Positionen in diesem Raum sind irrelevant. Wenn wir unseren Bearbeitungsmodus von auswählen und verschieben, um Knoten miteinander zu verbinden, können wir durch Klicken und Ziehen von einem Knoten zum anderen wechseln, wodurch ein Pfeil entsteht, der sie in einer Richtung verbindet. Dies ist ein Übergang vom Startknoten zum inaktiven Knoten. Wenn also die Zustandsmaschine gestartet wird, wechselt sie sofort zum inaktiven Knoten, wodurch der Animationsspieler angewiesen die inaktive Animation abzuspielen. den Bearbeitungsmodus zurückschalten, um Knoten auszuwählen und zu verschieben, fügen wir nun auch die Walk- und Run-Animationen hinzu. Und wenn Sie wieder zum Verbinden von Knoten zurückkehren, schaffen Sie einen Übergang von Idle zu Walking und Walking to Run. Wenn diese Zustandsmaschine gestartet wird, geht sie sofort vom Startknoten zum Run-Knoten über. Deshalb möchten wir diesen Übergängen Bedingungen hinzufügen , um einzuschränken , wann dieser Übergang stattfinden darf. Wenn Sie den Übergang von Idle zu Walk auswählen, erweitern Sie den Bereich „Weiter“. Unter dem erweiterten Ausdruck befindet sich ein Textbereich. Hier können wir einen beliebigen logischen Ausdruck angeben, mit dem wir steuern möchten, wann dieser Übergang stattfinden darf, solange das Ergebnis ein boolescher Wert, wahr oder falsch ist solange das Ergebnis ein boolescher Wert, wahr oder falsch In diesem Fall wollen wir die Walk-Animation abspielen, wenn die X-Geschwindigkeit der Figur etwas anderes als Null ist Das ermöglicht also das Gehen sowohl nach links als auch nach rechts. Dieser Ausdruck wird auf dem Knoten geprüft, den wir in den Eigenschaften des Animationsbaumknotens, dem Basisknoten für erweiterte Ausdrücke, angeben . diesen Knoten als Wurzelknoten der Szene festlegen, also D-Node für den Körper der Figur, können wir die Animationszustandsmaschine automatisch auf die Geschwindigkeit der Figur reagieren automatisch auf die Geschwindigkeit der Figur , um die Animation zu ändern. zur Zustandsmaschine zurückkehren vom Gehen zum Laufen wechseln, wollen wir überprüfen, ob der absolute Wert der X-Geschwindigkeit der Figur größer ist als die Gehgeschwindigkeit der Figur Möglicherweise möchten Sie einen anderen Schwellenwert angeben, indem beispielsweise festlegen, dass der Absolutwert der X-Geschwindigkeit gleich der Laufgeschwindigkeit oder höher als der Durchschnitt der Geh- und Laufgeschwindigkeit usw. sein muss Laufgeschwindigkeit oder höher als . Jetzt müssen wir einen Übergang vom Gehen zurück zum Leerlauf hinzufügen. Beim Erstellen von Übergangsschleifen zwischen zwei oder mehr Knoten in einer solchen Zustandsmaschine die Bedingungen aller Übergänge dürfen die Bedingungen aller Übergänge nicht alle gleichzeitig zutreffen. Dies würde es der Zustandsmaschine unmöglich machen , zu entscheiden , welcher Status gerade aktiv sein soll, da sie einfach auf unbestimmte Zeit zwischen den Zuständen hin- und herschalten wird Da die Bedingung für den Übergang von Idle zu Walking darin besteht, dass die X-Geschwindigkeit etwas anderes als Null ist, sollte der Übergang von Walk zu Idle der Fall sein, wenn die X-Geschwindigkeit gleich Null ist Diese beiden Bedingungen können nicht gleichzeitig erfüllt sein, sodass die Zustandsmaschine nicht in einer Schleife zwischen diesen beiden Zuständen stecken bleiben kann Schleife zwischen diesen beiden Zuständen stecken bleiben dieselbe Logik auf den Übergang von Laufen zu Laufen angewendet wird, müssen die Bedingungen für diesen Übergang logisch inkompatibel mit dem Übergang von Gehen zu Laufen Wenn also der absolute Wert der X-Geschwindigkeit des Charakters kleiner oder gleich der Gehgeschwindigkeit des Charakters ist, wird dies niemals gleichzeitig zutreffen wie größer als Wenn wir das Spiel starten, beginnt die Zustandsmaschine am Startknoten und bewegt sich entlang von am Startknoten und bewegt sich Übergängen zwischen verschiedenen Zuständen, jeder Zustand eine oder mehrere Animationen darstellt. In einigen Fällen kann die Zustandsmaschine zum Endknoten übergehen. In diesem Fall funktioniert es nicht mehr. Wenn wir unseren Charakter animieren, wollen wir nie, dass diese Zustandsmaschine den Endknoten erreicht, also gibt es keinen Übergang, der dorthin führt Das funktioniert so, dass die Figur im Leerlauf, beim Gehen und Laufen nach links oder rechts animiert wird, aber wir müssen auch Animationen für das Springen hinzufügen Wenn wir hier die Sprunganimation hinzufügen würden, müssten wir der Sprunganimation Übergänge aus all unseren bestehenden Zuständen hinzufügen , da die Figur aus jedem dieser Zustände springen kann Das wird sich verheddern, chaotisch und schwierig zu handhaben sein, vor allem, wenn dein Charakter mehrere verschiedene Sprunganimationen hat Stattdessen können wir eine verschachtelte Zustandsmaschine erstellen. Wir beginnen damit, unseren aktuellen Zustandsmaschine als Projektressource zu speichern unseren aktuellen Zustandsmaschine als Projektressource Nennen wir es Fortbewegung. Dann ersetze diese Zustandsmaschine durch eine neue. in unserer neuen leeren Zustandsmaschine rechten Maustaste in einen leeren Bereich und wählen Sie Laden aus. Suchen Sie die Locomotion-Zustandsmaschine und fügen Sie sie der neuen Zustandsmaschine als einzelnen Knoten hinzu. Benennen Sie sie um, sodass Sie wissen , dass es die Locomotion-Zustandsmaschine handelt Fügen Sie dann einen Übergang vom Start zur Fortbewegung hinzu. Die gesamte Locomotion-Zustandsmaschine besteht nun einem einzigen Knoten, den wir öffnen können indem wir auf die Schaltfläche Bearbeiten mit einem Bleistiftsymbol Die Idle-Animationen „Walk“ und „ Ausführen“ wechseln immer noch wie zuvor, aber jetzt sind sie in einer größeren Zustandsmaschine verschachtelt Wir können zur anderen Zustandsmaschine zurückkehren, indem wir auf die Semmelbrösel klicken In dieser Zustandsmaschine fügen wir alle Animationen hinzu, die sich auf das Springen beziehen, und verbinden sie mit Übergängen So sieht eine Endlosschleife in einer Zustandsmaschine aus. Wir möchten, dass der Charakter aus einem beliebigen Bewegungszustand wechselt um zu springen, wenn seine Y-Geschwindigkeit kleiner als Null ist, was bedeutet, dass er sich aufwärts bewegt Wenn ihre Y-Geschwindigkeit größer oder gleich Null ist, hat sie den Höhepunkt ihres Sprungs erreicht, und ich wechsle zur Fallanimation Gehen Sie dann vom Fallback zur Fortbewegung über, wenn sich der Charakter auf dem Boden befindet Wir können die Funktion aufrufen oder unsere private Variable verwenden , die wir zuvor erstellt haben Vielleicht möchten wir das Springen überspringen und direkt zum Fallen übergehen , wenn der Charakter von einem Felsvorsprung heruntergeht Fügen wir das also als weiteren Übergang hinzu, vorausgesetzt , dass sich der Charakter nicht mehr auf dem Boden befindet Dadurch entsteht ein Konflikt in unserer Zustandsmaschine, wenn der Charakter in einem Fortbewegungszustand befindet und springt Ihre Geschwindigkeit ist beide kleiner als Null und sie liegen nicht auf dem Boden Welchen Übergang sollte die Zustandsmaschine also verwenden? In Fällen wie diesem können wir unseren Übergängen Vorrang vor anderen einräumen, indem wir ihre Prioritätseigenschaft herabsetzen. Wenn der Charakter springt, ist seine Y-Geschwindigkeit kleiner als Null und er befindet sich nicht auf dem Boden Dem Übergang zum Sprung wird jedoch Priorität eingeräumt. Das ist also der Übergang , der genutzt werden wird. Wenn der Charakter von einem Felsvorsprung heruntergeht, ist seine Geschwindigkeit größer als Null und er befindet sich nicht auf dem Boden, es gibt also keinen Konflikt Unser 2-D-Jump'n'Run-Charakter ist jetzt animiert, aber wir können dafür sorgen, dass er sich viel besser anfühlt , indem wir mehr Feinschliff hinzufügen Wir sehen uns im nächsten Video. 18. 2-4 Soundeffekte: Hallo Freunde. In diesem Video werden wir unserem animierten Charakter Soundeffekte hinzufügen . Dazu müssen wir einige Sounddateien in unser Projekt importieren , sortiert in einen entsprechenden Ordner. Ich werde einige Soundeffekte hinzufügen, mit denen Sie dieser Lektion folgen können, aber ich empfehle Schülern mit fortgeschrittenem ihre eigenen oder kostenlosen Ressourcen zu verwenden. Zuerst werde ich den statischen Körperknoten entfernen, bei dem dieses weiße Rechteck handelt, da ich es nicht mehr verwende. zunächst einen Player Two-D-Knoten für Audiostreams hinzu Player Two-D-Knoten Ihrer Charakterszene zunächst einen Player Two-D-Knoten für Audiostreams hinzu, falls Sie noch keinen haben. Der 2-D-Node des Audio-Stream-Players unterscheidet sich von einem Audio-Stream-Player-Knoten , dass die Lautstärke des Soundeffekts je nach Nähe zum Hörer variiert Der Standard-Listener ist die Kamera. Wir können die Stream-Eigenschaft unseres Audio-Stream-Players mit einem Soundeffekt füllen unseres Audio-Stream-Players mit und auf den Wiedergabe-Schalter klicken, um ihn zu Wenn wir uns die Animationen unseres Charakters ansehen, insbesondere die Sprunganimation, können wir der Animation eine Audiowiedergabe hinzufügen und den Audiostream-Player auswählen, der als Player für diesen Track Audiostream-Player auswählen, der als Player bezeichnet werden soll Wir können dann Soundeffekte mit Keyframes versehen, um sie als Teil dieser Animation abzuspielen, aber das ist mit vielen Einschränkungen verbunden Wenn der Soundeffekt länger als die Animation ist , wird er gekürzt Wenn es sich bei der Animation um eine Endlosschleife handelt, wird sie wiederholt , und mit Soundeffekten wird der Spieler beim Spielen des Spiels wie diesem oft etwas hören beim Spielen des Spiels wie diesem oft Es ist eine gute Idee, etwas Abwechslung und Zufälligkeit hinzuzufügen , damit der Spieler nicht müde wird, es zu hören Lassen Sie uns also diesen Track aus der Animation entfernen und eine andere Methode ausprobieren Da wir den genauen Moment kennen , in dem der Charakter aus dem Drehbuch springt, wäre es einfacher, den Sound auf diese Weise abzuspielen Lassen Sie uns den Audio-Stream-Player in DNodeT Jump umbenennen und eine Referenz abrufen um ihn in einer privaten Variablen zu speichern Wenn der Charakter springt, müssen wir ihm nur sagen, dass er abspielen Wenn man den Soundeffekt aus der Animation heraushält, wird er in seiner Gesamtheit und nur einmal abgespielt Wir können die beiden D-Knoten dieses Audio-Stream-Players duplizieren um weitere Soundeffekte hinzuzufügen , z. B. einen für ein Landegeräusch Im Drehbuch können wir ihn dann genauso abspielen wie den Sprungsound, aber wir haben noch keine praktische Funktion für den Fall, dass der Charakter auf dem Boden landet. Im physikalischen Prozess haben wir eine If-Anweisung, haben wir eine If-Anweisung überprüft, ob der Charakter von einem Felsvorsprung heruntergelaufen ist diese Logik umkehren, können wir überprüfen, ob der Charakter diesen Frame erreicht hat, ob er nicht im letzten Frame auf dem Boden war und sich in diesem Frame auf dem Boden befindet Wir rufen dann eine neue private Funktion auf. Nennen wir es bei Landed. Vorerst muss diese Funktion nur den Lande-Soundeffekt abspielen. Diese Soundeffekte werden abgespielt wenn der Charakter springt und landet, aber sie werden immer dieselben sein, was den Spieler nach einiger Zeit nerven wird Wir können das verbessern, indem wir die Tonhöhe des Sounds bei jeder Wiedergabe leicht zufällig anpassen die Tonhöhe des Sounds bei jeder Wiedergabe Lassen Sie uns also ein Skript an unseren Audio-Stream-Player Two dende anhängen unseren Audio-Stream-Player und es so etwas wie Soundeffekt-Randomizer nennen , ohne eine Vorlage zu verwenden, und es im entsprechenden Ordner speichern Dieses Skript benötigt eine öffentliche Funktion ihm sagt, dass es einen zufälligen Soundeffekt abspielen soll, keine Parameter akzeptiert und keinen Wert zurückgibt Das Endergebnis wird sein, dass die im Audio-Stream-Player definierte Wiedergabefunktion aufgerufen die im Audio-Stream-Player definierte Wiedergabefunktion wird, um die Klasse zu kennzeichnen. Bevor wir den Soundeffekt abspielen, möchten wir jedoch den Wert der Eigenschaft Pitch Scale bearbeiten Mithilfe der integrierten Funktion rand F range können wir eine zufällige Gleitkommazahl zwischen einem von uns angegebenen Minimal- und Maximalwert erzeugen . Da eins die Standard-Tonhöhenskala ist, ordne ich sie nach dem Zufallsprinzip auf einen Wert zwischen 0,5 und 1,5 an, wodurch ein breites Spektrum ähnlicher Sounds erzeugt werden sollte Wir können dasselbe Skript an den anderen Audio-Stream-Player an Dnode anhängen , indem wir auf den Knoten im Szenenbaum klicken und es von der Registerkarte Dateisystem auf den Knoten ziehen im Szenenbaum klicken und es von der Registerkarte Dateisystem auf den Knoten Zurück im Zeichenskript rufen wir, anstatt die Wiedergabefunktion des Audio-Stream-Players für die D-Klassen aufzurufen, stattdessen unsere Play-Zufallsfunktion Das mag ausreichen, um die Monotonie unserer Sprung - und Landegeräusche zu reduzieren , aber während des Spiels werden ständig Schritte zu hören sein Spiels werden ständig Schritte zu hören Vielleicht möchtest du für so etwas mehrere verschiedene Soundeffekte haben für so etwas mehrere verschiedene Soundeffekte und den Audiostream-Player nach dem Zufallsprinzip einen auswählen lassen Lassen Sie uns einen D-Knoten eines AudioStream-Players mit zwei D-Knoten duplizieren , um einen weiteren für Schrittgeräusche zu erstellen, ebenfalls mit demselben Randomizer-Skript, das Im Skript exportieren wir eine Variable, die all die verschiedenen Schrittgeräusche als Array von Audiostreams enthält Dies kann schnell aufgefüllt werden indem eine Gruppe alle Schrittgeräusche im Assets-Ordner auswählt und sie auf das exportierte Array im Inspektor zieht auf das exportierte Array im Wenn wir dann einen zufälligen Soundeffekt abspielen, prüfen wir, ob die Größe dieses Arrays nicht Null ist Wenn das Array nicht leer ist, bedeutet das, dass wir den Wert von stream als zufälliges Element dieses Arrays festlegen sollten stream als zufälliges Element dieses Arrays Zugriff auf ein Mitglied des Arrays mit einer Integer-Indexnummer als zufällige Ganzzahl zwischen Null und der Größe des Arrays minus Eins. Dadurch wird einfach ein zufälliger Sound aus unserer Reihe von Sounds ausgewählt. Bei unseren anderen randomisierten Sounds ist die Größe Null, da sie keinen Wert für das Array angeben, da sie keinen Wert für das Array angeben, und es wird nicht versucht, den Soundeffekt zufällig zu ordnen, sondern nur seine Tonhöhenskala anzupassen Jetzt muss nur noch der Soundeffekt durch die Walk-and-Run-Animationen ausgelöst werden von der Skriptansicht zur Two-D-Ansicht wechseln, wählen Sie zuerst den Animationsbaumknoten und dann den Animation-Player-Knoten aus, um vorübergehend eine Vorschau der Animationen anzuzeigen, ohne dass der Animationsbaum beeinträchtigt Wenn entweder die Walk- oder Run-Animation geöffnet ist, können wir der Animation eine Aufrufmethodenspur hinzufügen und eine Methode im Audio-Stream-Player für Schritte aufrufen , um sie zu einen Schlüssel in die Animation auf diesem Track einfügen, rufen wir die Methode play Eine Methode ist in diesem Zusammenhang gleichbedeutend mit einer Funktion. Wir können durch die Animation blättern, um die Frames zu finden, bei denen die Füße des Charakters tatsächlich den Boden berühren, und die Keyframes so einstellen, dass sie sich genau auf diesen Wiederholen Sie diesen Vorgang dann mit der anderen Animation. Jetzt haben wir ein paar zufällige Soundeffekte für Schritte, Springen und Landen, aber vielleicht wollen wir auch Staubwolken Wir sehen uns im nächsten Video. 19. 2-5 Animierter Sprite: Hallo Freunde. In diesem Video werden wir Staubpartikel für unseren Jump'n'Run-Charakter erzeugen für unseren Jump'n'Run-Charakter Dafür müssen wir mehr Spritesheets importieren. Beginnend mit der Charakterszene fügen wir dem Knoten ein animiertes Sprite hinzu und nennen es etwa Jump Das Animated Sprite to Dende unterscheidet sich von einem normalen Sprite-to-de-Node , dass es keine einzige Textureigenschaft besitzt Es hat eine Sprite-Frames-Ressource. auf das Drop-down-Menü klicken, können wir eine neue Sprite-Frames-Ressource für diesen Animated Sprite Two D-Knoten erstellen Sprite-Frames-Ressource für diesen Animated Sprite Klicken Sie dann auf die Ressource, um sie zu öffnen. Dadurch wird im unteren Bereich eine neue Registerkarte mit der Bezeichnung Sprite-Frames geöffnet unteren Bereich eine neue Registerkarte mit der Bezeichnung Sprite-Frames In diesem Fenster können wir eine oder mehrere Sprite-Frame-Animationen erstellen eine oder mehrere Sprite-Frame-Animationen , die dieser Knoten abspielen kann Diese Animationen können nur das Sprite selbst verändern. Sie können nicht wie ein Animation Player-Knoten mit Audio, Funktionsaufrufen oder anderen Eigenschaften synchronisiert Funktionsaufrufen oder anderen Eigenschaften werden Je nachdem, welche Elemente Sie verwenden, können Sie Sprites entweder aus einzelnen Dateien oder aus einem einzelnen Spritesheet hinzufügen einzelnen Dateien oder aus einem einzelnen Spritesheet Ich verwende Sprite Sheets, also klicke ich auf die Schaltfläche „Werberahmen aus Sprite Durchsuchen Sie das Dateisystem , um die gewünschten Assets zu finden Wenn Sie ein Spritesheet verwenden, werden Sie aufgefordert, auszuwählen, welche Frames des Spritesheets Sie verwenden möchten Im Gegensatz zu einer Atlas-Textur müssen diese Sprite-Frames gleichmäßig verteilt sein Wählen Sie die Anzahl der Frames in jeder Zeile und Spalte des Spritesheets aus, und sie werden für Sie in Scheiben geschnitten Sie können dann jeden der Frames, die Sie verwenden möchten, auswählen , indem Sie darauf klicken Die Zahl in der Ecke jedes Sprite-Frames gibt die Reihenfolge an, in der er der Animation hinzugefügt wird Wenn sie nicht in der richtigen Reihenfolge sind, können Sie die Sprite-Frames abwählen und erneut auswählen oder sie in der falschen Reihenfolge importieren und später Genau wie bei Charakteranimationen , die einen Frame länger als der letzte Frame sind, ist es auch bei Sprite-Animationen wie dieser eine gute Idee Sprite-Animationen wie dieser einen leeren Frame zu haben Das letzte Bild bleibt also für die gesamte Dauer eines Frames auf dem Bildschirm gezeichnet gesamte Dauer eines Frames auf dem bevor die Animation als fertig betrachtet wird Wir können die Bildrate der Animation festlegen. Ich verwende 12 Bilder pro Sekunde und lege fest, ob diese Animation in einer Endlosschleife laufen soll oder nicht, was ich dann abschalten werde. Es gibt auch eine Option, um diese Animation automatisch abzuspielen. Jeder Animated Sprite Toti-Knoten kann nur eine Autoplay-Animation haben, und der Knoten spielt diese Animation wenn der Knoten zum Szenenbaum hinzugefügt wird Wenn beim Springen des Spielers eine Staubwolke entsteht , wollten wir diese Animation abspielen Lassen Sie uns diese Animation also automatisch abspielen. Wir können eine Vorschau anzeigen , wie die Animation aussehen wird, indem wir auf die Play-Schaltfläche Um die Animation besser zu sehen, können wir das Charakter-Sprite und die Kollisionsform vorübergehend ausblenden , indem wir im Szenenbaum auf das Augensymbol neben ihnen Genau wie der Charakter muss auch diese Animation sauber auf dem Boden der X-Achse liegen Im Bereich Offset im Inspektor können wir also den Y-Offset auf die Hälfte der vertikalen Größe einstellen Bei den Assets, die ich verwende, sind das 16 Pixel mehr. Dadurch bleiben die Ursprünge der Knoten bei 00 und der Sprite-Offset wird trotzdem dargestellt Wenn die Farbe der Sprites nicht ganz stimmt oder Sie ihre Transparenz anpassen möchten, können Sie dies im Bereich Canvas-Elemente in den Eigenschaften des Knotens im Inspektor tun Eigenschaften des Knotens im der Modulate-Eigenschaft handelt es eine Farbe mit dem Standardwert Weiß, die Werte Rot, Grün, Blau und Alpha hat Grün, Blau und Alpha Jedes Pixel im Sprite erhält vor dem Zeichnen eine eigene Farbe, die mit dieser Modulationsfarbe multipliziert So können wir die Rot-, Grün-, Blau- oder Alpha-Werte anpassen Grün-, Blau- oder Alpha-Werte Ich gebe meiner Staubwolke halbe Transparenz, indem ich ihr moduliertes Alpha auf 0,5 setze Wir können die Sprites neu anordnen, indem sie anklicken und mit den Pfeiltasten ziehen, Frames löschen, leere Frames hinzufügen oder bei Bedarf weitere Frames importieren Wenn Sie mit dem Aussehen der Animation zufrieden sind, denken Sie daran, das Charakter-Sprite und die Collusionsform wieder einzublenden Charakter-Sprite Ich werde das Looping zu Demonstrationszwecken einschalten. Wenn wir das Spiel starten, folgt der Staub dem Charakter, da er ein Kind von ihm ist Aber was wir normalerweise für so etwas wollen, ist die Staubwolke an einem bestimmten Ort erscheint und sich nicht bewegt Diese Staubwolke muss ein Geschwister des Charakters sein, kein Kind rechten Maustaste auf den Animated Sprite Two D-Knoten klicken, können wir ihn als eigene Szene speichern Legen Sie es in einen neuen Ordner für Staubwolken. Lösche es aus der Charakterszene. Dann öffne es, damit wir es isoliert bearbeiten können. Lassen Sie uns das Looping in dieser Animation ausschalten. Wir möchten immer noch, dass es automatisch abgespielt wird, wenn die Staubwolke erzeugt wird, aber damit werden wir uns im nächsten Video befassen Vorerst müssen wir zwei weitere Staubwolken erzeugen. Einen, wenn der Charakter landet und einen , wenn er läuft oder rennt. So können wir unsere bestehende Jump-Dust-Szene duplizieren , um die Dinge einfacher zu machen. Es wird keinen Unterschied machen, aber ich möchte sicherstellen, dass der Name des Stammknotens meiner Szenen mit dem Dateinamen der Szene übereinstimmt. Dann tausche einfach die Sprites gegen die jeweils richtigen aus A Stellen Sie sicher, dass alle richtig versetzt sind, damit sie sauber auf dem Boden der X-Achse aufliegen Wir haben jetzt drei verschiedene Staubwolken wir für unseren Charakter verwenden möchten Wir müssen sie nur instanziieren. Wir sehen uns im nächsten Video. 20. 2-6 Instanziierung: Hallo Freunde. In diesem Video werden wir die Staubwolken als Reaktion auf die Bewegungen unseres animierten Charakters instanziieren Reaktion auf die Bewegungen unseres animierten Charakters Ausgehend von der Spielszene wollen wir, dass unsere Staubwolken in der Welt als Geschwister unseres Charakters existieren , nicht Fügen wir dem World Environment Node ein neues Skript hinzu. Ich nenne es World und lege es in den Scripts-Ordner. Der Hauptzweck dieses Skripts wird vorerst darin bestehen, neue Szenen als untergeordnete Elemente hervorzurufen Also werden wir eine neue öffentliche Funktion namens spawn schreiben, die eine gepackte Szene als ersten Parameter akzeptiert Ich nenne es einfach etwas vages wie SN und auch eine Position, an der es erzeugt werden soll, was ein Vektor zwei ist Dann gibt diese Funktion den Knoten zurück , den sie erstellt, falls wir ihn verwenden möchten Wir können eine gepackte Szene in einen Knoten verwandeln , indem wir ihre Instantiate-Funktion aufrufen Wir müssen diesen Knoten in einer Variablen speichern , um ihn verwenden zu können Ich nenne ihn Instanz. Wenn Sie einen Knoten erstellen, wird er nicht zum Szenenbaum hinzugefügt. Das müssen wir auch tun. Aber um einen Knoten zum Szenenbaum hinzuzufügen, benötigt der Knoten einen übergeordneten Knoten. Dieser Weltumgebungsknoten wird der übergeordnete Knoten sein, also nennen wir ihn die Funktion add child geben ihm die Instanz als Argument. Dadurch wird der Knoten zum Szenenbaum hinzugefügt, aber seine Position wird am Ursprung der Szene liegen, die Koordinaten 00. Wir wollen also die Position des neu instanziierten Knotens als Spawn-Position festlegen neu instanziierten Knotens als Spawn-Position Dies setzt jedoch voraus, dass der neu instanziierte Knoten eine Positionseigenschaft besitzt, was nicht Dies würde zwar noch keinen Fehler verursachen, könnte es aber in Zukunft sein, wenn wir die Spawn-Funktion verwenden verschiedene Knotentypen zu erstellen Es wäre also eine gute Idee, zu überprüfen, ob es sich bei dieser Instanz um ein Canvas-Element handelt , bevor Sie versuchen, auf ihre Positionseigenschaft zuzugreifen Wir können den Parameter Spawnposition optional machen indem wir ihm den Standardwert Vector zwei Punkt Null Schließlich können wir den Instanzknoten zurückgeben. Jetzt müssen wir diese Funktion als Reaktion darauf aufrufen , dass der Charakter bestimmte Aktionen ausführt. Der einfachste Weg, dies zu tun, ist die Verwendung von Signalen. Im Charakterskript können wir am Anfang des Skripts Signale für jedes der drei Male deklarieren am Anfang des Skripts Signale für jedes der , zu denen wir eine Staubwolke erzeugen wollen , wenn der Charakter getreten, gesprungen oder Signale werden üblicherweise in der Vergangenheitsform benannt, bedeutet, dass das fragliche Ereignis eingetreten Genau wie Funktionen können Signale Parameter haben. Um die Staubwolken erscheinen zu lassen, müssen wir die Position des Charakters kennen und wissen, in welche Richtung er blickt, damit wir angeben können, ob das Sprite umgedreht werden soll In der Sprungfunktion können wir das gesprungene Signal ausgeben und dabei die aktuelle Position des Charakters angeben und angeben, ob das Sprite des Charakters horizontal umgedreht ist oder nicht, als Argumente, die den Parametern des Signals entsprechen Argumente Das Gleiche kann gemacht werden, wenn der Charakter landet. Für die Schritte können wir eine neue private Funktion deklarieren. Benennen wir sie Schritt für Schritt und geben das Signal aus. Wenn Sie möchten, können Sie den Schrittsound auch innerhalb dieser Funktion abspielen lassen, anstatt ihn als separate Spur in die Animationen aufzunehmen ihn als separate Spur in die Animationen Aber um das zu tun, benötige ich einen Verweis auf den Audio-Player für Schritte am Anfang meines Skripts Auswahl des Animation Player-Knotens und der Walk-Animation Wir können der Animation eine Aufrufmethodenspur hinzufügen, die eine Methode im Stammknoten der Szene aufruft. Fügen Sie dann Keyframes ein, um die On-Step-Funktion während der Frames aufzurufen , wenn die Füße der Figur den Boden berühren Wenn wir die Soundeffekte über das Skript auslösen, müssen wir dies nicht mehr in der Animation tun und können diesen Track löschen Dann muss ich diesen Vorgang auch für meine Laufanimation wiederholen diesen Vorgang auch für meine Laufanimation zur Spielszene wechseln, können wir Signale mit Skripten verbinden , um automatisch auf sie zu reagieren. den Charakter auswählen und den Inspektor-Tab auf den Knoten-Tab umschalten, können wir unsere Liste der Signale sehen. Doppelklicken Sie entweder auf ein Signal oder klicken Sie mit der rechten Maustaste und wählen Sie Verbinden, ein neues Fenster wird geöffnet. In diesem Fenster können wir den Knoten auswählen, mit dem wir das Signal verbinden möchten. In diesem Fall der Weltumgebungsknoten. Geben Sie dann entweder den Namen einer Funktion ein, die als Reaktion auf das Signal aufgerufen werden soll, oder wählen Sie eine Funktion aus einer Liste aus. Ich gebe manuell den Namen einer neuen Funktion ein und nenne sie Spawn Jump Dust Wenn Sie auf Connect klicken, wird das Fenster geschlossen und das World Environment Node-Skript mit dieser automatisch hinzugefügten Funktion angezeigt das World Environment Node-Skript mit dieser automatisch hinzugefügten Funktion Diese Funktion hat auch ein grünes Symbol, das anzeigt, dass sie über eine Signalverbindung aufgerufen wird , und der Charakterknoten im Szenenbaum hat ein Signalsymbol uns anzeigt, dass er ein Signal mit einer Verbindung aussendet. Diese Signalverbindung ist auch auf der Registerkarte Knoten aufgeführt. Wir können Variablen für unsere drei verschiedenen Staubwolkenszenen exportieren , bei denen es sich um Szenen mit vielen Bildern handelt. Füllen Sie dann jede dieser Variablen auf der Registerkarte „Dateisystem“ mit den entsprechenden Szenen aus Lassen Sie uns zunächst einfach die Spawn-Funktion aufrufen und dabei Jump Dust als Argument und auch die aktuelle Position des Charakters übergeben Jump Dust als Argument und auch die aktuelle Position des Charakters Godot mag es nicht, wenn wir unsere Funktionsparameter genauso benennen wie die bereits vorhandenen Eigenschaften eines Knotens Aber wir können diesen Parameter in etwas Spezifischeres wie die Zeichenposition umbenennen etwas Spezifischeres wie die Zeichenposition Dadurch wird bei jedem Sprung des Charakters automatisch eine Sprungstaubwolke instanziiert jedem Sprung des Charakters automatisch eine Sprungstaubwolke instanziiert Der Knoten Animated Sprite Two D spielt die von uns erstellte Sprite-Animation automatisch ab, aber wir möchten nicht, dass dieser Staubwolkenknoten nach Abschluss weiter existiert Nachdem der Charakter viele Male gesprungen ist, würde der Szenenbaum viele Animated Sprite Two-D-Knoten enthalten , die nichts tun Also müssen wir sie aufräumen. Die Methode, Knoten aus dem Szenenbaum zu entfernen , besteht darin, ihre freie Funktion aufzurufen. Aber das wollen wir erst tun, wenn ihre Animation abgeschlossen ist, was ein Signal für den Animated Sprite Two D-Knoten Da wir wissen, dass der Knotentyp unserer Staubwolkenszenen ein Animated Sprite Two D ist, können wir sie in einer privaten Variablen dieses Typs speichern und sie Dust nennen Wir können Signale durch Code verbinden , genau wie wir es mit dem Inspektor getan haben , und das Signal für die fertige Animation mit seiner freien Funktion verbinden Signal für die fertige Animation mit seiner freien Funktion Denken Sie daran, dass wir keine Klammern verwenden, wenn wir auf eine Funktion verweisen , anstatt eine Funktion aufzurufen keine Klammern verwenden, wenn wir Wir können die Staubwolke auch horizontal umdrehen, wenn das Sprite des Charakters umgedreht wurde, als dieses Signal weggelassen diesen Vorgang für die anderen beiden Signale wiederholen, können wir die Art der Staubwolke ändern, die erzeugt wird Wenn wir das Spiel starten, kehren wir zum Editor-Fenster und klicken im Szenen-Tab auf die Fernbedienungstaste Wir können den Szenenbaum des Spiels sehen , das gerade läuft. erweitern den Baum, sodass wir die Kinder des World Environment Node sehen können . Wir können sehen, dass die beiden D-Nodes von Animated Sprite erstellt und zerstört werden, wenn wir springen, landen und herumlaufen Der Remote-Szenenbaum aktualisiert nicht jedes Bild, sodass einige Staubwolken erzeugt und zerstört werden können , ohne dass sie im Remote-Szenenbaum angezeigt werden im Remote-Szenenbaum Wir sehen uns im nächsten Video. 21. Audiobus 2-7: Hallo Freunde. In diesem Video fügen wir einen separaten Soundeffekt für die Stimme des Charakters hinzu. Ich muss weitere Audiodateien für die Bemühungen des Charakters importieren . Sprach-Soundeffekte unterscheiden sich von anderen Soundeffekten darin, dass wir immer nur einen nach dem anderen abspielen möchten, da unsere Sprachboxen jeweils nur einen Ton erzeugen können. Wir benötigen also nur einen TD-Node für den Audio-Stream-Player für alle Vokalisationen eines Charakters Lassen Sie uns in der Charakterszene einen der vorhandenen TD-Knoten des Audiostream-Players duplizieren , um einen neuen Knoten für die Stimme des Charakters zu erstellen Vielleicht möchtest du diesen Knoten auch irgendwo um den Hals oder Kopf des Charakters platzieren um den Hals oder Kopf des Charakters , anstatt zu seinen Füßen. Allerdings wird das bei meinem winzigen Charakter keinen nennenswerten Unterschied machen . Der Soundeffekt-Randomizer ist diesen Knoten nicht mehr verfügbar, sodass wir das Skript entfernen können indem wir auf die Schaltfläche für das separate Skript Wir werden das durch ein neues Skript ersetzen. Nennen wir es Stimme. In diesem Skript können wir eine beliebige Anzahl von Standard-Soundeffekten für die Stimme exportieren, üblicherweise als Anstrengungen oder Anstrengungen bezeichnet werden Lassen Sie uns eine Variable für den Sound von Jump Effort als Audiostream exportieren , den wir im Inspektor auffüllen können wir auf die Ressource klicken, können wir uns eine Vorschau davon ansehen, wie sich das anhören wird Ressource klicken, können wir uns eine Vorschau davon ansehen, wie sich das anhören Dann fügen wir eine Funktion hinzu , die einen Jump-Effort-Sound abspielt. Diese Funktion muss jedoch nichts tun, wenn der Sprach-Audio-Stream-Player gerade damit beschäftigt ist, andere Sounds abzuspielen Nur wenn er nicht abgespielt wird, stellen wir den Stream auf Jump Effort und spielen ihn ab Dadurch wird verhindert, dass neue Anfragen, einen anderen Effort-Sound abzuspielen , den vorherigen Sound unterbrechen Wir können hier auch dieselben Techniken verwenden wie bei unseren Soundeffekten, z. B. die Tonhöhenskala nach dem Zufallsprinzip anpassen oder eine Reihe von Audiostreams erstellen und jedes Mal einen zufällig auswählen Und im Gegensatz zu normalen Soundeffekten, denen immer erwartet wird, dass sie jedes Mal abgespielt werden, sind Anstrengungen nicht immer erforderlich Wir können also auch einen zufälligen Zufall hinzufügen , dass die Anstrengung nicht funktioniert, auch wenn das möglich ist. Bei Verwendung der Funktion rand F wird eine Zufallszahl 0-1 zurückgegeben Wir können überprüfen, ob dies weniger als eine prozentuale Wahrscheinlichkeit ist, sagen wir, 25%, ausgedrückt als 0,25 Hängt man das mit einem Operator und an die Bedingung an, so darf die Stimme dieses Charakters keinen anderen Ton abspielen und muss außerdem eine zufällige Chance von 25% bestehen bevor man diese Anstrengung spielen darf dies auszulösen, müssen wir lediglich das gesprungene Signal des Charakters mit der Jump-Effort-Funktion „Stimmen abspielen“ verbinden gesprungene Signal des Charakters mit der Jump-Effort-Funktion „Stimmen abspielen Aber das gesprungene Signal des Charakters liefert zwei Argumente und die Funktion zum Abspielen von Stimmen akzeptiert keine Parameter, sodass sie nicht als kompatibel angesehen Wenn wir auf den Schalter „Nur kompatible Methoden“ klicken, werden alle Funktionen angezeigt, auch wenn sie nicht übereinstimmen, und wir können die Funktion „ Jump Effort abspielen“ auswählen Um zu verhindern, dass dies zu einem Fehler führt, erweitern wir den Bereich für Fortgeschrittene indem wir auf den Schalter für Fortgeschrittene klicken Hier können wir neue Argumente binden oder die Bindung der vorhandenen Argumente aufheben Trennen Sie einfach die beiden vorhandenen Argumente vom gesprungenen Signal des Charakters, und jetzt ist das Signal mit dem Funktionsaufruf kompatibel es testen, werden wir hören, dass der Versuch zufällig mit einer Wahrscheinlichkeit von 25% abgespielt wird, und er wird sich nie von selbst unterbrechen B. Eine weitere Möglichkeit, Stimmen von anderen Soundeffekten zu trennen , besteht darin, ihnen Audiobus-Layout einen separaten Audiobus zuzuweisen Klicken Sie unten im Editor auf die Audio-Schaltfläche , um das Audiobus-Layout zu öffnen, das derzeit nur über einen einzigen Bus, den Master-Bus, verfügt. Wenn wir jedoch auf Bus hinzufügen klicken, können wir dem Audiobus-Layout weitere Busse hinzufügen, einen für Soundeffekte und einen für Stimmen. Es ist auch eine gute Idee, einen anderen für Musik zu haben. Auf diese Weise können wir unser Audio in verschiedene Kategorien einteilen und die gesamte Kategorie im gesamten Spiel auf einmal steuern . Wir können die Lautstärke aller Soundeffekte, Stimmen und Musik unabhängig voneinander einstellen, und die Master-Lautstärke wirkt sich auf alle aus. Es gibt auch viele verschiedene Audioeffekte , die zu jedem Bus hinzugefügt werden können, wenn wir möchten. In unserer Charakterszene haben wir mehrere verschiedene Audiostream-Player mit zwei D-Knoten, und diesen muss jeweils mitgeteilt werden, zu welchem Audio-Bus sie gehören, wobei die Standardeinstellung Master Bus ist. Jeder der Soundeffekte kann so eingestellt werden dass er auf dem Soundeffekt-Bus abgespielt wird, während die beiden D-Knoten des Sprach-AudioStream-Players angewiesen werden können , auf dem Sprachbus abzuspielen Jetzt können wir die Lautstärke unserer Soundeffekte unabhängig von den Stimmen M. M. Wir haben jetzt einen sehr ausgefeilten 2-D-Jump'n'Run-Charakter Als Nächstes werden wir anfangen, Umgebungen zu erstellen , in denen wir uns bewegen können Wir sehen uns im nächsten Abschnitt. 22. 3-1 Kachelkarte: Hallo Freunde. In diesem Abschnitt werden wir eine Umgebung schaffen in der sich unser Charakter bewegen und herumspringen kann. Dazu muss ich Assets für mein Terrain importieren, sortiert in einen neuen Ordner für Terrain-Sprite-Assets auf das Asset doppelklicken, können wir es im Inspektor in der Vorschau anzeigen Wir können sehen, dass dieses Asset genau wie der Charakter ein Spritesheet Mit Ausnahme von Animationsframes enthält dieses Spritesheet verschiedene Sprites zum Zeichnen von Terrain auf der Grundlage der umliegenden Beginnend mit der Spielszene machen wir das aktuelle Level zu einem statischen Körper, machen wir das aktuelle Level zu einem statischen Körper seine eigene Szene zu kennzeichnen Ich erstelle einen neuen Ordner für Raumszenen. Und je nach Größe deines Spiels möchtest du vielleicht auch Räume nach Regionen sortieren. Also erstelle ich einen weiteren Ordner für Räume in der Waldregion und speichere diesen Raum als Startraum ab. Dann öffne diese neue Raumszene. Ich möchte nicht mehr, dass der statische Body-2-D-Node der Wurzelknoten ist, da dieser Raum mehr als nur ein Stockwerk enthalten wird. Also werde ich als Kind dieser Szene einen regulären Knoten mit zwei D hinzufügen . dann mit der rechten Maustaste auf diesen Knoten klicken, können wir Make Scene Root auswählen, um den Szenenbaum neu zu organisieren , sodass dieser Knoten jetzt der Wurzelknoten ist Jetzt ist der Boden ein untergeordnetes Element des Wurzelknotens, und wir könnten diesem Knoten weitere statische Körper für Wände, Decken, Plattformen und Hindernisse hinzufügen diesem Knoten weitere statische Körper für Wände, Decken, , um unseren Raum zu bauen Ich benenne den Wurzelknoten so um, dass er dem Namen der Szene entspricht. Wenn wir Kacheln aus einem Spritesheet verwenden , die die gleiche Größe und den gleichen Abstand haben, können wir einen anderen von Gadot bereitgestellten Knoten verwenden , die so genannte Kachelmap-Ebene, um sie einfacher zu zeichnen der Szene einen Knoten mit einer Kachelkartenebene hinzufügen wird das Kachelkartenfenster am unteren Rand des Editors geöffnet, aber wir können hier noch nichts tun Zuerst müssen wir uns die Eigenschaften der Knoten der Kachelmap-Ebene im Inspektor ansehen . Der Knoten der Kachelkartenebene kann erst dann etwas zeichnen, wenn er über einen Kachelsatz verfügt. auf das Drop-down-Menü klicken, erstellen wir ein neues Kachelset. Klicken Sie dann auf das Kachelset , um seine Eigenschaften zu erweitern. Die erste Option ist die Form der Kacheln in diesem Kachelset. Die Kacheln, die ich verwende, sind quadratisch, aber es gibt auch Optionen für isometrische, halb versetzte quadratische und sechseckige Diese werden normalerweise für Perspektiven von oben nach unten verwendet, und dieses Spiel ist ein Side-Scroller, daher verwende ich quadratische Kacheln Als Nächstes müssen wir die Größe der Kacheln festlegen. Mein importiertes Spritesheet hat die Kachelgröße im Namen, 32 mal 32 Pixel Wir werden die restlichen Einstellungen vorerst ignorieren und im unteren Bereich des Editors von Tilemap auf Kachelsatz umschalten unteren Bereich des Editors von Tilemap auf Jetzt können wir dem gerade erstellten Kachelset Kacheln hinzufügen. Klicken Sie entweder unten auf die Plus-Schaltfläche und navigieren Sie dann durch das Dateisystem, um Ihre Assets zu finden , oder klicken Sie auf die Assets und ziehen Sie sie von der Registerkarte Dateisystem in den Bereich Kachelquellen Dadurch werden wir aufgefordert, dass die Engine das Spritesheet für uns automatisch in Kacheln aufteilt Wenn wir Ja wählen und die Kachelgröße korrekt einstellen, werden die Kacheln im Spritesheet für uns automatisch auf diese Größe zugeschnitten und dem Kachelsatz hinzugefügt Wenn wir auf die Schaltfläche mit dem Radiergummi klicken, können wir auf Kacheln klicken, um sie aus dem Kachelset zu entfernen Durch Klicken und Ziehen werden alle Kacheln gelöscht , über die wir ziehen Strg- oder Befehlstaste gedrückt halten und dann klicken und ziehen, können wir alle Kacheln im ausgewählten Bereich entfernen Wenn wir den Radierer wieder ausschalten, können wir dieselben Steuerelemente verwenden, um dem Kachelsatz Kacheln hinzuzufügen Wenn Sie übergroße Kacheln erstellen möchten, können Sie dies tun, indem Sie die Umschalttaste gedrückt halten und dann auf mehrere Kacheln klicken und sie mit der Maus darüber ziehen Dadurch werden mehrere Kacheln so behandelt, als ob sie immer als eine größere Gruppe von Kacheln gezeichnet werden sollen Aber dieses Spritesheet hat keine übergroßen Kacheln, also lösche ich sie und füge jede dieser Kacheln einzeln zum Kachelset Da unser Kachelset nun Kacheln enthält, kann unsere Kachelkartenebene dieses Kachelset verwenden , um die Kacheln zu zeichnen Wir wechseln also vom Kachelsatzfenster zum Kachelkartenfenster. Wenn das Malwerkzeug ausgewählt ist, können wir eine Kachelquelle aus dem Kachelsatz und dann eine Kachel aus der Kachelquelle auswählen . In der Szenenansicht mit zwei D-Szenen gibt der Editor orangefarbene Richtlinien für die Anordnung der Kacheln vor. Wir können diese Kachel nun durch Klicken an die gewünschte Stelle malen . Wenn Sie den Versatz der Kacheln ändern möchten, können Sie die Transformationsposition der Tilemap-Ebenenknoten anpassen Transformationsposition der Tilemap-Ebenenknoten Wie im Kachelset können wir den Schalter „Löschen“ verwenden , um Kacheln zu löschen, anstatt Das Auswahlwerkzeug kann verwendet werden, um eine Kachel aus der T D-Ansicht und nicht aus dem Kachelsatzfenster auszuwählen eine Kachel aus der T D-Ansicht und nicht aus dem Kachelsatzfenster Wir können Kacheln horizontal, vertikal oder beides umgedreht zeichnen und sie je nach Bedarf im oder gegen den Uhrzeigersinn drehen gegen den Uhrzeigersinn Wir können auch mehrere Kacheln gruppieren und sie alle gleichzeitig bemalen. Option „Zufälliges Feld platzieren“ umschalten, wird stattdessen nach dem Zufallsprinzip aus den ausgewählten Kacheln ausgewählt Wenn die Streuung zunimmt, bleiben einige Steine unbemalt, wenn Sie können auch Linien zeichnen. Wenn mehrere Kacheln ausgewählt sind, werden sie entlang der Linie wiederholt. Und das Rechteckwerkzeug kann sehr schnell einen ganzen Bereich der Kachelkartenebene ausfüllen . Das Bucket-Tool kann verwendet werden, um einen leeren, geschlossenen Bereich der Kachelkartenebene zu füllen . Die Optionen „Zufallsprinzip“ und „ Streuung“ gelten auch für die Werkzeuge „Line Wrecked“ und „Bucket Das Bucket-Tool verfügt außerdem über einen zusammenhängenden Schalter, der, wenn er deaktiviert ist , verwendet werden kann, um alle passenden Kacheln auf der gesamten Kachelkartenebene der gesamten Da der Knoten der Kachelkartenebene unser Terrain zeichnet, benötigen wir den statischen Body-Tutti-Knoten nicht mehr und können ihn aus der Szene löschen Zurück in der Spielszene können wir unseren Startraum sehen. Der Knoten wird nicht umbenannt. Es steht immer noch die aktuelle Stufe. Wenn wir das Spiel starten, kollidiert der Charakter nicht mit dem Terrain , sondern fällt einfach hindurch Wir haben jetzt eine Kachelkartenebene einen Kachelsatz zum Zeichnen von Kacheln verwendet, aber wir müssen noch mehr Arbeit investieren, um unser Kachelset zu konfigurieren Wir sehen uns im nächsten Video. 23. 3-2 Gelände: Hallo Freunde. In diesem Video werden wir mehr Optionen für Kachelsätze verwenden, um Malen von Kacheln auf eine Kachelkartenebene schneller und einfacher zu gestalten. in der Raumszene Wählen Sie in der Raumszene den Knoten der Kachelkartenebene aus und erweitern Sie dann das Kachelset im Inspektor. Wenn Sie den Abschnitt Physik-Ebene erweitern, ist er derzeit leer Deshalb fügen wir eine neue Physik-Ebene hinzu. Wir müssen keine der Eigenschaften der Physikebene bearbeiten . Es muss nur existieren. Wir werden uns später im Kurs mit Kollisionsebenen und Kollisionsmaskierung befassen Wenn Sie möchten, können Sie aber auch ein physikalisches Material hinzufügen , um dessen Reibung, Rauheit, Sprungkraft oder Saugfähigkeit anzupassen Rauheit, Sprungkraft Ich möchte kein Physikmaterial, also lösche ich es aus dem Nachdem die Physikebene zu unserem Kachelset hinzugefügt wurde, können wir die Registerkarte „Kachelsatz“ unten im Editor öffnen , um diese Physikebene auf unsere Kacheln anzuwenden. Wechseln Sie vom Atlas-Setup zu den Farbeigenschaften, indem Sie auf diese Schaltfläche klicken. Hier können wir viele verschiedene Eigenschaften auf unsere Kacheln malen , aber die, die wir jetzt malen wollen , ist Physik-Ebene Null. Beim Bemalen sollte die gesamte Kachel standardmäßig mit vier weißen Knoten an allen Ecken gefüllt sein . Ist dies nicht der Fall, klicken Sie auf die drei Punkte und wählen Sie „Auf Standardform zurücksetzen“ oder drücken Sie die F-Taste Wir können diese physikalische Kollisionsform jetzt auf unsere Kacheln malen Kollisionsform jetzt auf unsere Kacheln Alle diese Kacheln sind so konzipiert, dass sie dieselbe quadratische Form haben. Wenn Sie jedoch unterschiedliche Objekte verwenden, müssen Sie möglicherweise die Kollisionsform für verschiedene Kacheln anpassen . Wir können auf diese weißen Punkte klicken und sie ziehen um die Kollisionsform anzupassen, sie zu löschen oder nach Bedarf weitere hinzuzufügen , um eine beliebige Form zu erstellen. Wenn Sie eine bessere Ansicht benötigen, um genauer zu sein, können Sie diesen Editor so erweitern, dass er das gesamte Bedienfeld ausfüllt. Es sind auch Optionen zum Einrasten von Rastern verfügbar. die Rasterausrichtung auf die Pixelgröße einstellen, können Sie , wenn Sie möchten, eine pixelgenaue Kollision erzeugen A Nachdem wir Kollisionsformen auf die Felder gemalt und das Spiel erneut ausgeführt haben, wird der Charakter mit unseren Kacheln das Spiel erneut ausgeführt haben, wird kollidieren Jetzt haben wir eine Kollision, aber es ist sehr mühsam, ein Terrain nach dem anderen zu zeichnen ist sehr mühsam, ein Terrain nach dem Wir können die im Editor integrierten Tools verwenden, um es einfacher zu machen. den Geländeabschnitt erweitern, können wir diesem Kachelsatz ein Gelände-Set hinzufügen. Dem Gelände-Set muss auch ein Terrain hinzugefügt werden. Also werden wir auch hier ein Element erstellen. Wir können das Terrain benennen , wie wir wollen. Ich nenne meinen Wald und gebe ihm eine Farbe. Diese Farbe wird nicht im Spiel gezeichnet sondern nur im Editor, um sie einzurichten. Es hilft, eine Farbe zu wählen, die sich den im Spritesheet verwendeten Farben abhebt, sodass sie hervorsticht Ich verwende Rosa als Kontrast zu meinen grünen und braunen Geländekacheln Öffnen Sie als Nächstes das Kachelsatzfenster am unteren Rand des Editors. Terrains sind eine Methode zum Zeichnen von Kacheln, die so konzipiert sind, dass sie miteinander verbunden sind, wie es bei diesem Spritesheet Wechseln Sie zu den Farbeigenschaften, und die Eigenschaft, die wir malen möchten, ist die Geländeeigenschaft Wir können dann unser Terrain-Set, das wir gerade erstellt haben, Terrain-Set Null und das Terrain in diesem Terrain-Set, das Waldgelände, auswählen Terrain-Set, das wir gerade erstellt haben, Terrain-Set Null und das Terrain . Um die Geländeeigenschaft zu malen, müssen wir zunächst alle Kacheln auswählen, die Teil des Geländes sind , sodass sie nicht mehr dunkel sind. In diesem Spritesheet sind das alle. Wenn Sie mit der Maus über ein Plättchen fahren, das zu diesem Terrain hinzugefügt wurde, wird das Plättchen in neun Quadrate aufgeteilt mittlere Quadrat muss ausgefüllt werden , um dieses Plättchen als Teil unseres Geländes zu zeichnen Die anderen Quadrate weisen den Editor an, dieses Plättchen zu zeichnen, wenn sich in dieser Richtung ein anderes Geländeplättchen neben diesem befindet. Beginnend mit diesem Plättchen soll dieses gezeichnet werden, wenn sich keine anderen Geländeplättchen neben ihm befinden. Es ist also nur das mittlere Quadrat bemalt. Das Plättchen ganz links soll gezogen werden, wenn sich rechts davon ein anderes Geländeplättchen befindet , sodass das rechte Quadrat darauf gemalt wird. Das gegenüberliegende Plättchen auf der rechten Seite folgt der gleichen Logik auf der linken Seite, und das mittlere Plättchen wird gezogen, wenn sowohl links als auch rechts angrenzendes Gelände vorhanden ist . Die vertikalen Kacheln sind identisch, nur nach oben und nach unten. Der große Block in der oberen linken Ecke kombiniert diese beiden Elemente, fügt Ecken hinzu und hat auch die durchgehende Kachel in der Mitte , auf der alle Quadrate gemalt sind. Dies reicht aus, um konvex geformte Geländeblöcke zu zeichnen konvex geformte Geländeblöcke zu Öffnen Sie das Kachelkartenfenster, wechseln Sie von Kacheln zu Terrains und wählen Sie dann das Terrain aus, das wir gerade erstellt haben Wenn das Malwerkzeug ausgewählt ist, können wir wie zuvor Geländekacheln nach Belieben auf die Ebene der Kachelkarte malen wie zuvor Geländekacheln nach Belieben auf die Ebene der Kachelkarte Wenn unsere Geländekacheln nun jedoch an andere Geländekacheln angrenzen und rechteckige Formen bilden, werden sie automatisch auf die richtige Kachel aus dem Gelände aktualisiert. Durch das Löschen von Kacheln werden auch die umliegenden Kacheln aktualisiert. Das funktioniert auch mit den Tools Line Wreck und Bucket. Wenn wir konkave Ecken erzeugen wollen, müssen wir zur Geländemalerei zurückkehren alle verbleibenden Kacheln zum Gelände hinzufügen, füllen wir alle Quadrate aus, die der Frage entsprechen, ob in dieser Richtung ein weiteres Geländeplättchen neben diesem Feld liegen sollte liegen sollte Richtung ein weiteres Geländeplättchen neben diesem Feld Wenn du diesen Elementen folgst und dir nicht sicher bist , welches Muster auf den einzelnen Kacheln gezeichnet werden soll, kannst du das Video pausieren und meins kopieren. Bei einigen Kachelobjekten finden Sie eine Anleitung oder Referenz, die Ihnen bei den Regeln für die Nachbarschaft von Kacheln hilft. Sie können aber auch einfach experimentieren und herausfinden, was gut aussieht Versuchen Sie, ein gewisses Terrain in verschiedenen Formen zu zeichnen , um zu sehen ob alle möglichen Kombinationen berücksichtigt werden, und zeichnen Sie entsprechend Die Kacheln am unteren Rand sind auch dazu gedacht, mit angrenzendem Gelände in alle Richtungen gezeichnet zu werden . Jede Kachel in einer Kachelkarte ist normalerweise so gestaltet, dass sie ein einzigartiges Muster aufweist. Wenn Sie jedoch mehrere Kacheln mit demselben Muster haben, wählt das Terrain-Werkzeug beim Zeichnen nach dem Zufallsprinzip eine mit demselben Muster aus. Wir können die Wahrscheinlichkeit dieser Zufälligkeit anpassen, indem eine weitere Eigenschaft aus der Drop-down-Liste Wahrscheinlichkeit ausmalen der Drop-down-Liste Wahrscheinlichkeit Geben Sie einfach eine Wahrscheinlichkeit ein. Ich nehme 0,01, was 1% entspricht , und male das auf die Kacheln unten. Jedes Mal, wenn das Terrain-Werkzeug eine Kachel zeichnet , die in alle Richtungen angrenzt, eine Chance von 1%, dass jedes dieser Kacheln unten gezeichnet wird, oder es wird dieser Kacheln unten standardmäßig die leere Kachel verwendet Wenn Sie Terrain von der Kachelkarte aus malen die zufällige Verteilung dieser Kacheln nicht besonders gut aussieht, können Sie einfach weiter darüber zeichnen Der Terrain-Editor berechnet die zufällige Verteilung jedes Mal Wir können jetzt ganz einfach Räume für unser Spiel zeichnen , indem wir einen Knoten auf einer Kachelkartenebene verwenden, aber die Kamera bewegt sich nicht, sodass wir unseren Charakter nicht sehr weit bewegen können Wir sehen uns im nächsten Video. 24. 3-3 Kamera: Hallo Freunde. In diesem Video folgt die Kamera dem Charakter, sodass er sich weiter in der Umgebung bewegen kann . In der Spielszene haben wir die beiden D-Knoten des Charakters und der Kamera als Geschwister. Wenn wir der Kamera ein Kind des Charakters zuordnen, folgt sie natürlich der Kamera ein Kind des Charakters zuordnen, dem Spieler. Dies ist jedoch keine besonders gute Methode, da die meisten Spiele Übergänge, Zwischensequenzen oder andere Bereiche des Spiels haben , die an die Kameraansicht anpassen unabhängig vom Spielercharakter In einigen Spielen hat der Spieler die Wahl, welchen Charakter er spielen möchte, und dieser Charakter muss geladen sein, sodass in der Spielszene nicht festgelegt werden kann , ob die Kamera diesem Charakter folgen muss Es ist besser, die Kamera als Geschwister zu belassen und die Kamera stattdessen dem Spielercharakter durch ein Skript folgen stattdessen dem Spielercharakter durch ein Skript Lass uns ein Skript zur Kennzeichnung an unsere Kamera anhängen. Wir könnten es Kamera nennen oder es nach dem Verhalten benennen, dem Spieler folgen oder beides kombinieren , Kamera-Follow Wir könnten den Spielercharakter als Variable exportieren , wie wir es mit dem Eingabe-Handler gemacht haben, aber nehmen wir stattdessen an, dass diese Kamera angewiesen wird, mehr als einem Charakter während des Spiels zu folgen , und stattdessen eine öffentliche Funktion namens follow definieren, die ein Subjekt als Parameter akzeptiert. Theoretisch könnte dieses Subjekt alles sein, solange es in der Zwei-D-Welt existiert und eine Position hat Also geben wir ihr eine Art von Knoten zwei D und nicht die spezifischere Art von Charakterkörper zwei D. Auf diese Weise könnte diese Kamera angewiesen werden, einem starren Körper zu folgen oder was auch immer wir wollen Diese Funktion muss keinen Wert zurückgeben. Alles, was sie wirklich tun muss, ist dieses Subjekt in einer privaten Variablen zu speichern . dann ein Motiv hat, überschreibt sie die Prozessfunktion Wenn diese Kamera dann ein Motiv hat, überschreibt sie die Prozessfunktion und setzt ihre Position so ein, dass sie der globalen Position des Motivs entspricht Da das Motiv Teil einer größeren Szene sein kann, möchten wir nicht seine lokale Position relativ zu seinem Elternteil verwenden , sondern seine globale Position innerhalb der gesamten Spielszene wir den Delta-Parameter nicht verwenden, setze ich ihn mit einem Unterstrich fort Jetzt benötigen wir ein weiteres Skript , um diese Funktion von einem Knoten aus aufzurufen , der Zugriff sowohl auf die Kamera als auch auf unseren Charakter hat , der der Spielknoten sein wird ein Skript an den Spielknoten anhängen, nennen wir es Game Manager, und ich lege es in einen neuen Skriptordner für Manager-Skripte Es liegt in der Verantwortung des Spielmanagers, festzulegen, wann der Spieler das Spiel spielt, sich in einer Zwischensequenz befindet oder zwischen Szenen wechselt Vorerst, wenn der Spielmanager bereit ist , die Bereitschaftsfunktion zu überschreiben, weisen wir die Kamera an, dem Spieler zu folgen und den Eingabe-Handler zu aktivieren Um das zu tun, müssen wir jeden dieser Knoten in Variablen speichern jeden dieser Knoten in Variablen Da die Hierarchie der Spielszene im Vergleich zu anderen Szenen ziemlich komplex ist, müssen wir die Knoten möglicherweise neu anordnen dabei ihre Herkunft ändern In diesem Fall ist der Knotenpfad in unserem Skript nicht mehr gültig, was zu Fehlern führt Wir können dies vermeiden, indem wir mit der rechten Maustaste auf Knoten in unserem Szenenbaum klicken und Access als eindeutigen Namen auswählen. Dadurch wird rechts neben dem Knoten im Szenenbaum ein Prozentzeichen hinzugefügt . Auf diese Weise können wir den mit Dollarzeichen versehenen Knotenpfad durch den eindeutigen Namen mit Prozentzeichen ersetzen Knotenpfad durch den eindeutigen Namen mit Prozentzeichen Wenn dem Knoten bereits ein eindeutiger Name zugewiesen wurde, wird dieser automatisch übernommen, wenn Sie die Strg- oder Befehlstaste gedrückt halten und ihn in das Skript ziehen wir nun all diese Knotenreferenzen haben und der Game Manager bereit ist, Nachdem wir nun all diese Knotenreferenzen haben und der Game Manager bereit ist, können wir die Kamera anweisen, dem Spielercharakter zu folgen und den Eingabe-Handler zu aktivieren Wir haben noch keine Aktivierungsfunktion für den Eingabe-Handler geschrieben , also lasst uns zu diesem Skript wechseln und es schreiben. Das Erstellen einer aktivierten privaten Variablen als booleschen Wert , der standardmäßig auf False gesetzt ist , und eine öffentliche Aktivierungsfunktion, die wir setzen können, ist auf true aktiviert Bevor wir dann irgendwelche Eingaben vom Player verarbeiten, überprüfen wir, ob der Eingabe-Handler aktiviert ist, und kehren zurück, wenn er nicht aktiviert ist. Wenn aktiviert auf False steht, verlassen wir die Funktion und verhindern so, dass der restliche Code ausgeführt wird Wenn aktiviert auf False steht, verlassen wir die Funktion und verhindern so, dass der restliche Code ausgeführt Wir benötigen außerdem eine Deaktivierungsfunktion, die die Variable is enabled wieder auf False setzt. Das mag übertrieben erscheinen, da wir die Variable is enabled einfach öffentlich machen könnten. Aber wenn wir diese gekapselte Struktur verwenden, können wir innerhalb dieser Funktionen andere Logiken ausführen Wenn beispielsweise der Eingabehandler deaktiviert ist, weisen Sie den Charakter an, sich nicht mehr zu bewegen, indem Sie die Richtung auf Null setzen und ihm auch sagen, dass er gehen soll Wenn Sie den Eingabehandler aktivieren, wird die Bewegung bereits automatisch erkannt, da sie gerade geprüft wird. Wenn der Spieler allerdings angefangen hat, die Run-Taste gedrückt zu halten , bevor der Eingabe-Handler aktiviert wurde wurde die Eingabe zwar ignoriert, aber der Spieler erwartet trotzdem, dass sein Charakter läuft. Wir können den Status der Run-Taste überprüfen, wenn wir den Eingabe-Handler aktivieren und dem Charakter sagen, dass er entsprechend laufen soll. Wenn wir die Eingabefunktion für Bewegungen verwenden, könnten wir den Eingabe-Singleton auf den Status der Bewegung nach links und rechts überprüfen den Status der Bewegung nach links und dem Charakter sagen, dass er sich auch hier bewegen soll Zurück zur Spielszene: Da sich die Position des Charakters auch am Ursprung befindet, zeichnet die Kamera das Bild, wenn das Spiel beginnt Das ist keine besonders gute Darstellung des Charakters oder des Raums Normalerweise muss der Spieler mehr von dem sehen , was sich über ihm befindet oder was vor ihm können wir der Kamera einen Positionsversatz zuweisen , um sie entlang der Y-Achse nach oben und entlang der X-Achse nach rechts zu bewegen der Y-Achse nach oben und erreichen, können wir der Kamera einen Positionsversatz zuweisen, um sie entlang der Y-Achse nach oben und entlang der X-Achse nach rechts zu bewegen. Ich lege es um 64 Pixel nach oben und nach rechts und ändere auch meinen Zoom auf zwei. Wenn also die Kameraposition so eingestellt ist , dass sie der Position des Charakters entspricht, wird sie danach in jedem Frame um diesen Betrag versetzt, sodass der Spieler einen Blick leicht nach oben rechts von der Figur hat. Unsere Kamera folgt jetzt der Figur, aber die Kamera schaut nur nach rechts. Wir sehen uns im nächsten Video. 25. 3-4 Blick nach vorne: Hallo Freunde. Und dieses Video ermöglicht es der Kamera, entweder nach links oder rechts vor den Charakter zu schauen . dem Zeichenskript beginnen, können wir es uns leichter machen , indem wir Klassennamen für einige unserer Skripte angeben, indem das Schlüsselwort Klassenname oben im Skript verwenden. Nennen wir diese Klasse etwas Generischeres wie Character. Dadurch kann Godot die Namen von Variablen und Funktionen automatisch vervollständigen , wenn er in anderen Skripten auf Mitglieder dieser Klasse zugreift in anderen Skripten auf Mitglieder dieser Klasse So wie wir Signale verwendet haben, um auf die Aktionen des Charakters zu reagieren und Staubwolken zu erzeugen, müssen wir ein weiteres Signal geben wenn der Charakter die Richtung ändert, in die er schaut ein Signal mit dem Namen „ Richtungsänderung“ deklarieren, müssen wir als Parameter angeben, in welche Richtung der Charakter jetzt schaut dem Bereich Fortbewegung eine weitere Variable hinzufügen, müssen wir wissen welche Richtung der Charakter gerade schaut um zu wissen, ob er seine Blickrichtung geändert hat seine Blickrichtung geändert Da eine boolesche Variable von Natur aus auf False gesetzt ist, nenne ich die Variable nach links gerichtet, was, wenn sie falsch ist, bedeutet, dass sie In der Face Left-Funktion können wir unser neues Signal ausgeben und den Wert von direction als Argument übergeben Oh, unten im physikalischen Prozess, wenn wir dem Charakter sagen, dass er in die Richtung schauen soll, passiert das jedes Mal der Spieler bei jedem Frame eine Eingabe macht. Wir wollen dieses Signal nicht bei jedem Frame ausgeben, sondern nur bei Frames, wenn sie die Richtung ändern. Also fügen wir die Bedingung hinzu , dass das Zeichen nach links zeigt und die Richtung größer als Null ist, oder dass das Zeichen nicht nach links zeigt und die Richtung kleiner als Null ist. Jetzt werden diese Funktionen nur noch während des Frames aufgerufen , wenn der Charakter tatsächlich seine Blickrichtung ändert. Dadurch wird das Signal ausgegeben , damit wir darauf reagieren können. zum Kameraskript wechseln, benötigen wir eine Funktion, die der Signatur des Signals entspricht , das wir gerade erzeugt haben, um es zu verbinden. Nennen wir es bei Betreff geänderter Richtung, da das Zeichen das Subjekt sein wird. Die Richtung, in die das Zeichen zeigt, wird als Gleitkomma akzeptiert und es wird kein Wert zurückgegeben. Wir wollen, dass der X-Offset der Kamera dem Richtungszeichen entspricht . Also müssen wir den Wert des Offsets unverändert in einer anderen Variablen speichern Offsets unverändert in einer anderen Variablen Wir nennen es Standard-Offset und setzen es mithilfe eines Ready-Tags auf den Wert Offset Jetzt können wir den Wert von Offset sicher bearbeiten , ohne zu vergessen, was der ursprüngliche Wert war H. Wenn das Motiv die Richtung ändert, setzen wir den Wert für den Offset auf den Standard-Offset multipliziert mit dem Richtungsvorzeichen Wenn die Richtung also positiv ist, dann ist auch der Offset der Kamera positiv, und das Gleiche gilt für negativ Um dieses Signal zu verbinden wenn die Kamera angewiesen wird, einem Motiv zu folgen, wenn das Motiv nicht Null ist und das Motiv ein Charakter ist, die Klasse, die wir gerade benannt haben, dann können wir sicher auf das geänderte Richtungssignal des Charakters zugreifen das geänderte Richtungssignal des Charakters und es mit unserer Funktion verbinden. Ein Godot erkennt neue Klassennamen erst, nachdem Sie Ihre Skripte gespeichert haben Wenn wir diese Follow-Funktion jedoch aus irgendeinem Grund mehr als einmal für dasselbe Thema aufrufen , führt dies zu einem Fehler, da das Signal bereits verbunden ist Lassen Sie uns zunächst überprüfen, ob das Motiv, dem die Kamera folgen soll, dasselbe ist wie das Objekt, dem sie bereits folgt. In diesem Fall müssen wir nichts tun und können es einfach zu dieser Funktion zurückkehren. Jetzt wissen wir, dass das Thema etwas anderes als das aktuelle Thema ist . Lassen Sie uns überprüfen, ob das aktuelle Thema nicht Null ist und ob es sich um ein Zeichen handelt. Wenn beides zutrifft, sollten wir auch prüfen, ob das Richtungsänderungssignal des Charakters mit der Funktion „Beim Subjekt hat die Richtung geändert“ verbunden ist. Und wenn das stimmt, schalten wir das Signal ab, da die Kamera dem Motiv nicht mehr folgt und nicht darauf reagieren muss. Wenn das Spiel ausgeführt wird, die Kamera vor dem Charakter positioniert, aber das passiert sofort, was für den Spieler ziemlich verwirrend ist Besser wäre es, den Wert des Offsets im Laufe der Zeit schrittweise anzupassen , was wir ganz einfach mit einem Tween, der Abkürzung für „Zwischen“, tun können Abkürzung Also deklarieren wir eine neue Variable, nennen sie so etwas wie Look Ahead Tween Dann, wenn das Zeichen die Richtung ändert, wird der Wert dieser Variablen zugewiesen, um ein Tween zu erzeugen Create Tween ist eine Funktion der Node-Klasse, sodass sie von jedem Node verwendet werden kann Wenn das Tween erstellt ist, greifen wir auf seine Tween-Eigenschaftsfunktion Dies akzeptiert ein Objekt als erstes Argument, das dieser Knoten selbst ist Wir können dies mit dem Schlüsselwort self spezifizieren. Dann die Eigenschaft, die wir als Zeichenfolge verbinden wollen, das ist die Offset-Eigenschaft, genauer gesagt die X-Komponente, die wir mit dem Doppelpunkt angeben können Das nächste Argument ist der Endwert handelt es sich um den voreingestellten X-Offset multipliziert mit dem zuvor berechneten Richtungszeichen berechneten Richtungszeichen Und schließlich die Dauer des Tweens in Sekunden. Im Moment stelle ich es auf 1 Sekunde ein. Da dieses Tween 1 Sekunde dauert, es aber durchaus möglich ist, dass der Charakter in dieser Sekunde mehrmals die Richtung wechselt, würde dies zu dass der Charakter in dieser Sekunde mehrmals die Richtung wechselt, mehreren Tweens führen, die alle versuchen den Offset-Wert zu bearbeiten. Bevor wir das Tween erstellen, sollten wir also zuerst überprüfen, ob es bereits existiert, und ob es dadurch beendet wird Auf diese Weise kann nicht mehr als eines dieser Tweens gleichzeitig existieren und versuchen, den X-Offset zu bearbeiten das jetzt ausführen, zwickt der X-Offset der Kamera , dass er über eine Sekunde vor der Figur schaut, aber es ist immer noch ein wenig Wir können die Art und Weise, wie dieser Tween entsteht, anpassen , indem wir weitere Variablen exportieren Lassen Sie uns zunächst eine Dauer für dieses Tween als Gleitkommazahl exportieren und ihr einen Standardwert von 1 Sekunde geben Ersetzen Sie dann die Variable in unserer Funktion durch diese Variable. Als Nächstes fügen wir einen Übergangstyp und einen Beschleunigungstyp hinzu. Zusammen ermöglichen uns diese drei Variablen , eine Vielzahl verschiedener Tweens zu erstellen , indem wir anpassen wie schnell sich der Wert am Anfang und am Ende des Tweens ändert Anfang und am Ende des Da create tween ein Tween zurückgibt, können wir auf dessen Funktion set trans zugreifen und unseren Übergangstyp als Argument in derselben Zeile übergeben Die Funktion set trans gibt auch das Tween zurück, sodass wir diese Zeile fortsetzen und unmittelbar danach auch die Funktion set Es aufrufen unmittelbar danach auch die Funktion set Es Wir übergeben unsere Es-Variable als Argument. All dies gibt das Tween mit den eingestellten Transitions- und Easetypen zurück den eingestellten Transitions- und Easetypen und weist das Ergebnis der Variablen zu der Spielszene, indem wir den Kamera-Tutti-Knoten auswählen seine Eigenschaften im Inspektor ansehen, können wir die Werte dieser Variablen bearbeiten, wobei die Übergangs- und Beschleunigungstypen praktische Drop-down-Listen bereitstellen Wir können auch die Dauer des Tweens verkürzen Ich lasse meinen über 2 Sekunden ein Quad in Out Tween verwenden. Experimentieren Sie mit den verschiedenen Optionen , um ein Gefühl dafür zu bekommen, wie sie funktionieren Der Übergangstyp bestimmt welche mathematische Formel verwendet wird , um das Verhalten zu ändern, während der Typ der Lockerung entscheidet, wie sich dies auf die erste oder zweite Hälfte des Tweens auswirkt Die Kamera schwenkt jetzt sanft nach links oder rechts, um zu zeigen, was sich vor der Richtung befindet, in die der Charakter blickt Manchmal möchte der Spieler aber auch nach oben und unten schauen Wir sehen uns im nächsten Video. 26. 3-5 Nach oben schauen: Hallo Freunde. In diesem Video ermöglichen wir dem Spieler, dem Charakter zu sagen, dass er nach oben und unten schauen soll. Zunächst müssen wir der Eingabemap in den Projekteinstellungen weitere Eingabeereignisse hinzufügen Eingabemap in den Projekteinstellungen weitere Eingabeereignisse , damit sie nach oben und unten suchen können. Ich verwende die Aufwärts- und Abwärtspfeiltasten. Die Richtungstasten nach oben und unten und der rechte Stick sind nach oben und unten geneigt Im Spielerskript wird dann, anders als bei der Bewegungsrichtung, anders als bei der Bewegungsrichtung, die nur von der Figur verwendet wird, die Blickrichtung sowohl von der Figur als auch von der Kamera verwendet , was bedeutet, dass wir einen Verweis auf die Kamera benötigen Es lohnt sich, die Blickrichtung in einer Variablen zu speichern , sodass wir sie nur einmal pro Bild berechnen müssen. dann in der Prozessfunktion Sie dann in der Prozessfunktion ihren Wert aus dem Eingabe-Singleton ab, genauso wie wir es mit der Funktion Get Axis für die Bewegungsrichtung getan haben Funktion Get Axis für die die Namen der Eingabeaktionen geändert Denken Sie daran, dass up das erste Argument sein wird, da up negativ ist erste Argument sein wird Wir können diese Blickrichtung dann sowohl an den Charakter als auch an die Kamera senden . Für die Kamera verwende ich einen Funktionsaufruf. Aber für den Charakter zerlege ich den Wert einer öffentlichen Variablen Um den Namen der Richtungsvariablen der Zeichenklasse etwas klarer zu machen, könnte es klug sein, sie in Bewegungsrichtung umzubenennen Da diese Funktion im Kameraskript nicht existiert, werde ich sie vorerst auskommentieren, um Fehler zu vermeiden, bis ich bereit bin, sie zu schreiben. Drüben im Zeichenskript können wir den Ersetzen-Dialog mit Strg oder Befehls-R öffnen und Richtung durch die Bewegungsrichtung ersetzen sodass klarer ist, wofür sie verwendet werden soll. Fügen Sie dann eine neue öffentliche Variable für die Blickrichtung hinzu. Die L-Richtungsvariable muss an keiner Stelle im Skript verwendet werden. Sie wird nur vom Animationsbaum gelesen. In der Szene mit den Charakteren den Animation Player auswählen muss ich den Animation Player auswählen und LU- und L-Down-Animationen erstellen. Ich werde meine inaktive Animation duplizieren , um die Dinge einfacher zu machen. Bearbeiten Sie dann einfach die Y-Werte meiner Keyframes, um den Charakter entsprechend nach oben oder unten zu zeichnen . Dann kann ich in der Animationsbaum-Zustandsmaschine die die Locomotion-Zustandsmaschine bearbeitet, , die die Locomotion-Zustandsmaschine bearbeitet, die Animationen für die Suche nach oben und die Anzeige nach unten hinzufügen Übergang zu ihnen erfolgt auf der Grundlage des Werts der Blickrichtung Und stellen Sie sicher, dass ihre X-Geschwindigkeit Null bleibt, andernfalls sollten sie stattdessen zum Gehen übergehen Und zurück in den Leerlauf , falls die Blickrichtung gleich Null ist. Oder wenn sie angefangen haben zu laufen, wird die Figur animiert, nach oben oder unten zu schauen , wenn wir die Aufwärts- und Abwärtsrichtung drücken, aber die Kamera bewegt sich noch nicht Versuchen Sie in der Spielszene, den Y-Offset der Kamera zu ändern und entscheiden Sie, wie weit die Kamera bewegen soll, wenn der Charakter nach oben oder unten schaut Ich verwende 128 Pixel und setze es auf die Standardeinstellung von minus 64 zurück Um zum Player-Skript zurückzukehren, werde ich jetzt die Kamerafunktion auskommentieren und dann zum Kameraskript wechseln, dann zum Kameraskript wechseln diese Funktion zu deklarieren Ich akzeptiere eine Richtung als Float und gebe keinen Wert zurück. Der Hauptteil dieser Funktion wird fast identisch mit Funktion „ Beim Betreff hat sich die Richtung geändert“ sein. Alles, was wir tun müssen, ist, alle Instanzen eines Kopfes durch ein Hoch-Down zu ersetzen . Deklarieren Sie diese dann als neue Variablen. Wir benötigen außerdem eine weitere exportierte Variable für den zuvor festgelegten maximalen Blickabstand , den wir anstelle des Standard-Offsets verwenden werden, und Offset X ist Offset Y. Wenn wir jedoch die Aufwärts- oder Abwärtspfeile loslassen, soll die Kamera zum Standard-Offsetwert zurückkehren, nicht zu Null Das erfordert also ein wenig zusätzliche Logik. Eine andere Möglichkeit, einfache if-Anweisungen zu Ihren Skripten hinzuzufügen , besteht darin, eine ternäre Operation zu verwenden, die in GDScript dieselben if-Schlüsselwörter wie eine normale if-Anweisung verwendet , beginnend mit dem Standardfall, dem Wert, den wir bereits berechnet haben, aber nur, wenn die Richtung nicht Null ist, gefolgt von else Wenn die Richtung also Null ist, wollen wir stattdessen unseren Standard-Y-Offset verwenden Das funktioniert, aber in den meisten Spielen mit dieser Mechanik muss der Spieler die Taste einige Zeit gedrückt halten , bevor sich die Kamera bewegt Dies können wir erreichen, indem Player-Knoten einen Timer-Knoten Geben wir ihm einen Namen. Schau, warte. Wir können die Wartezeit vom Inspektor aus anpassen, aber 1 Sekunde ist in Ordnung, und der Timer muss auf einmal eingestellt sein. Das Timeout-Signal dieses Timers mit dem Player-Skript verbinden . In diesem Moment teilt das Player-Skript der Kamera mit, In diesem Moment teilt das Player-Skript dass sie anfangen soll, in die Richtung zu schauen Am Anfang des Skripts müssen wir einen Verweis auf den alten Timer-Knoten abrufen. Außerdem benötigen wir einen booleschen Wert, damit wir wissen, ob der Spieler gerade schaut oder In der Prozessfunktion setzen wir, nachdem wir den Wert der Blickrichtung aus dem eingegebenen Singleton erhalten haben, die Kamera zurück, wenn der Spieler bereits hinschaut und dann auch, wenn die Blickrichtung Null ist nachdem wir den Wert der Blickrichtung aus dem eingegebenen Singleton erhalten haben, die Kamera zurück, wenn der Spieler bereits hinschaut und dann auch, wenn die Blickrichtung Null ist, indem wir ihre Look-Funktion aufrufen und Null als Argument übergeben Dann sieht Set als falsch aus. Der Grund, warum ich keine and-Anweisung verwendet habe, ist, dass ich eine Else-Anweisung verwenden kann , wenn ich hier und jetzt davon ausgehe, dass das Suchen falsch ist. Überprüfe dann auch, ob die Blickrichtung nicht Null ist. In diesem Szenario, in dem der Spieler noch nicht hinschaut, aber die Blickrichtung eingibt, müssen wir ihn starten, wenn der Hold-Timer gestoppt ist. noch einen hinzufügen, wenn der Spieler nicht hinschaut und keine Blickrichtung eingibt, dann auch, wenn der Hold-Timer nicht gestoppt ist, bedeutet das, dass wir ihn anhalten und den Blick abbrechen müssen. Hinzufügen von Print-Anweisungen für all diese können wir sicherstellen, dass jede Anweisung nur einmal aufgerufen wird , wenn es angemessen ist. Außerdem müssen wir die Variable is looking auf true setzen, wenn der Look-Hold-Timer abgelaufen und die Kamera zu zwängen beginnt. wir das Spiel starten, auf die Aufwärts- oder Abwärtspfeile tippen , ohne die Taste gedrückt zu halten, wird der Hold-Timer gestartet, aber gestoppt und die Kamera bewegt sich nicht, aber der Charakter animiert immer noch, indem er nach oben und unten schaut Wenn Sie die Aufwärts- oder Abwärtstasten gedrückt halten, läuft der Timer nach 1 Sekunde ab und weist die Kamera an, nach oben oder unten zu schauen Sie die Aufwärts- oder Abwärtstasten loslassen, wird die Kamera auf ihre voreingestellte Offset-Position zurückgesetzt. Ich kommentiere diese Print-Anweisungen und passe meine Tween-Einstellungen im Inspektor an, dass sie sich über eine halbe Sekunde vervierfachen Der Spieler kann jetzt die Aufwärts- und Abwärtsrichtung gedrückt halten , um nach oben und unten zu schauen. Möglicherweise möchten wir jedoch einschränken, wie weit sich die Kamera bewegen kann um zu verhindern, dass Inhalte außerhalb des aktuellen Raums angezeigt werden Wir sehen uns im nächsten Video. 27. 3-6 Grenzen: Hallo Freunde. In diesem Video beschränken wir die Kamera so, dass sie innerhalb der Umgebungsgrenzen bleibt. Ausgehend von der Raumszene können wir den Wurzelknoten so ändern, dass er ein Bereichs-2-D-Knoten ist und nicht nur ein normaler Zwei-D-Knoten. Dies ist einem physikalischen Körper insofern ähnlich , als er eine Kollisionsform hat, aber er hat keine Masse und reagiert auch nicht auf Kräfte. Stattdessen können Sie es sich wie einen Bewegungs- oder Wärmemelder vorstellen . Er stellt eine Region des Weltraums dar und sendet ein Signal aus, wenn physikalische Körper ihn betreten oder verlassen. Dies wird später nützlich sein, um zu erkennen, wann der Spielercharakter den Raum betritt. Aber vorerst müssen wir nur wissen, welche Form es hat. eine Kollisionsform hinzufügen, um sie als Kind zu kennzeichnen, können wir ihr eine Formressource geben Wir werden eine rechteckige Form verwenden. Wir können die Form dann verschieben und ihre Größe ändern , um Raumgrenzen zu erstellen Wenn ein Skript an den Stammknoten der Szene anhängen , nennen wir es Room und sortieren es in den Skriptordner Wir benötigen einen Verweis auf die Kollisionsform, um zu enden. Ich benenne es in Shape Node um. Dann benötigen wir Funktionen , die verwendet werden können , um die obere linke Ecke und die untere rechte Ecke dieses Rechtecks abzurufen und die untere rechte Ecke dieses Rechtecks sodass sie Vektor-2-Koordinaten zurückgeben. Wir können auf die Kollisionsform, zwei Bezeichnungen der Formeigenschaft , über ihren Namen shape zugreifen Bezeichnungen der Formeigenschaft , über ihren Namen shape Dann wollen wir auch eine Funktion für die Shape-Ressource Get wrecked aufrufen die Shape-Ressource Get Die Funktion G wrecked gibt ein Wrack zwei zurück. Wenn wir die Dokumentation für diese Klasse öffnen, können wir sehen, dass sie eine Position und ein Ende hat Die Position ist die obere linke Ecke und das Ende ist die untere rechte Diese beziehen sich jedoch auf die Position der Knoten. Wir benötigen diese Koordinaten im globalen Raum, also fügen wir sie der globalen Position der Knoten hinzu. Die globale Position eines Knotens wird relativ zum Ursprung des Spiels sein, nicht zur Position der übergeordneten Knoten. Wir können diese Werte dann zurückgeben. Jetzt müssen wir der Kamera nur noch sagen , dass sie diese Grenzen einhalten soll. Aus der Game Manager-Szene holen wir uns vorerst einfach einen Verweis auf den Startraum und speichern ihn in einer Variablen namens Current Room. Wenn die Spielszene fertig ist, können wir die obere linke Ecke und die untere rechte Ecke aus dem aktuellen Raum abrufen und sie an die Kamera weitergeben, indem wir eine Funktion aufrufen, die ihre Grenzen festlegt. zum Kameraskript wechseln, deklarieren wir diese Funktion, indem sie die beiden Vektor-Zweien akzeptiert , die aus dem aktuellen Raum abgerufen wurden, und keinen Wert zurückgibt In dieser Funktion werden wir herausfinden, wie nah die Kamera an die obere linke und untere rechte Ecke dieses Raums herankommen kann die obere linke und untere rechte Ecke , ohne etwas zu sehen, das über diese Punkte hinausgeht Um das zu tun, müssen wir diese Variablen als Vektor-Zweier erstellen , und es ist hilfreich, einen booleschen Wert dafür zu haben ob die Kamera gerade gebunden ist oder nicht Wir müssen auch die Größe des Viewports kennen, die wir mit der Funktion Get Viewport automatisch abrufen können . Dann können wir auf die Größeneigenschaft zugreifen und sie mit dem Tag on ready in einer Variablen speichern Die Funktion Get Viewport ist in der Node-Klasse deklariert und gibt einen Vektor zwei zurück, der der Größe des Fensters entspricht, das wir in den Projekteinstellungen festgelegt haben Diese Viewport-Größe entspricht nicht unbedingt der Anzahl der Pixel, die von der Kamera gezeichnet werden, da die Kamera die Ansicht vergrößern oder verkleinern kann Wir müssen die Größe des Viewports durch den Zoom der Kamera dividieren , um die tatsächliche Pixelgröße des Bereichs zu erhalten , den die Kamera sehen kann Ein Vektor kann jedoch nicht durch einen anderen Vektor geteilt werden . Wir müssen einen Float verwenden. Ich verwende nur den X-Zoom und gehe davon aus, dass der Zoom der Kamera immer einheitlich ist. Aber das ist immer noch nicht gut genug, da die Position der Kamera in der Mitte ihrer Ansicht befindet. Die Position , an der sich die Kamera am nächsten an der linken oberen oder unteren rechten Ecke des Raums positionieren kann , ohne diese Punkte zu überschreiten , ist tatsächlich halb so groß. Wenn ich diesen Wert durch zwei teile, benenne ich die Variable um, um ihren neuen Wert widerzuspiegeln. Bei der Festlegung der Grenzen entspricht die Position ganz oben links der oberen linken Ecke des Raums plus der halben Größe der Kameraansicht. Die Position ganz unten rechts entspricht der unteren rechten Ecke des Raums minus der Hälfte der Kameraansicht, und wir können den Grenzwert auf true setzen. H. In der Prozessfunktion werden wir, nachdem wir der Kamera mitgeteilt haben, dass sie der Position des Motivs entspricht, diese Grenzbeschränkungen mit der Funktion Clamp F anwenden . Die Funktion Clamp F verwendet einen Float-Parameter wie die Position der Kamera, dann einen Minimalwert und einen Maximalwert und gibt dann einen Wert zurück, der innerhalb dieser Grenzen bleibt. Dann überschreiben wir die Position der Kamera mit dem Ergebnis der Fixierung und wiederholen dies für das Y. Da unsere Kamera aber auch einen Offset hat, ihre Position nicht genau genug der Mitte des Viewports Wir bearbeiten auch den Wert des Offsets zu unvorhersehbaren Zeiten Offsets Wir können ihn also bei den Berechnungen oben links und unten rechts nicht berücksichtigen , da sich der Wert wahrscheinlich häufig ändern wird. Wir müssen also den Offset bei den Klemmfunktionen berücksichtigen , indem wir ihn jedes Mal von oben links und unten rechts subtrahieren ihn jedes Mal von oben links und unten rechts Wenn du möchtest, dass deine Kamera während des Spiels ein- und auszoomt und dabei diese Grenzen respektiert, musst du diese auch bei den Berechnungen innerhalb der Prozessfunktion berücksichtigen den Berechnungen innerhalb der Prozessfunktion Das funktioniert, aber die Kameratweens scheinen mit den Grenzwerten zu kämpfen Durch das Tween wird der Offset der Kamera leicht über die Grenzen hinaus verschoben Offset der Kamera leicht über die Grenzen hinaus Der Frame wird gezeichnet, und in der nächsten Prozessschleife die Kameraposition von der Grenze wegbewegt , um den neuen Offset zu kompensieren Dies geschieht wiederholt, bis der Tween aufhört. Das liegt daran, dass die Tweens nach dem Vorgang am Ende des Frames ausgeführt werden , kurz bevor alles auf den Bildschirm gezeichnet Um dieses Problem zu beheben, können wir unsere Tweens von der Verwendung der Tween-Eigenschaft auf die Tween-Methode umstellen von der Verwendung der Tween-Eigenschaft auf die Tween-Methode eine Methode aufrufen, können wir die Grenzgrenzen gleichzeitig anwenden , während wir den Wert von Offset ändern Die Argumente für die Tween-Methode erfordern anstelle eines Verweises auf ein Objekt eine aufrufbare Wir sagen „Y−Offset setzen“. Gefolgt vom Startwert, der dem aktuellen Wert des Y-Offsets der Kamera entspricht, dann sind die übrigen Argumente identisch. Zwei ist der Endwert am Ende des Tweens und die Dauer des Tweens Das Gleiche können wir mit dem Look Ahead Tween Two machen. Wir müssen nur diese Set-X-Offset-Funktion schreiben und dabei einen einzigen Parameter akzeptieren, einen einzigen Parameter akzeptieren der dem Typ von from und zwei Argumenten entspricht Nachdem wir den Wert von X-Offset geändert haben, können wir die Grenzgrenze für die Kameraposition so festlegen , dass sie sofort kompensiert wird, und dasselbe für den Y-Offset tun. dies jetzt ausführen, werden die Offset-Tweens die Raumgrenzen nicht Wir haben die Kamera jetzt darauf beschränkt , nur zu zeigen, was sich im aktuellen Raum befindet, aber die Umgebung sieht sehr flach Wir sehen uns im nächsten Video. 28. 3-7 Parallaxe: Hallo Freunde. In diesem Video korrigieren wir das Parallax-Scrolling von Vordergrund und Hintergrund mit einem benutzerdefinierten Skript Ab der zweiten Raumszene kopiere ich alle meine Modulationsfarben von den Parallax-Tut-Knoten auf ihre untergeordneten Knoten Dann kann ich das Parent der Sprites aufheben und die Parallax-Tut-Knoten löschen , während beibehalte Ich füge dann einem dieser Sprites ein neues Skript hinzu, nenne es Parallax und lege es Das gleiche Skript kann an alle Sprites angehängt werden , die ich an Parallax haben möchte Um ein benutzerdefiniertes Verhalten zu erstellen, ist es hilfreich, sich etwas Zeit zu nehmen, um darüber nachzudenken , was Sie erreichen möchten, welche Knotenreferenzen und andere Informationen erforderlich Ich habe eine Reihe verschiedener Sprites. Ich möchte mich relativ zur Position der Kamera unterschiedlich bewegen , und ich weiß, dass sich die Kamera derzeit innerhalb der Grenzen dieses Raums befindet derzeit innerhalb der Grenzen dieses Raums Ich füge der Szene vorübergehend einen Kamera-D-Node hinzu und zoome ihn um den Faktor zwei heran zu tun, als ob es sich um die Spielszene handelt Wenn sich die Kamera genau in der Mitte dieses Raums befindet, wollte ich alles genau so zeichnen, wie es ist Wenn sich die Kamera jedoch von der Mitte wegbewegt, verschiebe ich alle Parallax-Sprites um einen relativen Betrag, wobei die Hintergrundelemente weniger bewegen als die Kamera und die Vordergrundelemente sich in die entgegengesetzte Richtung bewegen Dazu muss jedes Sprite die Position der Kamera relativ zur Raummitte sowie seine eigene ursprüngliche Position kennen Position der Kamera relativ zur Raummitte sowie seine eigene Im Parallax-Skript deklariere ich eine exportierte Variable, deklariere ich eine exportierte Variable die den Faktor enthält, um den sich das Sprite relativ zur Kamera bewegt, und nenne sie Scroll-Skala als Vektor 2. Das funktioniert ähnlich wie die Scroll-Skalenvariable im Parallax-Zwei-D-Knoten Wenn dieser Raum in den Szenenbaum geladen ist, können wir das Tag on ready verwenden, um seine Position zu ermitteln und sie als ursprüngliche Position in einer Variablen zu speichern Dank der Viewport-Funktion von Node G ist es ganz einfach, einen Verweis auf die aktuelle Kamera zu erhalten Dank der Viewport-Funktion von Node G ist es ganz einfach, einen Verweis auf die aktuelle Kamera zu den Viewport zurück, in dem sich dieser Node befindet, auch über die Funktion Get camera to D verfügt , um die Kamera abzurufen Wir können dies auch in einer Variablen speichern, indem wir das Tag on ready verwenden Wenn wir die Prozessfunktion außer Kraft setzen, benötigen wir Delta nicht und können sie als unbenutzt markieren Ich setze die Position des Sprites einfach auf seine ursprüngliche Position plus den Abstand der Kamera vom Mittelpunkt des Raums, multipliziert mit der Scroll-Skala Jetzt benötigt die Kamera nur noch eine öffentliche Funktion, die uns ihre Position relativ zum Mittelpunkt des aktuellen Raums mitteilen kann uns ihre Position relativ zum Mittelpunkt des aktuellen Raums mitteilen relativ zum Mittelpunkt des aktuellen Raums Wenn ich zum Kameraskript übergehe, schreibe ich diese Funktion, Offset vom Mittelpunkt, was der Position der Kamera plus ihrem Offset minus dem Mittelpunkt des Wenn ich dies als neue Variable deklariere, kann ich sie als Durchschnitt der oberen linken und unteren rechten Ecke des Raums berechnen , wenn ich sie mit der Funktion „Grenzen setzen “ akzeptiere Funktion „Grenzen setzen Wir könnten diese Funktion so ändern , dass sie den Mittelpunkt und die Größe des Rechtecks akzeptiert und nicht die obere linke und untere rechte Ecke, aber das würde sowieso keinen Unterschied in der Effizienz machen , also werde ich mich Jetzt können wir die Scroll-Skala für jedes der Parallax-Sprites so einstellen , dass sie jeweils einen anderen Abstand zur sie jeweils einen anderen Abstand Ich verwende weiterhin nur die horizontale Parallaxe gebe meinen Hügeln eine Scroll-Skala von einem Drittel entlang der X-Achse und den weiter hinten liegenden Hügeln zwei Für den Vordergrund müssen sie sich in die entgegengesetzte Richtung bewegen wie die Kamera Sie haben eine Bildlaufskala von minus einem Drittel und minus zwei Dritteln Das wird ausreichen, um die Illusion von Tiefe in unseren Räumen zu erzeugen. das Spiel ausführen, können wir in den zweiten Raum gehen und sehen, dass der Parallax-Effekt dem des Startraums identisch aussieht, obwohl er von einem sehr einfachen Skript ausgeführt wird Da sich die Sprites im Vordergrund in die entgegengesetzte Richtung der Kamera bewegen, müssen sie entweder ihre Position wiederholen und umdrehen, sodass eine Endlosschleife entsteht, oder wir können das Sprite einfach größer als den Raum machen Wenn ich meine Sträucher 1,5-mal länger mache als der Raum und das Gras doppelt so lang wie der Raum, bleibt auf beiden Seiten genug übrig , sodass die Kanten nie die Sicht der Kamera erreichen A Es wäre möglich, den Parallax-Zwei-D-Knoten zu verwenden, um Vordergrund und Hintergrund in einem separaten Viewport zeichnen und sie auf verschiedenen Leinwandebenen zeichnen oder zu versuchen, den aktuellen Raum immer am Ursprung der Spielszene Diese Lösungen würden später zu weiteren Komplikationen und Einschränkungen führen , wenn es beispielsweise darum geht , die Karte des Spiels zu zeichnen Ich finde es manchmal einfacher, benutzerdefinierte Lösungen wie diese zu schreiben , als die bereitgestellten Knoten zu verwenden. Die Lösung speichert auch alles für einen Raum an einem Ort, was es einfacher macht, die Räume intuitiver zu entwerfen und zu bauen. Ich benötige diesen Kamera-Tuti-Knoten nicht mehr, also lösche ich ihn die Wolken vom Parallax-Touti-Knoten entfernen, können wir das Parallax-Skript ändern und die auch automatisch scrollen das Wrect-Gebiet erweitern, müssen wir nur den Expositionswert mit der Zeit verringern, um die Wolken nach rechts zu verschieben verringern, um die Wolken nach rechts zu das Parallax-Skript an diesen Knoten anhängen, können wir zunächst seine Scroll-Skala auf eins setzen , sodass sie der Bewegung der Kamera entspricht Dadurch erscheinen die Wolken im Vergleich zu den Parallax-Hügeln unendlich weit entfernt einen weiteren Vektor zwei für die automatische Scrollgeschwindigkeit exportieren, müssen wir jetzt Delta in der Prozessfunktion verwenden und können den Unterstrich entfernen auf die Eigenschaft region rect und ihre Position zugreifen, beginnend mit dem X, subtrahieren wir den AutoScrollX-Wert Dadurch wird die Geschwindigkeit des Autoscrollens auf Pixel pro Sekunde erhöht. Ordnen Sie das Ergebnis dann der Region recs X-Position zu. Wenn wir dies jedoch über einen sehr langen Zeitraum ausführen würden, würde sich diese Zahl den Grenzwerten einer Fließkommazahl nähern und könnte zu Problemen führen Der Wert der X-Position entspricht der Größe, das Ergebnis ist tatsächlich dasselbe. wäre es besser, die X-Position wieder auf Null zurückzusetzen diesem Fall wäre es besser, die X-Position wieder auf Null zurückzusetzen, damit wir das für unendlich lange Zeit wiederholen können . Mit der AP F-Funktion können wir einen Minimal - und Maximalwert angeben, um den Wert so zu begrenzen, dass er nur zwischen Null und der Größe der Aufnahme liegt. Diese Funktion gibt ein Ergebnis zurück , das zwischen diesen beiden Werten liegen muss, aber im Gegensatz zu Clamping wird der Rest immer noch im Ergebnis enthalten sein. Und wir können dasselbe tun, wenn wir das vertikale automatische Scrollen verwenden wollen Ich gebe den Wolken zur Demonstration einen großen automatischen Bildlauf entlang des X. Und wenn wir das Spiel starten, scrollen die Wolken automatisch nach rechts und drehen sich in einer Endlosschleife Mama. Mama. Ich setze den Auto-Scroll-Wert wieder auf einen vernünftigen Wert zurück. Wir haben jetzt das Parallax-Scrollen im Vordergrund und im Hintergrund für beide Räume Die Übergänge zwischen den Räumen erfolgen jedoch sehr plötzlich. Wir sehen uns im nächsten Video. 29. 4.1 Inhalt: Hallo Freunde. In diesem Abschnitt ermöglichen wir dem Spieler, zwischen mehreren Räumen in unserem Spiel zu wechseln. die Startraumszene öffnen, können wir sehen, dass die visuellen Komponenten dieses Raums außerhalb der Kameragrenzen liegen. Wenn wir uns in einem Raum befinden würden, der an diesen angrenzt, würden wir nicht wollen , dass diese Sprites würden wir nicht wollen , dass diese Sprites zeichnen, obwohl sie eigentlich in einem anderen Raum sein Und wenn wir uns vorstellen würden, dass unser gesamtes Spiel aus vielen verschiedenen Räumen bestünde, wäre es eine enorme Verschwendung von Ressourcen, all ihre visuellen Komponenten geladen zu haben ihre visuellen Komponenten , wenn wir nur einen nach dem anderen betrachten Also fügen wir der Szene einen weiteren Knoten zwei D hinzu. Nennen Sie es Inhalt. Ordnen Sie dann all diese anderen Knoten mit Ausnahme der Kollisionsform wieder dem Inhaltsknoten zu Ausnahme der Kollisionsform wieder dem der rechten Maustaste auf den Inhaltsknoten klicken, speichern wir ihn als eigene Szene Ich erstelle im Ordner Forest Rooms einen neuen Ordner für Inhalte. Geben Sie der Szene dann den Namen Start Room-Inhalt. Löschen Sie dann den Inhalt dieser Szene. Wenn der Spielercharakter diesen Raum betritt, müssen wir nur seinen Inhalt laden und ihn der Szene hinzufügen. Löschen Sie dann den Inhalt , wenn sie ihn verlassen. Wir können erkennen, wann der Spielercharakter den Raum betritt , indem wir das vom Körper eingegebene Signal verbinden , da der Tutti-Knoten des Charakters ein physischer Körper ist dieses Signal mit dem Raumskript verbinden, fügt es automatisch wir dieses Signal mit dem Raumskript verbinden, fügt es automatisch eine Funktion für den eingegebenen Körper hinzu, wobei der Körper als Parameter akzeptiert Da wir den Text nicht benötigen, können wir ihn mit einem Unterstrich als unbenutzt markieren Am Anfang des Skripts ist es hilfreich, diesem Skript einen Klassennamen zu geben Nennen wir es Room. Exportieren Sie dann den Inhalt, der als gepackte Szene angezeigt wird. Und füllen Sie diese Variable aus, indem Sie auf die Inhaltsszene klicken und sie von der Registerkarte Dateisystem in den Inspektor ziehen die Inhaltsszene klicken und sie von der Registerkarte Dateisystem in den Außerdem deklarieren wir eine Inhaltsvariable als Knoten zwei D. Wir deklarieren eine neue Funktion namens Wenn der Inhalt Null ist, weisen wir ihm den Wert des instanziierten Inhalts zu Fügen Sie dann als Kind den Inhaltsknoten zur Szene hinzu. Wenn der Spielercharakter diesen Raum betritt, rufen wir die Funktion zum Laden von Inhalten auf. Lassen Sie uns vorübergehend den Wert von body ausdrucken , damit wir sehen können, was er ist. Wir werden auch eine weitere Funktion benötigen, um den Inhalt des Raums zu entladen, wenn er nicht mehr benötigt wird, obwohl wir das erst mit dem nächsten Video testen können das erst mit dem nächsten Video testen Prüfen Sie zunächst, ob Inhalte entladen werden müssen. Wenn Inhalte vorhanden sind, rufen Sie die Funktion Qu free auf und setzen Sie die Variable auf Null Sie einen Knoten aus dem Szenenbaum befreien, wird der Inhalt der Variablen nicht automatisch gelöscht Wenn wir also einen Raum verlassen, seinen Inhalt entladen und dann denselben Raum wieder betreten würden , diese If-Anweisung, die prüft, ob der Wert des Inhalts Null ist, würde diese If-Anweisung, die prüft, ob der Wert des Inhalts Null ist, sagen, ja, da ist tatsächlich etwas in dieser Inhaltsvariablen Allerdings wurde der Knoten , der hier gespeichert wurde , zuvor aus dem Szenenbaum entfernt, sodass es zu einem Fehler kommen wird Das Setzen der Variablen auf Null, nachdem sie aus dem Szenenbaum entfernt wurde, behebt dieses Problem. Beim Ausführen des Spiels befindet sich unser Charakter im Kollisionsbereich des Startraums, sodass der Inhalt des Startraums geladen wird. Wir wollen jedoch nicht, dass andere Physikkörper das Signal auslösen und versehentlich den Inhalt des Raums laden Wir müssen sicherstellen, dass der Spielercharakter der einzige Körper ist, der das bewerkstelligen kann. zur Spielercharakterszene wechseln, können wir den Tutti-Knoten des Charakters auswählen und den Kollisionsbereich in den Eigenschaften, die von Collision Object übernommen wurden, erweitern den Kollisionsbereich in den Eigenschaften, die von Collision Object übernommen wurden Hier haben wir eine Kollisionsebene und eine Kollisionsmaske mit jeweils 32 nummerierten Schaltflächen Dies sind Bitmasken, bei denen es sich lediglich um ganze Zahlen handelt, die auf eine bestimmte Weise verwendet werden. Da Ganzzahlen als 32 binäre Nullen und Einsen gespeichert werden , können wir jedes einzelne Bit als Ebene verwenden Wenn es an der Zeit ist, nach Kollisionen zu suchen, indem wir einfache logische Operationen zwischen Kollisionsmaske eines Objekts und der Kollisionsebene des anderen Objekts anwenden, können wir bestimmen, ob sie kollidieren sollen Nur wenn die Maske des ersten Objekts eine Eins hat, die sich an derselben Bitposition wie die Ebene des zweiten Objekts befindet, wird eine Kollision ausgelöst Andernfalls wird es einfach so hindurchgehen , als ob es nicht da wäre. Wenn die Kollisionsebene des Charakters auf eine andere Zahl geändert wird, existiert er nun auf seiner eigenen Kollisionsebene getrennt von allem anderen im Spiel. Da sich die Zahlen in Achtergruppen befinden, verwende ich gerne die ersten acht Ebenen für Kollisionsebenen in der Umgebung, die nächsten acht für den Spielercharakter, die nächsten acht für Feinde usw. Der Körper des Charakters maskiert immer noch die erste Ebene, sodass er während seines physikalischen Prozesses immer noch mit dem Terrain kollidiert, wenn wir Move und Slide aufrufen Wir können diese Ebenen in den Projekteinstellungen unter Ebenennamen Physik zwei D benennen. Ich nenne Ebene eins als Terrain und Ebene neun als Diese Namen werden zusammen mit ihrem Bit - und Integer-Wert angezeigt, wenn Sie mit der Maus über die Ebenenschaltflächen im Inspektor fahren der Maus über die Ebenenschaltflächen im Inspektor zusammen mit ihrem Bit - und Integer-Wert angezeigt, wenn Sie mit In der Startraumszene können wir die Kollisionsmaske ändern, sodass dieser Bereich zwei Enden nur die Kollisionsebene des Spielercharakters maskiert, nur der Spielercharakter Kollisionen mit diesem Bereich auslöst mit diesem Bereich auslöst Wenn wir das Spiel erneut starten, wird sich nichts ändern, aber wir können sicher sein , dass keine anderen Personen Inhalt des Raums laden werden Wir haben jetzt den Inhalt unseres Raums dynamisch geladen, wenn der Spielercharakter ihn betritt, aber wir haben immer noch nur einen Raum. Wir sehen uns im nächsten Video. 30. 4-2 Zimmer: Hallo Freunde. In diesem Video fügen wir einen zweiten Raum hinzu, in den der Charakter ziehen kann. Wir beginnen damit, die Startraumszene zu duplizieren. Ich nenne diesen zweiten Raum. Dann dupliziere auch die Inhaltsszene des Startraums und öffne sie, damit ich sie bearbeiten kann Entferne dann die Bäume und das Blätterdach, sodass sie sich optisch vom Startraum unterscheidet Wir können auch das Gelände und die Grenzen bearbeiten wenn wir die beiden Räume noch besser voneinander unterscheiden möchten Wenn ich die zweite Raumszene öffne, benenne ich den Stammknoten der Szene so um, dass er dem Dateinamen entspricht. Vergessen Sie nicht, die Inhaltsszene des zweiten Raums der Raumszene des zweiten Raums zuzuweisen , damit bei der Eingabe der richtige Inhalt geladen wird. Da meine Welt in Regionen aufgeteilt sein wird, füge ich in der Spielszene meine Welt in Regionen aufgeteilt sein wird, füge ich in einen Knoten zwei D hinzu und nenne ihn Wald. Dann mache meine beiden Räume zu Kindern der Waldregion. Speichern Sie die Waldregion als eigene Szene im Ordner Räume und öffnen Sie die Waldregionsszene, um sie zu bearbeiten. In der Waldregionsszene können wir diese beiden Räume jetzt problemlos nebeneinander positionieren . Wir möchten die Räume nebeneinander positionieren , sodass wir den Raum wechseln können , wenn der Spieler einen Raum verlässt und einen anderen betritt. Wir schalten das Raster-Snapping ein, erweitern dann die Fangoptionen und wählen Snap und wählen Wir können den Rasterschritt auf die Kachelgröße unserer Geländekacheln einstellen unserer Geländekacheln Dadurch ist es sehr einfach, die Räume exakt nebeneinander zu positionieren die Räume exakt nebeneinander zu Das vom Körper der Tutti-Knoten eingegebene Signal wird ausgegeben, sobald des Charakters Tutti mit der Kollisionsform des Raums überschneidet Einfachheit halber müssen wir zwischen den Räumen etwas Platz lassen, der so groß ist, dass sich der Körper des Charakters nicht mit mehr als einem Raum gleichzeitig überschneiden kann mit mehr als einem Raum gleichzeitig überschneiden Andernfalls müssten wir zusätzliche Logik für den Fall hinzufügen der Charakter einen Raum betritt ohne den vorherigen Raum vollständig zu verlassen. Ihr Charakterkörper überschneidet sich gleichzeitig mit den Bereichen beider Räume , dreht sich dann aber um und kehrt in den ersten Raum zurück Es ist viel einfacher, wenn die Räume voneinander entfernt sind. Wenn der Charakter einen neuen Raum betritt, wissen wir, dass er den vorherigen Raum bereits verlassen hat Dadurch kann sich der Charakter auch vollständig außerhalb der Kameragrenzen bewegen , bevor der Übergang in den neuen Raum ausgelöst Da die Kollisionsform meines Charakters nur 12 Pixel breit ist und der Abstand zwischen den Räumen 32 Pixel breit ist, weiß ich mit Sicherheit, dass der Charakter zwischen diese beiden Räume passt , ohne beide gleichzeitig zu berühren Diese Lücke bedeutet auch, dass alle unsere Räume ihre Bodenkollision weit genug über die Kameragrenzen des Raums hinaus ausdehnen müssen ihre Bodenkollision weit genug über die Kameragrenzen des , um zu verhindern, dass die Figur herunterfällt, bevor sie den angrenzenden Raum erreicht. Ich werde die Kamera etwas verkleinern und die Codezeile auskommentieren , die die Kamera an die Grenzen des aktuellen Raums bindet an die Grenzen des aktuellen Raums Beim Ausführen des Spiels können wir sehen, dass der Inhalt des Startraums sofort geladen wird, da sich der Charakter bereits in diesem Raum befand Wenn wir zu dem zweiten Raum wechseln, wird dessen Inhalt geladen, sobald der Spielercharakter den Schwellenwert überschreitet. Wir wollen aber auch den Inhalt des vorherigen Raums, den wir gerade verlassen haben, entladen Inhalt des vorherigen Raums, den wir gerade verlassen Es liegt in der Verantwortung des Spielmanagers, sich um die Übergänge zu kümmern, da dabei viele Komponenten der Spielszene zusammenarbeiten Wir müssen ein Signal von dem Raum, der betreten wurde, an den Spielmanager senden , der sich in unserem Projekt nicht einmal in derselben Szene befindet. Wir werden auch viele verschiedene Räume in unserem Spiel haben und es wäre mühsam , dieses Signal für jeden einzelnen Raum einzeln manuell verbinden zu müssen. Es wäre also einfacher, unsere Skripte zu verwenden, um es zu automatisieren. Aus dem Raumskript fügen wir oben im Skript ein neues Signal hinzu, oben im Skript ein neues Signal das wir aussenden können, um mitzuteilen, dass der Spielercharakter diesen Raum mit dem Raum betreten hat , der als Parameter eingegeben wurde. Wenn dann das vom Körper eingegebene Signal empfangen wird, senden wir dieses Signal aus, anstatt den Inhalt zu laden , und geben diesen Raum selbst als Argument weiter. Wenn dieser Raum fertig ist, können wir auf den Stamm der Szenenbäume zugreifen, indem wir eine Puppe starten oder den annotierten Knotenpfad mit einem Schrägstrich, dann dem Wort root und einem weiteren Schrägstrich kennzeichnen dann dem Wort root und einem weiteren Schrägstrich Von der Wurzel des Szenenbaums aus heißt der erste Knoten, auf den wir zugreifen wollen, Spiel, so wie er in der Spielszene benannt ist Dadurch erhalten wir Zugriff auf das Game Manager-Skript mit einem Punkt. Dann können wir auf eine Funktion verweisen, die wir noch nicht geschrieben haben. Rufen wir es an, wenn der Spieler den Raum betreten hat. Dann können wir diese Funktion mit einem passenden Raumparameter in das Game Manager-Skript schreiben . Ich nenne es Room Entered , um es in diesem Zusammenhang klarer zu machen. Um den Inhalt des vorherigen Raums zu entladen, müssen wir wissen, was der vorherige Raum war, also benötigen wir eine Variable für den Raum, in dem sich der Spielercharakter gerade befindet Ich ersetze dieses aktuelle Level durch das aktuelle Zimmer und lasse es leer Ich benötige das On Ready-Etikett nicht mehr. Als erstes sollten wir überprüfen, ob der Raum, der betreten wird, derselbe ist wie der Raum in dem sich der Spielercharakter gerade befindet. In diesem Fall müssen wir nicht wirklich etwas tun und können diese Funktion einfach verlassen. Jetzt können wir davon ausgehen , dass der aktuelle Raum und der eingegebene Raum unterschiedliche Räume sind. Beim ersten Start des Spiels gibt es keinen aktuellen Raum. Wir werden zuerst prüfen, ob der aktuelle Raum nicht Null ist. Wenn es einen aktuellen Raum gibt, sollten wir ihn mit der Funktion, die wir im vorherigen Video geschrieben haben, anweisen, seinen Inhalt zu entladen mit der Funktion, die wir im vorherigen Video geschrieben haben, anweisen, seinen Inhalt im vorherigen Video geschrieben haben dann den aktuellen Raum dem Raum zuweisen, den wir betreten haben, können wir diesen aktuellen Raum anweisen, seinen Inhalt zu laden und schließlich die Kamera an die Grenzen des aktuellen Raums zu binden Aber ich werde das auskommentieren, damit wir sehen können, was mit dem verkleinerten Bild passiert Wenn wir jetzt das Spiel starten, sendet das Betreten des zweiten Raums ein Signal an den Spielmanager, den Inhalt des Startraums zu entladen, bevor der Inhalt des zweiten Raums geladen Wir haben jetzt mehrere Räume in unserem Spiel, aber das Parallax-Scrolling im Vordergrund und Hintergrund funktioniert nicht für Räume, die nicht um den Ursprung der Szene herum zentriert sind um den Ursprung der Szene herum zentriert Wir sehen uns im nächsten Video. 31. 4-3 Parallaxe: Hallo Freunde. In diesem Video korrigieren wir das Parallax-Scrolling von Vordergrund und Hintergrund mit einem benutzerdefinierten Skript Ab der zweiten Raumszene kopiere ich alle meine Modulationsfarben von den Parallax-Tut-Knoten auf ihre untergeordneten Knoten Dann kann ich das Parent der Sprites aufheben und die Parallax-Tut-Knoten löschen , während beibehalte Ich füge dann einem dieser Sprites ein neues Skript hinzu, nenne es Parallax und lege es Das gleiche Skript kann an alle Sprites angehängt werden , die ich an Parallax haben möchte Um ein benutzerdefiniertes Verhalten zu erstellen, ist es hilfreich, sich etwas Zeit zu nehmen, um darüber nachzudenken , was Sie erreichen möchten, welche Knotenreferenzen und andere Informationen erforderlich Ich habe eine Reihe verschiedener Sprites. Ich möchte mich relativ zur Position der Kamera unterschiedlich bewegen , und ich weiß, dass sich die Kamera derzeit innerhalb der Grenzen dieses Raums befindet derzeit innerhalb der Grenzen dieses Raums Ich füge der Szene vorübergehend einen Kamera-D-Node hinzu und zoome ihn um den Faktor zwei heran zu tun, als ob es sich um die Spielszene handelt Wenn sich die Kamera genau in der Mitte dieses Raums befindet, wollte ich alles genau so zeichnen, wie es ist Wenn sich die Kamera jedoch von der Mitte wegbewegt, verschiebe ich alle Parallax-Sprites um einen relativen Betrag, wobei die Hintergrundelemente weniger bewegen als die Kamera und die Vordergrundelemente sich in die entgegengesetzte Richtung bewegen Dazu muss jedes Sprite die Position der Kamera relativ zur Raummitte sowie seine eigene ursprüngliche Position kennen Position der Kamera relativ zur Raummitte sowie seine eigene Im Parallax-Skript deklariere ich eine exportierte Variable, deklariere ich eine exportierte Variable die den Faktor enthält, um den sich das Sprite relativ zur Kamera bewegt, und nenne sie Scroll-Skala als Vektor 2. Das funktioniert ähnlich wie die Scroll-Skalenvariable im Parallax-Zwei-D-Knoten Wenn dieser Raum in den Szenenbaum geladen ist, können wir das Tag on ready verwenden, um seine Position zu ermitteln und sie als ursprüngliche Position in einer Variablen zu speichern Dank der Viewport-Funktion von Node G ist es einfach, einen Verweis auf die aktuelle Kamera zu erhalten Dank der Viewport-Funktion von Node G ist es einfach, einen Verweis auf die aktuelle Kamera zu den Viewport zurück, in dem sich dieser Node befindet, auch über die Funktion Get camera to D verfügt , um die Kamera abzurufen Wir können dies auch in einer Variablen speichern, indem wir das Tag on ready verwenden Wenn wir die Prozessfunktion außer Kraft setzen, benötigen wir Delta nicht und können sie als unbenutzt markieren Ich setze die Position des Sprites einfach auf seine ursprüngliche Position plus den Abstand der Kamera vom Mittelpunkt des Raums, multipliziert mit der Scroll-Skala Jetzt benötigt die Kamera nur noch eine öffentliche Funktion, die uns ihre Position relativ zum Mittelpunkt des aktuellen Raums mitteilen kann uns ihre Position relativ zum Mittelpunkt des aktuellen Raums mitteilen relativ zum Mittelpunkt des aktuellen Raums Wenn ich zum Kameraskript übergehe, schreibe ich diese Funktion, Offset vom Mittelpunkt, was der Position der Kamera plus ihrem Offset minus dem Mittelpunkt des Wenn ich dies als neue Variable deklariere, kann ich sie als Durchschnitt der oberen linken und unteren rechten Ecke des Raums berechnen , wenn ich sie mit der Funktion „Grenzen setzen “ akzeptiere Funktion „Grenzen setzen Wir könnten diese Funktion so ändern , dass sie den Mittelpunkt und die Größe des Rechtecks akzeptiert und nicht die obere linke und untere rechte Ecke, aber das würde sowieso keinen Unterschied in der Effizienz machen , also werde ich mich Jetzt können wir die Scroll-Skala für jedes der Parallax-Sprites so einstellen , dass sie jeweils einen anderen Abstand zur sie jeweils einen anderen Abstand Ich verwende weiterhin nur die horizontale Parallaxe gebe meinen Hügeln eine Scroll-Skala von einem Drittel entlang der X-Achse und den weiter hinten liegenden Hügeln zwei Für den Vordergrund müssen sie sich in die entgegengesetzte Richtung bewegen wie die Kamera Sie haben eine Bildlaufskala von minus einem Drittel und minus zwei Dritteln Das wird ausreichen, um die Illusion von Tiefe in unseren Räumen zu erzeugen. das Spiel ausführen, können wir in den zweiten Raum gehen und sehen, dass der Parallax-Effekt dem des Startraums identisch aussieht, obwohl er von einem sehr einfachen Skript ausgeführt wird Da sich die Sprites im Vordergrund in die entgegengesetzte Richtung der Kamera bewegen, müssen sie entweder ihre Position wiederholen und umdrehen, sodass eine Endlosschleife entsteht, oder wir können das Sprite einfach größer als den Raum machen Wenn ich meine Sträucher 1,5-mal länger mache als der Raum und das Gras doppelt so lang wie der Raum, bleibt auf beiden Seiten genug übrig , sodass die Kanten nie die Sicht der Kamera erreichen A Es wäre möglich, den Parallax-Zwei-D-Knoten zu verwenden, um Vordergrund und Hintergrund in einem separaten Viewport zeichnen und sie auf verschiedenen Leinwandebenen zeichnen oder zu versuchen, den aktuellen Raum immer am Ursprung der Spielszene Diese Lösungen würden später zu weiteren Komplikationen und Einschränkungen führen , wenn es beispielsweise darum geht , die Karte des Spiels zu zeichnen Ich finde es manchmal einfacher, benutzerdefinierte Lösungen wie diese zu schreiben , als die bereitgestellten Knoten zu verwenden. Die Lösung speichert auch alles für einen Raum an einem Ort, was es einfacher macht, Räume intuitiver zu entwerfen und zu bauen. Ich benötige diesen Kamera-Tuti-Knoten nicht mehr, also lösche ich ihn die Wolken vom Parallax-Touti-Knoten entfernen, können wir das Parallax-Skript ändern und die auch automatisch scrollen das Wrect-Gebiet erweitern, müssen wir nur den Expositionswert mit der Zeit verringern, um die Wolken nach rechts zu verschieben verringern, um die Wolken nach rechts zu das Parallax-Skript an diesen Knoten anhängen, können wir zunächst seine Scroll-Skala auf eins setzen , sodass sie der Bewegung der Kamera entspricht Dadurch erscheinen die Wolken im Vergleich zu den Parallax-Hügeln unendlich weit entfernt einen weiteren Vektor zwei für die automatische Scrollgeschwindigkeit exportieren, müssen wir jetzt Delta in der Prozessfunktion verwenden und können den Unterstrich entfernen auf die Eigenschaft region rect und ihre Position zugreifen, beginnend mit dem X, subtrahieren wir den AutoScrollX-Wert Dadurch wird die Geschwindigkeit des Autoscrollens auf Pixel pro Sekunde erhöht. Ordnen Sie das Ergebnis dann der Region recs X-Position zu. Wenn wir dies jedoch über einen sehr langen Zeitraum ausführen würden, würde sich diese Zahl den Grenzwerten einer Fließkommazahl nähern und könnte zu Problemen führen Der Wert der X-Position entspricht der Größe, das Ergebnis ist tatsächlich dasselbe. wäre es besser, die X-Position wieder auf Null zurückzusetzen diesem Fall wäre es besser, die X-Position wieder auf Null zurückzusetzen, damit wir das für unendlich lange Zeit wiederholen können . Mit der AP F-Funktion können wir einen Minimal - und Maximalwert angeben, um den Wert so zu begrenzen, dass er nur zwischen Null und der Größe der Aufnahme liegt. Diese Funktion gibt ein Ergebnis zurück , das zwischen diesen beiden Werten liegen muss, aber im Gegensatz zu Clamping wird der Rest immer noch im Ergebnis enthalten sein. Und wir können dasselbe tun, wenn wir das vertikale automatische Scrollen verwenden wollen Ich gebe den Wolken zur Demonstration einen großen automatischen Bildlauf entlang des X. Und wenn wir das Spiel starten, scrollen die Wolken automatisch nach rechts und drehen sich in einer Endlosschleife Mama. Mama. Ich setze den Auto-Scroll-Wert wieder auf einen vernünftigen Wert zurück. Wir haben jetzt das Parallax-Scrollen im Vordergrund und im Hintergrund für beide Räume Die Übergänge zwischen den Räumen erfolgen jedoch sehr plötzlich. Wir sehen uns im nächsten Video. 32. 4-4 Übergang: Hallo Freunde. In diesem Video werden wir den Übergang zwischen Räumen mit einem einfachen Übergang zu Schwarz glätten. In der Spielszene beginnen die meisten Spiele entweder mit einem Ladebildschirm oder komplett schwarz und werden dann ausgeblendet, wenn das Spiel gestartet wird. der Canvas-Ebene einen Knoten hinzufügen, können wir einen farbzerstörten Knoten verwenden , um einfache Farben einfach zu zeichnen den Layout-Bereich erweitern, ändern wir die Voreinstellung für Anker auf Full Wreck Dadurch wird die zerstörte Farbe angewiesen, die gesamte Leinwand auszufüllen Es ist derzeit weiß, aber Schwarz ist üblicher, sodass wir die Farbe oben auf Schwarz ändern können Wenn das Spiel beginnt, müssen wir diese Farbe nur schrittweise von Schwarz zu Durchsichtig ändern, sodass Sichtfenster der Kamera dahinter sichtbar In unseren kleinen, einfachen Räumen werden sie sofort geladen. Das Laden und Entladen von Rauminhalten verursacht derzeit keine Verzögerung Wenn wir uns aber vorstellen, dass unsere Räume aus viel mehr Sprites bestehen werden und vor allem Soundeffekte und Hintergrundmusik geladen werden, führt das dazu, dass das Laden des Raums länger dauert als ein einzelnes Bild Wir können denselben Effekt auch rückwärts verwenden, um zu Schwarz zu wechseln, unseren Raum zu entladen und zu laden und dann wieder einzublenden, wenn alles fertig ist Dieses Projekt wird nicht so groß werden , dass wir einen echten Ladebildschirm benötigen Benennen wir diesen Node Fade um und geben ihm einen eindeutigen Namen. Wir müssen sicherstellen, dass dieser Knoten am unteren Rand des Szenenbaums bleibt damit er über alles andere gezeichnet werden kann, oder wir müssen seinen Z-Index erhöhen. Dieses große schwarze Rechteck in der Spielszene kann die Arbeit an anderen Dingen behindern. Vielleicht möchten wir, dass dieser Knoten standardmäßig ausgeblendet wird. Wenn ich ein Skript an diesen Knoten anhänge, nenne ich es fade und speichere es im Ordner scripts ich die Ready-Funktion überschreibe, möchte ich als Erstes ihre Eigenschaft visible auf true setzen, sodass alles schwarz dargestellt wird ihre Eigenschaft visible auf true setzen, sodass alles schwarz dargestellt Wir benötigen zwei öffentliche Funktionen, um die Farbe entweder auf Schwarz oder Transparent einzustellen Um den Wert einer Eigenschaft im Laufe der Zeit anzupassen, ist es am einfachsten, ein Tween zu verwenden Also werden wir eine als Variable deklarieren. Ich erwarte zwar nicht, dass das Fading mehr als einmal in schneller Folge erlaubt wird, es ist trotzdem eine gute Idee, zu überprüfen, ob das Tween bereits existiert, und es für alle Fälle zu beenden Dann erstelle ein neues Tween. Hier sind keine ausgefallenen Übergangs - oder Lockerungsarten erforderlich, ein lineares Tween funktioniert einwandfrei wird dieser Knoten selbst, seine Farbeigenschaft und seine Farbe so verändert dass er im Laufe der Zeit transparent ist. Vorerst werde ich 1 Sekunde warten. In der Klasse ist eine transparente Farbe definiert, aber wenn wir mit der Maus darüber fahren, können wir sehen, dass sie Rot-, Grün - und Blauwerte von Eins hat, was bedeutet, dass es sich um transparentes Weiß und nicht um transparentes Schwarz handelt Dadurch wird nicht der gewünschte Effekt erzielt, also definiere ich meine eigene transparente Farbe als Konstante und nenne sie klar Es ist üblich, bei der Benennung von Konstanten ausschließlich Großbuchstaben zu verwenden üblich, bei der Benennung von Konstanten Dies wird eine Farbe mit Null Rot-, Grün-, Blau- und Alphawerten Wir können auch eine Konstante für die Dauer des Tweens definieren und die 1 Sekunde durch diese Konstante ersetzen Dies macht es etwas einfacher, die Dauer zu ändern, ohne das Skript durchsehen zu müssen und ohne eine Variable für etwas zu exportieren, das Sie für Ihr gesamtes Projekt konsistent halten möchten Ihr gesamtes Projekt Für die Funktion Feed to Black könnten wir den gesamten Code kopieren und einfügen und dabei nur das Endwertargument des Funktionsaufrufs der Eigenschaft Tween ändern , aber es wäre besser, Redundanz zu vermeiden Stattdessen machen wir daraus eine eigene private Funktion namens tween color, private Funktion namens tween color, akzeptieren die endgültige Farbe als Parameter übergeben sie dann als Argument an den Funktionsaufruf der Eigenschaft Tween Funktionsaufruf der Eigenschaft Dann können sowohl die Funktion Fate to Black als auch zwei Clear-Funktionen diese Funktion aufrufen und dabei unterschiedliche Argumente übergeben Im Game Manager-Skript finden wir oben einen Verweis auf den Fade-Knoten. Wenn der Spielercharakter einen Raum betritt , nachdem er den Rauminhalt geladen hat, können wir sagen, dass der Fade zu Tween seine Farbe auflöst. Wenn das Spiel zum ersten Mal startet, gibt es keinen aktuellen Raum zum Entladen, also wird dieser sofort eingeblendet Nachdem wir den zweiten Raum betreten haben, sollten wir ihn zu Schwarz verblassen lassen bevor wir den Inhalt des aktuellen Raums entladen Dann fahren wir mit dem Laden des zweiten Raums fort und blenden Diese Funktion wartet jedoch nicht ab, bis der Tween fertig ist, bevor der Inhalt des Raums entladen wird Sie wird es sofort tun. Um diese Funktion anzuhalten, während das Tween schwarz wird, können wir das Schlüsselwort await verwenden Auf Await folgt ein Signal. Das Signal, auf das wir warten wollen, ist das fertige Signal des Tweens im Fade-Skript Wir können dieses Signal also von unserer Tween-Funktion zurückgeben. Änderung des Rückgabetyps unserer Funktion von void auf signal Das gleiche Rücksignal wird durch die Funktionen „Fade to Black“ und „Clear“ erneut weitergeleitet. Zurück im Game Manager-Skript kann der Game Manager jetzt jederzeit auf dieses Signal zugreifen , wenn er diese Funktionen aufruft. Wir können warten, bis es schwarz wird, oder darauf, dass das Ausblenden gelöscht wird. Diese Funktion wird also pausieren und warten, bis der Tween beendet ist, bevor wir fortfahren Wir wollen generell nicht, dass der Spieler währenddessen die Kontrolle über den Charakter hat Deshalb können wir vor dem Start des Übergangs oben in der Funktion den Spielerpunkt Disable aufrufen vor dem Start des Übergangs oben in der Funktion den und den Spielerknoten am Ende wieder aktivieren und den Spielerknoten am Ende , nachdem der Übergang abgeschlossen ist. Ich habe vergessen, diese Richtungsvariable auf die Bewegungsrichtung zu aktualisieren , als ich sie umbenannt habe. Diese Räume sind zwar recht klein und sollten recht schnell be- und geladen werden, aber wir können vielleicht trotzdem einen Fall sehen, in dem der vorherige Raum entladen wird und weil es kein Terrain gibt , auf dem der Charakter stehen kann, fallen sie durch den Boden, bevor der Inhalt des nächsten Raums geladen wird, um eine neue Etage zu schaffen Deshalb sollten wir den Charakter gleichzeitig deaktivieren und aktivieren wie den Spielerknoten Eine andere Möglichkeit, Knoten zu aktivieren und zu deaktivieren , besteht darin, ihre Prozessmodus-Eigenschaft zu ändern. Wenn der Übergang beginnt, deaktiviert, und dann erben, wenn der Übergang abgeschlossen ist Jetzt kann der Spieler den Charakter nicht mehr kontrollieren und der Charakter wird beim Übergang zwischen Räumen nicht von der Schwerkraft beeinflusst beim Übergang zwischen Räumen nicht von der Schwerkraft Als Nächstes werden wir daran arbeiten, unsere Räume auf einer Karte zu zeichnen. Wir sehen uns im nächsten Video. 33. 4-5 Ansichtsfenster: Hallo Freunde. In diesem Video beginnen wir damit, unsere Räume auf einer Karte zu zeichnen. Es ist zwar möglich, die Karte getrennt von der Spielwelt zu zeichnen , aber es ist viel aufwändiger, Konsistenz zwischen der Welt und der Karte aufrechtzuerhalten , wenn Sie beide bei jeder Änderung separat aktualisieren müssen . Positionieren von Symbolen auf der Karte, insbesondere von Symbolen, die sich wie der Spielercharakter bewegen können, kann zu einer noch schwierigeren Aufgabe werden Eine viel einfachere Methode, eine Karte zu erstellen, besteht darin, einfach eine zweite Kamera zu haben eine zweite Kamera die Welt aus einer vergrößerten Perspektive zu betrachten, aber die Welt und ihren Inhalt auf einfachere Weise zu zeichnen Lassen Sie uns also eine weitere Kamera zu unserer Spielszene hinzufügen und diese in Kartenkamera umbenennen Standardmäßig wird nur die erste Kamera verwendet und sie zeichnet das Hauptfenster des Spiels Um die Karte zu zeichnen, muss die Kartenkamera einen anderen Viewport zeichnen, also fügen wir einen als Knoten im Szenenbaum hinzu , der ein untergeordneter Viewport-Knoten ist Benennen Sie es in Map Viewport um und geben Sie ihm einen eindeutigen Namen. In einigen unserer Skripte haben wir bereits die G-Viewport-Funktion verwendet, haben wir bereits die G-Viewport-Funktion verwendet um den Haupt-Viewport des Spiels zu ermitteln , der zum Zeichnen der beiden D-Welten des Spiels verwendet wird Die Zwei-D-Welt ist in diesem Kontext nicht dasselbe wie der Welt-Umgebungsknoten Er enthält alle TD-Knoten, die sich derzeit in der Mitte befinden, einschließlich des Spielmanagers. Wenn wir die Kartenkamera dem Karten-Viewport unterordnen, zeichnet diese Kamera jetzt den Karten-Viewport statt des Haupt-Viewports des Spiels, aber sie hat keine Stelle auf dem Bildschirm, um ihn zu Deshalb müssen wir der Leinwandebene einen Knoten hinzufügen, der die Textur beschädigt hat , damit die Kamera den Viewport zeichnen kann Nennen wir das Ganze Map-Viewport-Textur. Ich entferne all diese Dummy-Steuerknoten und stelle sicher, dass der Knoten dem die Textur beschädigt wurde, vor dem Fade-Knoten gezeichnet wird , indem ich ihn in der Szenenhierarchie weiter oben positioniere auf das Textur-Dropdown-Menü klicken, können wir die Viewport-Textur auswählen und dann das Map-Viewport auswählen, das als Textur für dieses Textur-Wret gezeichnet werden soll für dieses Textur-Wret gezeichnet Die Größe der Textur wird automatisch Größe des Viewports angepasst Derzeit wird nur die standardmäßige graue Hintergrundfarbe gezeichnet , da die Kartenkamera und das Viewport nichts sehen können Standardmäßig hat jeder Viewport seine eigene Welt. Sie können sich diese Welten wie Parallelwelten oder Existenzebenen vorstellen Parallelwelten oder Existenzebenen Sie können zur gleichen Zeit denselben Raum einnehmen , aber unabhängig voneinander existieren. Aber wir möchten, dass dieser Viewport dieselbe Welt zeichnet wie unser Haupt-Viewport Im Game Manager-Skript holen wir uns einen Verweis auf den Map-Viewport-Knoten Sie dann in der Ready-Funktion die Eigenschaft World Two D des Viewports Wir können auf den Haupt-Viewport zugreifen, indem den Game Manager-Knoten die Funktion „Viewport“ aufrufen dann auf dessen Eigenschaft World Two D zugreifen Jetzt zeichnen sowohl der Haupt-Viewport als auch der Map-Viewport dieselbe Welt Wir möchten generell , dass unsere Karten viel mehr von der Welt zeigen, also stelle ich den Zoom auf ein Achtel ein Wenn wir die Abmessungen der Map-Textur ändern möchten, können wir die Pixelmaße des Viewports festlegen , indem wir es im Szenenbaum auswählen Ich mache die Hälfte der Abmessungen meines Spiels auf 640 mal 360 Pixel Anstatt diese graue Farbe zu zeichnen, wenn nichts da ist, würde ich es vorziehen, wenn der Hintergrund meines Map Viewports transparent ist Ich schalte den transparenten Hintergrund ein. Dadurch ist die Karte jedoch schwer lesbar. Ich möchte, dass diese Kartentextur in einem Panel enthalten ist, damit sie vom Hauptspiel getrennt erscheint der Canvas-Ebene einen Panel-Container hinzufüge, ordne ich die Map-Textur so an , dass sie ein untergeordnetes Element des Panel-Container-Knotens Dann benenne ich den Panel-Container Map um und gebe ihm einen eindeutigen Namen Mit dem Standarddesign zeichnet der Panel-Container eine transparente schwarze Farbe . Da es sich um einen Container handelt, passt er seine Größe automatisch an, sodass er auch seine untergeordneten Objekte enthält Dadurch wird deutlich , dass die Map-Textur auf der Leinwand gezeichnet wird nicht als Teil der Welt, und wir können das Aussehen des Panel-Containers später über den Theme-Editor anpassen Aussehen des Panel-Containers später über den Theme-Editor Ich verwende die Anker des Panel-Containers , um ihn in der Mitte des Bildschirms zu verankern Wir wollen generell, dass die Kartenkamera dem Spielercharakter folgt , genau wie die Hauptkamera, aber ohne Tweening oder andere Funktionen Im Gegensatz zur Hauptkamera muss die Kartenkamera nie etwas anderes tun, sodass es sicher ist, dass sie immer exakt der Position des Spielercharakters exakt der Position des Spielercharakters Es gibt keine Möglichkeit, die Kartenkamera an den Spielercharakter anzupassen, da sie ein untergeordnetes Element des Karten-Viewports bleiben muss , um die Karte zu zeichnen Wir könnten ein anderes Skript schreiben, um diese Kamera zu bewegen, aber es gibt einen Knoten, den wir verwenden können, um die Dinge einfacher zu machen, den Ferntransformationsmodus von zwei D. Mit der Ferntransformation zwei D als untergeordnetes Element des Spielercharakters können wir seinen entfernten Pfad zur Kartenkamera festlegen Jetzt werden die Transformationseigenschaften, die Position, die Drehung und die Skalierung der Kamera automatisch aktualisiert, sodass sie denen des Spielercharakters entsprechen. Wir können die Rotation und Skalierung ausschalten , indem wir den Update-Bereich erweitern Selbst wenn wir die Rotation oder Skalierung des Spielercharakters bearbeiten würden , würden wir nicht wollen, dass die Karte diese Eigenschaften kopiert Mm. Unsere Spielewelt wird jetzt auf der Leinwand gezeichnet, aber wir wollen lieber eine vereinfachte Version der Welt zeichnen als eine exakte Kopie. Wir sehen uns im nächsten Video. 34. 4-6 Sichtbarkeit: Hallo Freunde. In diesem Video lassen wir die Kartenkamera eine vereinfachte Version der Welt zeichnen. im Startraum und fügen wir vorübergehend den Inhalt des Raums hinzu. Ich möchte nicht all diese Sprites auf die Karte zeichnen, sondern nur einen Umriss der Form und des Geländes des Raums Wir können zwei beliebige D-Knoten verwenden, um dies zu zeichnen, je nachdem, welchen Stil wir wollen Ich verwende einen Ebenenknoten vom Typ „Tile Map“. Geben Sie ihm ein neues Kachelset mit Kacheln, die 32 mal 32 Pixel groß sind. Ich importiere ein neues Sprite, das nur ein einfaches weißes Quadrat mit 32 mal 32 Pixeln Dann füge es dem Kachelset hinzu. dieses weiße Quadrat auf meiner Ebene „Tile Map“ zeichne, zeichne ich einen Umriss des Raums, wobei ich das Gelände als Boden anstelle der Kameragrenze verwende und Türöffnungen lasse, um Verbindungen zu anderen Räumen herzustellen Wir möchten, dass die Hauptkamera nur den Inhalt zeichnet, während die Kartenkamera stattdessen diese Notiz auf der Ebene „Tile Map“ zeichnet Während beide denselben Raum betrachten, werden sie zwei verschiedene Versionen davon sehen. Jetzt, wo ich die Form meines Raums habe, lösche ich den Inhalt aus der Szene. Da der Layer-Knoten „Tile Map immer von der Kartenkamera betrachtet wird, bleibt er immer geladen und wird nicht wie der Inhalt geladen und entladen den Bereich Sichtbarkeit ausdehne, kann ich die Eigenschaft „ Farbe modulieren“ verwenden , um meine weißen Quadrate in farbige umzuwandeln, wenn ich möchte Da dies Teil der Waldregion ist, werde ich die Karte grün zeichnen Damit die Kartenkamera das zeichnet, aber nicht die Hauptkamera, ändere ich ihre Sichtbarkeitsebene 1—2. Die Standardsichtbarkeitsebene 1 ist alles, was von der Hauptspielkamera gezeichnet wird, während Ebene zwei alles ist, was ich auf der Karte zeichnen möchte . Genau wie bei den Kollisionsebenen können wir diese Sichtbarkeitsebenen in den Projekteinstellungen unter Ebenennamen zwei D-Rendern benennen . Ich nenne Ebene eins Welt und Ebene zwei Karte. Diese Sichtbarkeitsebenen hängen von den Sichtbarkeitsebenen ihrer Eltern ab. Wenn der Viewport den Knoten im Startbereich des Raums nicht sehen kann, er sich nicht die Mühe, zu überprüfen, ob er untergeordneten Knoten der Ebene „Tile Map“ sehen kann Die Sichtbarkeitsebene des übergeordneten Knotens des Startraums muss sowohl auf eins als auch auf zwei gesetzt sein, da er untergeordnete Elemente hat, die von beiden Viewports gezeichnet werden können In der Hierarchie nach oben muss die Sichtbarkeit der Waldregion so eingestellt sein, dass beide Sichtbarkeitsebenen verwendet werden, ebenso wie der Stammknoten der Spielszenen Der Weltumgebungsknoten besitzt keine Eigenschaft der Sichtbarkeitsebene. nun den Map-Viewport auswählen, können wir seine Canvas-Aufrufmaske so einstellen , dass nur Ebene zwei und nicht Ebene eins angezeigt Dies funktioniert ähnlich wie die Eigenschaft Kollisionsmaske für Kollisionsobjekte Nur wenn das Bit für die Maske auf eins gesetzt ist, kann sie dann alles sehen, auf dessen Ebene dasselbe Bit auf eins gesetzt ist? Aber wir können nicht vom Editor aus auf den Haupt-Viewport zugreifen , um die Canvas-Aufrufmaske so zu ändern , dass nur Ebene eins und nicht Ebene zwei angezeigt Standardmäßig maskiert es jede Ebene. Also müssen wir es per Skript bearbeiten. In der Skriptbereitschaftsfunktion des Game Managers können wir mit der G-Viewport-Funktion auf den Haupt-Viewport zugreifen und dann dessen Eigenschaft Canvas-Aufrufmaske festlegen Maus über Ebene eins fahren, können wir sehen, dass ihr ganzzahliger Wert ebenfalls eins ist Wir können den Wert der Canvas-Aufrufmasken einfach auf eins setzen. Jetzt wird nur die Sichtbarkeitsebene eins und nicht die zweite Ebene oder eine andere Ebene. kopiere den Ebenenknoten „Tile Map“ im ersten Raum Ich kopiere den Ebenenknoten „Tile Map“ im ersten Raum und füge ihn in den zweiten Raum ein, um diesen Raum auch auf der Karte zu zeichnen. Ich instanziiere den Inhalt des Raums und bearbeite dann die Kacheln, sodass sie die Form dieses Raums genauer wiedergeben . Wenn ich fertig bin, lösche ich den Inhalt Denken Sie daran, die Sichtbarkeitsebene der übergeordneten Knoten so einzustellen , dass sie auf beiden Sichtbarkeitsebenen vorhanden ist, damit die Kinder von ihren jeweiligen Viewports aus gesehen werden können Jetzt sind beide Räume auf der Karte deutlich sichtbar, und das großen Aufwand, wenn wir weitere Räume hinzufügen ohne großen Aufwand, wenn wir weitere Räume hinzufügen. Sie müssen lediglich die Karte für jeden Raum in seiner Szene auf einer separaten Sichtbarkeitsebene hinzufügen jeden Raum in seiner Szene auf einer separaten Sichtbarkeitsebene Wir können der zweiten Karte ganz einfach weitere Dinge hinzufügen, indem ihnen weitere Sprites hinzufügen und sie auf Sichtbarkeitsebene zwei platzieren, wie zum Beispiel ein Symbol für die Charakterkarte eines Spielers die Szene mit den Spielercharakteren öffnen, fügen wir ein Sprite zur Kennzeichnung hinzu und nennen es Ich fülle die Textur mit einer Atlas-Textur, verwende dasselbe Spritesheet und wähle eine Region aus, die als Kartensymbol verwendet werden soll Ich verwende den Kopf des Charakters irgendwo im Spritesheet, wo der Schwanz nicht im Nachdem wir die Textureigenschaft ausgefüllt haben, setzen wir ihre Sichtbarkeitsebene auf zwei und nicht Dann muss der Wurzelknoten dieser Szene sowohl die Ebene eins als auch die zweite Ebene haben Ich passe den Abstand des Sprites an, sodass es wie der Charakter auf dem Boden sitzt. weiß, dass der Zoom der Kamera ein Achtel beträgt, vergrößere ich dieses Symbol um das Achtfache , sodass es in der Szene sehr groß erscheint Da ich nicht möchte, dass dieses Symbol meinen Charakter verdeckt , wenn ich in der Szene arbeite, möchte ich es lieber verstecken . Das gilt dann alles in meinem Spiel, dem ich ein Kartensymbol hinzufügen möchte. Ich füge diesem Knoten ein Skript hinzu und nenne es Kartensymbol. Und ich lasse es einfach die Eigenschaft visibility bei ready auf true setzen. Nun, dieses sehr große Kartensymbol muss nicht im Editor gezeichnet werden während ich an meinem Charakter arbeite, sondern es wird gezeichnet, wenn ich das Spiel starte. Wir haben jetzt unsere Karte, die Umrisse von Räumen und den Spielercharakter mit einem Symbol zeichnet , aber vielleicht möchten wir, dass die Karte mit einer Taste ein- und ausgeschaltet Wir sehen uns im nächsten Video. 35. 4-7 Karte: Hallo Freunde. In diesem Video ermöglichen wir dem Spieler, die Karte mit einer Taste zu öffnen und zu schließen. Ab der Spielszene werde ich die Karte standardmäßig ausblenden, indem ich die Sichtbarkeit des Containerknotens, auf dem sie gespeichert ist, ein- und ausschalte Hängen Sie dann ein neues Skript an den Container an. Ich verwende zwar derzeit dafür einen Panel-Container, muss aber auf keine der Funktionen des Panel-Containers in diesem Skript zugreifen Funktionen des Panel-Containers und kann von dem allgemeineren Steuerelementtyp erben von dem allgemeineren Steuerelementtyp Wenn ich in Zukunft einen anderen Typ von Kontrollknoten verwenden möchte, muss ich mein Skript nicht ändern Dieses Skript benötigt öffentliche Funktionen , um die Map zu öffnen und zu schließen. Um die Dinge einfach zu halten, setze ich die Sichtbarkeit des Knotens entsprechend auf true oder false. Es gibt auch Funktionen zum Ein - und Ausblenden die in der Canvas-Elementklasse definiert sind und dasselbe tun. Es mag zwar sinnlos erscheinen, eine Funktion zu haben , die nur eine andere Funktion aufruft, Ihre Implementierungen in solche öffentlichen Funktionen gekapselt halten , können wir sie in Zukunft problemlos aktualisieren Wir können diesen Funktionen zusätzliche Logik hinzufügen, um Dinge geschehen zu lassen, wenn die Karte geöffnet oder geschlossen wird, oder wir könnten einen Tween verwenden, um die Karte außerhalb des Bildschirms zu verschieben oder sie vergrößern und verkleinern zu lassen, anstatt nur ihre Sichtbarkeit umzuschalten sie vergrößern und verkleinern zu lassen, anstatt nur . Wenn ich diese Änderungen vornehmen möchte, muss ich nur dieses Skript bearbeiten und muss nicht auch das Player-Skript oder andere Skripts bearbeiten , die , Da ich mich entschieden habe, eine Umschalttaste zu verwenden , um die Map ein- und auszuschalten, anstatt Funktionen zum Öffnen oder Schließen aufzurufen, hätte ich lieber eine einzige Umschaltfunktion eine private Variable hinzufüge ob die Map gerade geöffnet ist oder nicht, lasse ich mit der Umschaltfunktion die Map schließen , wenn sie geöffnet ist, oder sie öffnen, wenn sie Dann können die Funktionen Öffnen und Schließen den Wert von Ich öffne entsprechend festlegen Beim Öffnen der Projekteinstellungen der Registerkarte Eingabekarte müssen wir eine neue Eingabeaktion zum Öffnen und Schließen der Map hinzufügen . Ich verwende die Rücktaste und die Auswahltaste auf meinem Controller den meisten Spielen mit dieser Art von Spielkarte kann der Spieler auch die Kamera schwenken Ich habe bereits die Eingaben „Nach oben“ und „Nach unten suchen“. Ich füge einfach Look Left und Look Right hinzu. Mit der linken und rechten Pfeiltaste oder dem nach links oder rechts geneigten rechten Stick auf meinem Controller Im Player-Skript können wir eine Variable exportieren, die einen Verweis auf den Kartenknoten enthält, und diese dann in den Inspektor Sie dann in der Eingabefunktion der Karte mit, Teilen Sie dann in der Eingabefunktion der Karte mit, dass sie ein- oder ausgeschaltet werden soll, wenn die Kartentaste gedrückt wurde Wenn Sie das Spiel starten, wird die Karte versteckt, aber wenn Sie die Kartentaste drücken, wird die Karte angezeigt und durch erneutes Drücken wird sie geschlossen Um die Kartenkamera zu schwenken, müssen wir nur ihren Offset-Wert anpassen. Also geben wir dem Kartenskript einen Verweis auf die Kartenkamera. Hinzufügen einer öffentlichen Funktion namens pan, die ein Vektor-Zwei-Argument für die Richtung akzeptiert, ein Vektor-Zwei-Argument für die Richtung akzeptiert in die die Kamera geschwenkt werden soll. Wir addieren zum Kameraversatz diese Richtung multipliziert mit einer Pan-Geschwindigkeit, und wir können auf Delta zugreifen, obwohl wir uns nicht in einer Prozessfunktion befinden, indem wir die Knotenklassen Get Process Delta t function aufrufen die Knotenklassen Get Process Delta t function diese Pan-Geschwindigkeits-Variable exportiere, setze ich meine auf 1024 Das mag schnell erscheinen, aber denken Sie daran dass die Kartenkamera sehr weit herausgezoomt ist, sodass sie sich scheinbar mit einem Achtel der Geschwindigkeit bewegt Damit das Spielerskript diese Kamera steuern kann, wenn die Map geöffnet ist, muss es wissen können, ob die Map geöffnet ist. Anstatt die Variable is open öffentlich zu machen und jedem anderen Skript zu erlauben, ihren Wert zu ändern, können wir eine Funktion schreiben, die den Wert der Variablen zurückgibt Wenn die Karte geschlossen ist, setze ich den Offset der Kamera wieder auf Null zurück, sodass sie wieder auf dem Spielercharakter zentriert ist. wir zum Spielerskript wechseln, fügen wir in der Prozessfunktion die Steuerelemente für das Schwenken der Karte Aber nur, wenn die Karte geöffnet ist. Wenn die Karte geöffnet ist, weisen wir sie an, zu schwenken. So wie wir die G-Achse verwendet haben, um den Zustand zweier entgegengesetzter Richtungen als Gleitkommazahl zu berechnen, können wir den G-Vektor verwenden, um einen Vektor zwei aus vier Richtungen zu erhalten . Wir müssen ihm nur die Namen der vier Eingabeaktionen geben , die der X- und Y-Achse entsprechen. Schau nach links, schau nach rechts, schau nach oben und schau nach unten. Das letzte Argument ist eine tote Zone, das ist die Mindestlänge des Vektors, der verwendet wird. Wenn der Vektor zu kurz ist, können wir ihn ignorieren, was für Analogsticks nützlich ist , um Drift zu ignorieren. Das wird auf einem Controller zwar keine Probleme bereiten, da ich den rechten Analogstick verwende, aber einem Controller zwar keine Probleme bereiten, da ich den rechten Analogstick verwende, meine PC-Steuerung verwendet die Pfeiltasten sowohl für die Bewegung als auch für das Schauen. Wenn die Karte geöffnet ist, lege ich die restlichen Steuerelemente für das Suchen und die Bewegung in einem Block zusammen, um sie zu überspringen. Wenn du möchtest, dass der Spielercharakter sich weiterhin bewegen und nach oben oder unten schauen kann, während die Karte geöffnet ist, musst du die Eingabeaktionen so ändern , dass sie sich nicht überschneiden. Um zu verhindern, dass sich der Charakter nach dem Öffnen der Karte weiter bewegt, setze ich seine Bewegungsrichtung auf Null, wenn die Karte geöffnet wird. Der Spieler kann jetzt eine Taste drücken, um auf eine Weltkarte zuzugreifen, unsere beiden Räume und die aktuelle Position des Spielers angezeigt werden, und wir können die Kartenkamera schwenken, wenn wir wollen. Im nächsten Abschnitt werden wir damit beginnen, die Statistiken des Spielers im Auge zu behalten und sie auf dem Head-up-Display darzustellen. Wir sehen uns im nächsten Abschnitt. 36. 5-1 HUD: Hallo Freunde. In diesem Video beginnen wir damit, Informationen über den Spielercharakter auf dem Heads-up-Display anzuzeigen. Seit Beginn dieses Kurses wurde Godot 4.6 veröffentlicht Die Aktualisierung des Projekts auf Godot 4.6 hat keine Probleme verursacht, daher werde ich die Lektionen in der aktualisierten Version fortsetzen Ich empfehle nicht, während der Arbeit an einem Projekt auf eine neuere Version einer Game-Engine zu aktualisieren während der Arbeit an einem Projekt auf eine neuere Version einer Game-Engine , es sei denn, Sie haben Versionskontrolle, um bei Bedarf zurückzukehren Ich muss einige UI-Sprites in mein Projekt importieren , um die Charakterstatistiken auf dem In der Spielszene haben wir eine Leinwandebene, die im Inspektor auf Ebene eins eingestellt ist im Inspektor auf Ebene eins eingestellt Das Hauptfenster, in dem die beiden D-Welten des Spiels dargestellt werden, wird als Ebene Null betrachtet Alles in der Zwei-D-Welt des Spiels wird also unabhängig von ihrem Z-Index auf Ebene Null gezeichnet Leinwandebene, Ebene eins, wird all das überziehen, um Dinge wie Menüs und das Kopfdisplay unserer Charaktere wie Gesundheit und Magie zu zeichnen. den Knoten auf der Canvas-Ebene handelt es sich in der Regel um Kontrollknoten von Goy. Sie sind alle mit grünen Symbolen gekennzeichnet, um sie von zwei blauen D-Knoten zu unterscheiden Beginnen wir damit, einen Kontrollknoten als untergeordnetes Element der Canvas-Ebene hinzuzufügen , ihn in HUD umzubenennen, ihn so anzuordnen, dass er sich ganz oben in den untergeordneten Objekten der Canvas-Ebenen befindet, und die Map zu einem untergeordneten Element des HUD machen Anschließend können wir diesem übergeordneten Knoten so viele Symbole, Messanzeigen und Text hinzufügen, wie wir benötigen, um unser Head-up-Display zu erstellen Es ist aus mehreren Gründen hilfreich, wenn ein einfacher Kontrollknoten als übergeordneter Knoten für dein gesamtes HUD fungiert mehreren Gründen hilfreich, wenn ein einfacher Kontrollknoten als übergeordneter Knoten für dein gesamtes HUD Einige Eigenschaften des übergeordneten HUD-Knotens werden von allen untergeordneten Knoten übernommen Da der Canvas-Layer-Knoten kein Kontrollknoten ist, hat er nicht dieselben Eigenschaften kann daher diesen Vorteil nicht bieten Wenn Sie all Ihren HUD-Elementen ein einheitliches Erscheinungsbild verleihen möchten , können Sie dem übergeordneten Knoten ein Thema hinzufügen, das angewendet wird automatisch auf alle untergeordneten Knoten Außerdem bleibt der Überblendungsübergang auf natürliche Weise am unteren Rand des Szenenbaums stehen, da du nur übergeordnete Objekte hinzufügst, sodass du dir nicht jedes Mal Gedanken darüber machen musst den Szenenbaum neu anzuordnen Im Gegensatz zu zwei D-Knoten, die anhand ihrer Eigenschaft „ Transformationsposition definieren, wo sie sich relativ zum Ursprung der Szene befinden, verwenden Kontrollknoten sowohl eine Position eine Größe, um ihre Position innerhalb eines definierten Raums zu definieren Normalerweise das Spielfenster, das als dieses blaue Rechteck angezeigt wird. Wir können sehen, dass der HUD-Knoten eine Größe von 40 mal 40 Pixeln hat und sich an Position 00 befindet, was der oberen linken Ecke des Fensters entspricht Wir können den Kontrollknoten zwar einfach verschieben und seine Größe ändern, indem wir diese Werte bearbeiten, diese Änderungen lassen sich nicht gut skalieren oder funktionieren effektiv, wenn wir die Fenstergröße in den Projekteinstellungen ändern würden die Fenstergröße in den Projekteinstellungen Kontrollknoten haben also diese grünen Anker, mit denen wir die Position und Größe jedes Kontrollknotens relativ zu seinem übergeordneten Knoten festlegen können die Position und Größe jedes Kontrollknotens relativ zu seinem übergeordneten Knoten festlegen jedes Kontrollknotens relativ zu seinem übergeordneten Knoten , wobei die Leinwandebene das gesamte Fenster darstellt Wir möchten, dass das HUD das gesamte Fenster abdeckt, sodass wir voreingestellten Anker auf Full Wreck setzen können Dadurch werden die Anker an jeder der vier Ecken des Fensters platziert und die werden dann automatisch entsprechend aktualisiert Werte für Größe und Position Wenn wir die Karte sichtbar machen, wurde ihre Position nicht aktualisiert, daher setze ich ihre Anker auf die Mitte zurück Jetzt können wir sehen, dass die Karte , da sie in der Mitte des übergeordneten Knotens verankert ist , Verschieben oder Ändern der Größe des HUD-Knotens durch Verschieben oder Ändern der Größe des HUD-Knotens so verschoben wird, dass sie zentriert Um die Gesundheit und Magie des Charakters darzustellen, füge ich einen neuen Kontrollknoten hinzu, in dem diese Elemente gruppiert werden, und ich nenne ihn „lebenswichtig Ich lasse ihn oben links verankert, setze aber seine Größe auf Null zurück Als Nächstes füge ich einen Knoten mit zerstörter Textur hinzu, um eine einfache Textur, ein Profil des Charakters, zu zeichnen und seine Textureigenschaft aufzufüllen, und seine Textureigenschaft aufzufüllen indem ich das Asset aus der Registerkarte „Dateisystem“ ziehe einen weiteren Knoten mit zerstörter Textur hinzufüge, nenne ich dieses Gesundheitssymbol und füge seiner Textur eine nenne ich dieses Gesundheitssymbol und füge seiner Textur eine Atlas-Textur hinzu. Dabei wähle ich ein Sprite aus meinem Spritesheet Spritesheet Ich benötige mehrere davon , um die Gesamtgesundheit meines Charakters darzustellen Also werde ich es ein paar Mal duplizieren und sie grob nacheinander positionieren. Es wäre eine gute Idee , diese Symbole unter einem einzigen übergeordneten Knoten zusammenzufassen. Also füge ich einen weiteren Kontrollknoten mit dem Namen Health Counter hinzu und ordne alle Gesundheitssymbole so an, dass sie diesem Knoten untergeordnet Jedes dieser Symbole manuell zu positionieren ist ziemlich mühsam Godot stellt also Kontrollknoten sogenannte Container, zur Verfügung , um dies für uns zu erledigen Da ich möchte, dass diese Symbole horizontal angeordnet werden, ändere ich den Typ des übergeordneten Knotens in einen horizontalen Box-Container Dadurch werden alle untergeordneten Knoten automatisch angeordnet. Sie werden so gestreckt, dass sie die vertikale Höhe des horizontalen Box-Containers ausfüllen , der die Standardgröße von 40 Pixeln hat dieser Wert zurückgesetzt wird, wird er gezwungen, auf die Größe des größten Kindes herunterzufahren auf die Größe des größten Ich möchte, dass sie näher beieinander liegen. Deshalb stelle ich unter „Theme-Overrides “ -Abschnittskonstanten den Abstand auf Das Hinzufügen weiterer Symbole zu diesem Zähler ist so einfach wie das Duplizieren des Es ist eine gute Idee, Ihre HUD-Elemente unter Berücksichtigung ihrer maximalen Grenzwerte Ich werde also neun Gesundheitssymbole haben. Das ist die maximale Anzahl, die ich in mein Spiel integrieren möchte Wenn Sie einen der untergeordneten Knoten auswählen, können deren Positionswerte nicht mehr manuell bearbeitet werden, da der Containerknoten jetzt für die Steuerung ihrer Position zuständig ist . Behalten Sie also diese Einschränkung im Hinterkopf. Wenn Sie die Positionen dieser Texturen einzeln animieren wollten , könnten Sie das nicht tun , solange sie sich in einem übergeordneten Container befinden Als Nächstes füge ich einen weiteren Knoten hinzu, der die Textur zerstört hat , um die magische Leiste des Charakters zu zeichnen Füllen Sie dann die Textureigenschaft mit dem Asset aus der Registerkarte „Dateisystem Diese Textur dient zwar nicht als Maßstab, aber sie hilft, alles, was Sie auf Ihrer Motorhaube haben möchten, zu zeichnen , damit Sie sich vor der Implementierung ein Bild davon machen können, wie es aussehen soll vor der Implementierung ein Bild davon machen können, wie es aussehen Wie bei den Gesundheitssymbolen möchte ich sehen, wie diese magische Anzeige in mein Layout passt , wenn sie ihre maximale Grenze erreicht hat. dieses Bild dehnen, um die Anzeige zu verlängern die einzelnen Pixel des Bildes gestreckt , was schlecht aussieht. Wir werden uns im nächsten Video damit befassen, aber im Moment brauchen wir nur eine Vorstellung davon, brauchen wir nur eine Vorstellung davon wie groß oder klein die Magieanzeige sein kann. Vielleicht möchten Sie sich etwas Zeit nehmen, um das Layout Ihrer Hüttenelemente so zu gestalten, wie Sie es möchten. Dieses Layout sieht gut aus. Aber wenn ich mein Spiel starte, ist es sehr klein und entspricht nicht der Pixeldichte des restlichen Spiels. Da ich einen Kamerazoom von zwei verwende, sind alle meine Pixel doppelt so groß. Also setze ich die Skala meines Vitalknotens auf zwei verdoppele damit die Größe aller seiner Das ist einfacher zu lesen und passt besser zur Ästhetik meines Spiels Wenn wir die Anker-Voreinstellungen des Elternknotens von vitals ändern, können wir ihn leicht ändern, um seine Position relativ zu einer beliebigen Ecke des Bildschirms oder zur Mitte eines beliebigen Randes zu definieren seine Position relativ zu einer beliebigen Ecke des Bildschirms oder zur Mitte eines beliebigen Randes Oder die Mitte des Bildschirms wie auf der Karte. Sie können dann die Positionen der untergeordneten Knoten im Verhältnis zum verankerten übergeordneten Knoten anpassen , sodass sie ihre relative Position beibehalten auch wenn Sie die Auflösung Ihres Spiels ändern Ich lasse meinen in der oberen linken Ecke und gebe ihm 20 Pixel Abstand zum Fensterrand Wir haben jetzt einige Texturen auf dem Head-up-Display gezeichnet, aber sie machen noch nichts Wir sehen uns im nächsten Video. 37. 5-2 Messgerät: Hallo Freunde. In diesem Video implementieren wir den Magic Gauge mithilfe von Style-Boxen. Beginnen wir damit, den Typ des Magic Gauge-Knotens zu ändern. Es gibt einen Kontrollknoten, der genau das tut, was wir brauchen, einen Fortschrittsbalken. Wenn Sie den Typ ändern, wird die Textur entfernt. Der Fortschrittsbalken wird als halbtransparentes graues Rechteck gezeichnet , und ein Prozentwert wird als Text angezeigt. Ich möchte diese Prozentangabe nicht, also deaktiviere ich sie im Inspektor. Der Umschalter „Unbestimmt“ gilt nicht für Messgeräte, sondern für Fortschrittsbalken die eigentlich keinen Fortschritt messen Nachdem wir die Minimal - und Maximalwerte für unsere magische Anzeige festgelegt haben, können wir den Wert auf eine beliebige Zahl dazwischen setzen, um zu sehen, wie sich der Fortschrittsbalken füllt Der Schrittwert ist der kleinste Wert, den der Wert erhöhen kann, wodurch er gezwungen wird, zur nächsten Stufe zu Die anderen Eigenschaften, die aus dem Bereich übernommen wurden für ein Messgerät nicht wirklich geeignet und können ignoriert werden Wir können auch die Richtung ändern, in der der Fortschrittsbalken gefüllt wird, wenn wir möchten. Ich lasse meinen von Anfang bis Ende stehen. Wie der Fortschrittsbalken aussieht , hängt vom Thema ab. Da wir noch kein Thema haben, wird das von Godot bereitgestellte Standarddesign verwendet Wenn wir nur das Thema für diesen Knoten selbst ändern möchten , können wir den Abschnitt „ Theme-Overrides“ erweitern Da ich die prozentuale Textanzeige nicht verwende, die Farben, Konstanten, sind die Farben, Konstanten, Schriftarten und Schriftgrößen irrelevant. Sie können sie jedoch verwenden, um zu ändern, wie die Schrift auf Ihrem Fortschrittsbalken geschrieben wird, wenn Sie möchten Im Bereich „Stile“ finden Sie die Stilfelder für die Darstellung des Hintergrunds und der Füllung der Fortschrittsbalken. auf das Drop-down-Menü klicken, können wir ein leeres Stilfeld auswählen, wodurch einfach nichts gezeichnet wird. Stylen Sie die Box-Linie, um nur eine einfache Linie zu zeichnen, stylen Sie die Box flach, um ein einfaches Rechteck zu zeichnen , oder stylen Sie die Box-Textur, um ein importiertes Textur-Asset zu verwenden. auf die Style-Box-Textur klicken um ihre Eigenschaften zu erweitern, können wir die Textureigenschaft mit einem Asset aus der Registerkarte Dateisystem füllen mit einem Asset aus der Registerkarte Dateisystem Wenn wir die Größe des Fortschrittsbalkens ändern, wird die Textur so gestreckt, dass sie den Raum ausfüllt, was nicht sehr gut aussieht Style-Boxen verfügen über mehr Eigenschaften , mit denen Sie ändern können, wie das Bild gezeichnet wird, wenn es gestreckt wird. die Texturränder wird die Textur in neun Segmente umgewandelt Durch die Texturränder wird die Textur in neun Segmente umgewandelt. Dabei wird das Bild zweimal horizontal und zweimal vertikal aufgeteilt, sodass es in neun Segmente aufgeteilt wird Die Ecken werden nicht gestreckt. Die Kanten werden nur in eine Richtung gestreckt , um die Ecken miteinander zu verbinden, und die Mitte wird in beide Richtungen gestreckt , um den Rest des Raums auszufüllen. Oder wir können das Zeichnen der Mitte der Textur ausschalten und nur die Ränder zeichnen Wenn Sie nicht möchten die einzelnen Segmente gestreckt werden, Eigenschaften für die Achsenstreckung bieten Ihnen die Eigenschaften für die Achsenstreckung die Option, stattdessen Kachelung zu verwenden, oder bei der Option „Kachelanpassung“ wird eine Kombination aus Kachelung und Dehnung verwendet , um dem zugewiesenen Raum optimal zu entsprechen Erweitern der Ränder wird die Textur über das Rechteck hinaus gezeichnet , das durch die Position und Größe der Knoten definiert durch die Position und Größe der Knoten Eine Unterregion kann verwendet werden , um einen Bereich eines Spritesheets zu zeichnen Modulate funktioniert genauso wie die Sichtbarkeit des Canvas-Elements. Dabei wird die Farbe jedes Pixels mit dieser Farbe multipliziert Inhaltsränder sind für Stilfelder vorgesehen, die zum Zeichnen von Containerknoten verwendet werden, sodass sie hier nicht relevant sind Wenn Sie eine weitere Style-Box-Textur für die Fortschrittsbalken hinzufügen , füllen Sie sie und füllen Sie sie mit der entsprechenden Textur Wenn Sie die Texturbereichswerte nicht manuell eingeben möchten , können Sie den Unterregionseditor auch verwenden, um die Texturränder visuell zu bearbeiten Bei Verwendung dieser Elemente der Magic Gauge nicht dazu gedacht , vertikal gestreckt zu werden. Ich stelle die Höhe auf 16 Pixel so ein, dass sie der Höhe der Elemente entspricht . Mithilfe der Stilfelder kann das Messgerät jedoch horizontal beliebig weit gestreckt werden , und es wird ohne Dehnung der Pixel gezeichnet. Der Wert kann auch bearbeitet werden, und die Fülltextur wird ebenfalls so weit wie nötig gedehnt ohne dass die Enden des Balkens gestreckt werden. Wenn wir möchten, dass diese Stilfelder auf mehr als nur einen Fortschrittsbalken angewendet werden, können wir dies automatisch machen, indem wir das Design bearbeiten , anstatt Theme-Overrides zu verwenden den HUD-Knoten auswählen und dann den Themenbereich erweitern, können wir aus der Drop-down-Liste ein neues Thema erstellen Wenn Sie auf die Themenressource klicken, wird das Themenfenster am unteren Rand des Editorfensters geöffnet. Hier können wir die meisten Kontrollknoten sehen, die Godot zu bieten hat , und wie sie derzeit vom Thema gezeichnet werden , einschließlich eines Fortschrittsbalkens hier. auf die Plus-Schaltfläche klicken, können wir diesem Thema einen Fortschrittsbalken hinzufügen und seine Designeigenschaften überschreiben , genauso wie wir es im Inspektor für den Fortschrittsbalkenknoten getan haben Für Farben, Konstanten, Schriften, Schriftgrößen und Stile stehen hier dieselben Theme-Eigenschaften Konstanten, Schriften, Schriftgrößen und Stile Wenn wir auf die Plus-Schaltflächen neben Hintergrund und Füllung klicken , können wir diesem Thema Stilfelder für den Fortschrittsbalken hinzufügen diesem Thema Stilfelder für den Fortschrittsbalken Da wir diese Stilfelder bereits erstellt haben, können wir den Fortschrittsbalkenknoten auswählen. Klicken Sie dann auf die Ressourcen der Stilbox und ziehen Sie aus dem Inspektor in den Theme-Editor. Der Fortschrittsbalken in der Theme-Vorschau wurde aktualisiert und verwendet nun die Style-Boxen. Jetzt erbt jeder Fortschrittsbalken, der vom HUD-Knoten erbt dieses Thema und verwendet diese Stilfelder, um den Fortschrittsbalken automatisch zu zeichnen Dies gibt uns die Möglichkeit alle Kontrollknoten desselben Typs auf die gleiche Weise zeichnen zu lassen oder Theme-Overrides zu verwenden , um einzelne Kontrollknoten unterschiedlich zu zeichnen Wir können die Theme-Overrides aus dem Fortschrittsbalkenknoten entfernen aus dem Fortschrittsbalkenknoten da diese Stilfelder nun vom HUDS-Theme übernommen werden Wenn Sie dieses Thema für Ihr gesamtes Projekt verwenden möchten , ohne es in jede Szene kopieren zu müssen, können Sie es als Projektressource speichern Dann können wir in den Projekteinstellungen unter GUI-Thema ein benutzerdefiniertes Thema festlegen, indem wir die gespeicherte Themenressource auswählen Dies erfordert einen Neustart des Editors, um wirksam zu werden. Jetzt wird jeder Fortschrittsbalken in jeder Szene des gesamten Projekts auf die gleiche Weise gezeichnet Stellen wir uns jedoch vor, Sie möchten mehrere magische Anzeigen haben , die diese Stilfelder verwenden, und mehrere andere Fortschrittsbalken , die andere Stilfelder verwenden Anstatt mehrere Themen zu haben, können wir Variationen des Thementyps verwenden auf die Plus-Schaltfläche klicken, können wir einen benutzerdefinierten Namen eingeben, der dem Thema hinzugefügt werden soll, z. B. Magic Gauge. Klicken Sie dann auf die Schaltfläche Tools und geben Sie ihr einen Basis-Typ-Fortschrittsbalken , indem Sie ihn entweder eingeben oder aus der Liste auswählen . Jetzt enthalten die anderen Registerkarten die Eigenschaften, die von der Fortschrittsleiste übernommen wurden, und wir können die Werte der Felder Hintergrund und Füllstil ändern . Ich kopiere die Stilfelder aus meinem Magic Gauge-Knoten und klicke dann auf das Kettengliedsymbol, um die Verknüpfung zu der Stelle aufzuheben, an der sie kopiert wurden Wenn ich zu den Eigenschaften des Fortschrittsbalkendesigns wechsle, entferne ich die Stilfelder und setze alles wieder auf das Standarddesign zurück Wählen Sie dann den Magic-Gauge-Knoten im Szenenbaum aus und erweitern Sie den Themenbereich im Inspektor Ich kann Magic Gauge in der Typvariante auswählen, um ihnen mitzuteilen, dass sie die Theme-Eigenschaften für das Magic Gauge verwenden sollen. Jetzt kann mein Spiel bei Bedarf mehrere Magieanzeigen haben, ohne dass ich die Stile für jeden von ihnen einzeln einrichten die Stile für jeden von ihnen einzeln Ich muss dem Theme nur sagen, dass es die Eigenschaften des Magic-Gauge-Designs verwenden soll , und ich kann immer noch andere Fortschrittsbalken in meinem Spiel haben und ich kann immer noch andere Fortschrittsbalken in meinem Spiel haben, bei denen es sich nicht um Zauberanzeigen handelt, sondern die auch in verschiedenen Stilen gezeichnet werden können Wir haben jetzt eine einfache Zauberanzeige, aber wir müssen noch den Gesundheitszähler implementieren Wir sehen uns im nächsten Video. 38. 5-3 Symbol: Hallo Freunde. In diesem Video erstellen wir ein Gesundheitssymbol mit Animationen, die anzeigen, wann der Charakter seine Gesundheit wiedererlangt oder verliert Derzeit werden die Gesundheitssymbole als Knoten mit zerstörter Textur angezeigt , die horizontal nach dem Containerknoten der horizontalen Box angeordnet horizontal nach dem Containerknoten der horizontalen Box Wenn Sie diese als Sprites animieren möchten, könnten Sie sie in Animated Sprite Two D Nodes umwandeln in Animated Sprite Das Mischen von Kontrollknoten mit zwei D-Knoten verursacht jedoch zwei D-Knoten Ich werde schnell die Animations-Sprite-Frames-Ressource einrichten die Animations-Sprite-Frames-Ressource , damit ich das demonstrieren kann Zwei D-Knoten verhalten sich nicht wie Kontrollknoten. Sie verankern ihre Positionen nicht Verhältnis zu ihren übergeordneten Knoten, werden Containerknoten organisiert Größe wird auch nicht automatisch an die Fensterauflösung angepasst Anstatt den Typ des verwendeten Knotens zu ändern, müssen wir diesen Textur-Wret-Knoten so animieren, wie Wenn wir das Drop-down-Menü für Textureigenschaften erweitern, können wir sehen, dass es eine Option für animierte Texturen gibt Diese animierte Texturressource kann bereits nur eine einzige Animation enthalten , sie entspricht in diesem Fall nicht wirklich unseren Bedürfnissen Wenn wir damit das Symbol animieren wollten, müssten wir jedes einzelne Bild der Animation über diese klobige Oberfläche als separate Atlas-Textur mit einer Dauer in Sekunden festlegen einzelne Bild der Animation über diese klobige Oberfläche als separate Atlas-Textur mit separate Atlas-Textur mit einer Dauer in Sekunden Und nach all dem müssten wir ein benutzerdefiniertes Skript verwenden, um zu kontrollieren, welche Frames der Animation trotzdem verwendet werden Wenn wir dieselbe Textur haben wollten, sollten mehrere Animationen abspielen. Es wäre also besser, diese Textureigenschaft als Atlas-Textur zu belassen . Wir könnten zwar ein benutzerdefiniertes Skript schreiben, um den Wert der Regionseigenschaft dieser Atlas-Textur zu ändern , der Zeit- und Arbeitsaufwand würde sich nicht wirklich lohnen, wenn der Animation Player-Knoten bereits existiert. Fügen wir also einfach einen Animation Player-Knoten als untergeordnetes Element dieses Gesundheitssymbols hinzu. Bevor wir irgendwelche Animationen machen, wäre es eine gute Idee, dieses Symbol zuerst als eigene Szene zu speichern . Dadurch wird der Animation Player-Knoten gekapselt, da er für den Kontext des HUD des Spiels nicht wirklich relevant ist In dieser Szene setze ich zunächst den Symbolbereich auf den Standardstatus, den ich als Standardstatus verwenden möchte . Dieser ist leer Erstellen Sie dann eine neue Animation für den Fall, dass sich dieses Symbol füllt, stellen Sie die Bildrate auf 12 Bilder pro Sekunde ein, passen Sie den Zoom an und aktivieren Sie den Frame-Snapping Ich setze das Bild dann mit einem Keyframe an den Anfang der Animation und füge es dem Reset-Track hinzu Auch wenn ich das nicht als ersten Frame der Animation verwenden möchte , ist es jetzt der Standardstatus, der von der Reset-Animation verwendet wird. Als Nächstes überschreibe ich den ersten Schlüssel meiner Füllanimation mit dem eigentlichen ersten Frame Fahren Sie dann mit den restlichen Frames fort, die das Symbol ausfüllen Ich setze die Dauer der Animation auf acht Frames. Denken Sie daran, den Aktualisierungsmodus auf diskret zu ändern , wenn Sie Frame-Animationen wie diese verwenden. Das sieht gut aus, also werde ich es duplizieren und eine weitere Animation erstellen wenn der Charakter Schaden erleidet, wodurch das Symbol geleert wird. Da ich weiß, dass meine Spritesheet-Sprites alle gleichmäßig verteilt sind, kann ich die Werte für die eingegebenen Bereiche einfach um ein Vielfaches von 32 Pixeln bearbeiten , um die gewünschten Frames zu erhalten Diese Animation ist mit nur sechs Frames kürzer . Es ist wichtig, dass diese Animationen mit dem Frame enden , der auch nach dem Ende erhalten bleibt. Sobald diese leere Animation abgespielt wird, bleibt das Symbol leer, bis die Füllanimation abgespielt wird. Ebenso bleibt das Symbol nach dem Abspielen der Füllanimation gefüllt, bis die leere Animation abgespielt wird . Anhängen eines Skripts an den Stammknoten des Integritätssymbols und Speichern dieses Skripts in einem neuen Ordner für UI-Skripte Wir gehen davon aus, dass dieses Skript für jedes animierte Symbol verwendet werden kann jedes animierte Symbol falls wir es für etwas anderes als Gesundheit verwenden möchten Dieses Skript benötigt nur dann einen Verweis auf den Animation Player-Knoten , wenn es bereit ist. Stellen Sie dann bei Bedarf öffentliche Funktionen bereit, um jede der Animationen abzuspielen. Zurück in der Spielszene können wir alle anderen Gesundheitssymbole löschen. Ich benenne dieses erste in das Gesundheitssymbol um und dupliziere es dann achtmal, um den Rest mit dem Animation Player und dem angehängten Skript neu zu erstellen den Rest mit dem Animation Player und dem angehängten Skript Wenn wir das testen wollen, können wir das Player-Skript verwenden, um dem Gesundheitssymbol per Tastendruck mitzuteilen , ob es gefüllt oder leer sein Wenn ich die Run-Taste drücke, verwende ich den mit dem Dollarzeichen versehenen Knotenpfad, um diesem ersten Gesundheitssymbol mitzuteilen, dass es gefüllt werden soll Wenn ich die Run-Taste loslasse, mache ich dasselbe, um zu sagen, dass es leer Da dies nur zu Testzwecken dient, muss ich mir keine Gedanken darüber machen, wie ineffizient dieser Code ist das Spiel starten und die Run-Taste drücken, alle Symbole gefüllt, obwohl ich nur dem ersten gesagt habe, dass es gefüllt werden soll Das liegt daran, dass Godot natürlich versucht, so ressourcenschonend wie möglich zu sein , und nur eine Atlas-Texturressource erstellt hat nur eine Atlas-Texturressource , die für alle Symbole verwendet werden kann Wenn wir also ein Symbol animieren, verwenden alle Symbole dieselbe Textur, sodass alle animiert sind In der Gesundheitssymbol-Szene können wir dieses Verhalten überschreiben, indem die Atlas-Texturressource im Inspektor erweitern Aktiviere im Bereich „Ressourcen“ die Option „Lokal zur Szene“ Dadurch wird Godot mitgeteilt, dass jede Instanz der Szene eine eigene Kopie dieser Atlas-Texturressource mit eigener Regionseigenschaft benötigt eigene Kopie dieser Atlas-Texturressource mit eigener Regionseigenschaft Dieses Spritesheet wird weiterhin von allen Icons gemeinsam genutzt, aber welche Region des Spritesheets sie zeichnen, wird Das Spiel wird erneut ausgeführt. Diesmal füllt sich nur das erste Symbol, wenn ich die Run-Taste drücke und leert sich, wenn ich die Taste loslasse Wenn der Test erfolgreich ist, können wir die zusätzlichen Codezeilen entfernen oder auskommentieren Wir haben jetzt animierte Gesundheitssymbole, aber der Gesundheitszähler zählt nicht wirklich die Gesundheit unseres Charakters. Wir sehen uns im nächsten Video. 39. 5-4 Zähler: Hallo Freunde. In diesem Video schreiben wir ein Skript, das die animierten Symbole so verwaltet, dass die animierten Symbole so verwaltet, einen Wert und einen Maximalwert widerspiegeln. Wir haben hier unsere animierten Symbole, aber wir müssen ein Skript an den übergeordneten Knoten anhängen , das steuert, wie und wann sie animiert werden , um die Zählung der Gesundheit des Spielercharakters widerzuspiegeln Ich nenne dieses Icon Counter und lege es in den Ordner UI-Skripts Dieses Skript enthält nichts speziell die Funktionen des horizontalen Box-Containers nutzt . Deshalb werde ich den generischeren Steuerungstyp erweitern, sodass ich den Typ dieses Knotens später ändern kann , wenn ich möchte. Das Skript benötigt zwei ganze Zahlen, eine für die maximale Gesundheit des Charakters und eine weitere für seine aktuelle Gesundheit Da ich möchte, dass dieses Skript nützlich ist, um alles zu zählen, nicht nur Gesundheit, werde ich den Oberbegriff Wert verwenden Vorerst können wir den Standardwert für maximale Gesundheit so festlegen, dass er der Anzahl der Kinder entspricht diesen Knoten haben, die das Tag on ready verwenden. Als Nächstes benötigen wir zwei öffentliche Funktionen , die beide Werte setzen, indem sie einen Integer-Parameter akzeptieren und den alten Wert durch den neuen überschreiben Wenn unser Spielercharakter Schaden erleidet und seine Gesundheit wiedererlangt, können wir diese öffentlichen Funktionen aufrufen, um Spieler die Änderungen des Gesundheitswerts mitzuteilen Es liegt in der Verantwortung dieses Skripts, zu kontrollieren, wie viele Symbole angezeigt werden und welche, basierend auf den Werten dieser Ganzzahlen und wie sie sich ändern, gefüllt oder geleert werden basierend auf den Werten dieser Ganzzahlen und wie sie sich ändern dieser Ganzzahlen und wie sie Wir beginnen damit, den Wert ihrer aktuellen Gesundheit festzulegen den Wert ihrer aktuellen Als Erstes sollten wir überprüfen, ob es sich bei der Zahl auf die wir den Wert setzen sollen, um eine gültige Zahl handelt. Wir können den Charakter nicht anzeigen, der weniger als null Lebenspunkte hat , und auch nicht mehr als die Anzahl der verfügbaren Symbole, also seine maximale Gesundheit. Also setzen wir den Wert zunächst auf den Rückgabewert einer Ganzzahl zwischen Null und maximaler Gesundheit. Wenn wir versuchen, diese Funktion mit einer negativen Zahl aufzurufen, wird sie stattdessen health auf Null setzen. Und ebenso wird alles, was über dem Maximum liegt, auf das Maximum begrenzt Wenn wir als Nächstes den Wert auf dieselbe Zahl setzen, die er bereits ist, sollten wir nichts tun müssen, also könnten wir einfach aus dieser Funktion zurückkehren Sobald wir festgestellt haben, dass wir den Wert, der von diesem Symbolzähler angezeigt wird, in eine neue gültige Zahl ändern von diesem Symbolzähler angezeigt wird , unterscheidet sich der Vorgang, je nachdem, ob die Zahl steigt oder fällt. Wenn der neue Wert größer als der alte Wert ist, weisen wir einige der Symbole an, dass sie gefüllt werden sollen. Aber welche Symbole? Die Symbole werden praktischerweise vom horizontalen Box-Container in derselben Reihenfolge gezeichnet wie ihr untergeordneter Index im Szenenbaum. Mithilfe einer einfachen Schleife mit vier Schleifen und I als Index können wir den Wertebereich bis zum neuen Wert durchzählen. Range gibt ein Array zurück, das die Folge von ganzen Zahlen enthält , die von der ersten bis zur zweiten Zahl hochgezählt werden, schließt jedoch die zweite Wenn also der alte Wert eins und der neue Wert vier war, erhalten wir die Zahlen eins, zwei und Da der Index des ersten untergeordneten Elements Null und nicht Eins ist , passt dies perfekt zu den Indizes der Symbole , die gefüllt werden müssen. Also werden wir den untergeordneten Knoten auf Index I setzen und ihm sagen, dass er gefüllt werden soll. Das Verfahren zum Verringern des Werts ist sehr ähnlich. Nur weil wir wissen, dass der neue Wert kleiner als der alte Wert ist, müssen wir der Bereichsfunktion ein zusätzliches Argument geben , nämlich ein negatives, das ihr sagt, dass sie herunterzählen soll. Wenn der alte Wert vier war und der neue Wert eins ist, range 43 und zwei zurück. Diese sind nicht identisch mit den untergeordneten Indizes der Symbole, sondern sind um eins größer. Wir können das also beheben, indem wir in der Funktion „Get Child“ eins von I subtrahieren und diese Icons so einstellen, dass sie Erst wenn das alles erledigt ist, setzen wir den alten Wert auf den neuen Wir können das testen, ohne zusätzliche Skripte oder Eingabezuordnungen hinzuzufügen ohne zusätzliche Skripte oder Eingabezuordnungen Wir müssen dem Skript lediglich eine Eingabefunktion hinzufügen. Zunächst prüfen wir, ob das Eingabeereignis eine Eingabeereignistaste war und ob es sich bei dem Ereignis um eine Taste handelte, die gedrückt wurde. Verwenden Sie dann eine Match-Anweisung für den Tastencode des Ereignisses. Wenn es sich bei der gedrückten Taste um eine der Zifferntasten handelt, können wir den Wert des Symbolzählers auf diese Zahl setzen eine Zahlenvariable als Ganzzahl deklarieren, können wir die Zahl, die gedrückt wurde, berechnen , indem wir einfach Taste Null vom Event-Tastencode subtrahieren Das funktioniert, weil Tastencodes eine Aufzählung sind, eine einfache nummerierte Liste . Was auch immer der Schlüsselcode für Schlüssel Null ist, der Schlüsselcode für Schlüssel Sieben wird der Schlüsselcode für Schlüssel Null plus Sieben sein Wir können eine Anweisung ausdrucken, die so etwas wie Set Current Health Two plus die in eine Zeichenfolge umgewandelte Zahl sagt Current Health Two plus die in eine Zeichenfolge umgewandelte Zahl Rufen Sie dann die Set-Value-Funktion auf und übergeben Sie die Zahl. Wenn wir das Spiel starten, wird durch Drücken einer beliebigen Zifferntaste der Symbolzähler auf diese Zahl gesetzt und die Symbole animiert , je nachdem, ob sie gefüllt oder geleert werden Und dasselbe können wir auch für die Einstellung des Maximalwerts Wir könnten zwar bereits die maximale Anzahl von Symbolen in der Szene haben und nur diejenigen ausblenden, die wir nicht verwenden, es wäre skalierbarer, neue Symbole nach Bedarf zu instanziieren Da dies nicht sehr oft vorkommt, es keinen Einfluss auf die Leistung und ermöglicht es, so viele weitere hinzuzufügen , wie wir benötigen, falls wir später die maximale Anzahl einstellen möchten Also werden wir eine Variable exportieren, um die Icon-Szene als gepackte Szene zu speichern . Den Inhalt der Sollwertfunktion kopieren. Nachdem Sie jede Instanz eines Werts auf den Maximalwert geändert haben, müssen nur noch wenige Änderungen vorgenommen werden. Erstens können wir den Maximalwert nicht anhand seiner selbst validieren . Wir müssen also eine Grenze setzen , wie hoch der Höchstwert möglicherweise sein kann. Möglicherweise möchten Sie diese Obergrenze exportieren , anstatt einen Wert fest zu codieren. Anstatt Symbole auszufüllen, werden wir neue Symbole instanziieren und sie als Kinder hinzufügen Und anstatt Symbole zu leeren, werden wir sie aus dem Szenenbaum entfernen, indem wir sie kostenlos Um das zu testen, verwende ich dasselbe Zifferntasteneingabesystem, setze aber den Maximalwert fest, indem ich den Aufwärtspfeil gedrückt halte Maximalwert fest, indem ich den Aufwärtspfeil Wenn also die Eingabepunkt-Aktion gedrückt wird, suche nach oben, dann drucke ich Max Health aus und stelle stattdessen diesen Wert ein und füge den aktuellen Gesundheitsteil in den anderen Block ein. das Spiel starte, kann ich den maximalen Gesundheitswert ändern , indem ich den Aufwärtspfeil gedrückt halte und eine der Zifferntasten drücke und den Aufwärtspfeil loslasse Ich kann auch weiterhin den aktuellen Gesundheitswert ändern. Denk daran, die Eingabefunktion nach dem Testen auszukommentieren. Wir haben jetzt einen animierten Symbolzähler, der die maximalen und aktuellen Gesundheitswerte der Spielercharaktere verfolgen kann der die maximalen und aktuellen Gesundheitswerte der Spielercharaktere verfolgen . Aber weder der Gesundheitssymbolzähler noch die Magieanzeige sind tatsächlich mit dem Spielercharakter verbunden. Wir sehen uns im nächsten Video. 40. 5-5 Verletzungsbox: Hallo Freunde. In diesem Video geben wir dem Charakter etwas Gesundheit, damit er sich mit dem Gesundheitssymbolzähler verbinden kann. Wir könnten dem Charakterskript Gesundheitsvariablen hinzufügen und es auf diese Weise verfolgen. Dies würde es jedem Charakter in unserem Spiel ermöglichen , ohne zusätzliche Arbeit gesund zu sein. Aber wenn wir bedenken , dass Dinge, die keine Charaktere sind , möglicherweise auch Gesundheit benötigen, wie zum Beispiel zerbrechliche Wände, wird das weniger vorteilhaft, zumal unser Charakter ein Charakterkörper zwei D ist und die zerbrechliche Mauer ein statischer Körper zwei D. Und vielleicht haben wir noch einen starren Körper für D, der ebenfalls Gesundheit benötigt Fälle müssten wir dieselben Variablen und Für jeden dieser Fälle müssten wir dieselben Variablen und Funktionen in mehreren Skripten verwenden Wir könnten unser Charakterskript so umschreiben , dass es von Physics Body Two D übernommen wird. Alles in unserem Spiel, das Gesundheit benötigt, kann dieses Skript ebenfalls verwenden Aber es gibt eine Menge Dinge in diesem Skript, die diese anderen Objekte nicht anwendbar wären Es wäre verschwenderisch , all diese Variablen und Funktionen an eine zerbrechliche Wand anzuhängen , die sie niemals benutzen müsste , und ebenso die Variablen und Funktionen, die für eine zerbrechliche Wand gedacht sind , an unseren Charakter anzuhängen In solchen Fällen möchtest du vielleicht das zusammengesetzte Muster anstelle der objektorientierten Vererbung verwenden , um deine Skripte in deinem gesamten Spielprojekt wiederzuverwenden Durch die Erstellung einer Gesundheitskomponente kann diese unabhängig davon existieren, womit sie verknüpft ist. Charaktere können eine Gesundheitskomponente haben und zerbrechliche Wände können auch eine Gesundheitskomponente haben In der Charakterszene fügen wir ein neues Kind hinzu, einen D-Node in Area Two, und nennen es Hurt Box Fügen Sie dann einen TD-Node mit Kollisionsform als untergeordnetes Element der Hurt Box hinzu, um deren Form zu definieren. Dies ist der Bereich in der Luft, in dem ein Charakter Schaden erleidet, wenn er getroffen wird. Möglicherweise möchtest du nicht immer, dass dies der Kollisionsform ihres Charakters entspricht. Außerdem solltest du generell immer wollen, dass die Kollision des Charakters aktiv bleibt, während die Verletzungsbox oft ausgeschaltet ist, um zu verhindern, dass der Charakter beispielsweise beim Ausweichen oder in Zwischensequenzen Schaden Ausweichen oder in Zwischensequenzen Es hilft also, deiner Hurt-Box einen separaten Kollisionsbereich zu geben einen separaten Kollisionsbereich Ich mache meine auch zu einer Kapsel, aber etwas kleiner als der Hauptteil des Charakters und setze ihre Debug-Farbe auf Grün, damit ich sie leichter voneinander unterscheiden kann Dieser Bereich muss nicht für die Überwachung von irgendetwas verantwortlich sein Überwachung von irgendetwas verantwortlich Es muss nur überwachbar sein, damit Hit-Boxen es erkennen können den Kollisionsbereich unter Kollisionsobjekt zwei D erweitern , können wir dieses Objekt so einstellen, dass es sich auf Ebene zehn befindet und seine Maske vollständig entfernen In den Projekteinstellungen gebe ich zwei D Physics Layer Ten den Namen Spieler Hurt Box. Jetzt kann alles im Spiel, das Schicht zehn sowohl überwacht als auch maskiert , den Spielercharakter verletzen Wenn ich ein Skript an diesen Knoten anhänge, nenne ich es Hurt Box Dieses Skript benötigt die gleichen Werte für maximale Gesundheit und dieselben aktuellen Integritätswerte wie für den Symbolzähler Da ich den Gesundheitswert mit Symbolen angeben werde, müssen diese Ganzzahlen sein Wenn du eine Anzeige für die Gesundheit deines Charakters verwendest, hast du die Möglichkeit, stattdessen Gleitkommazahlen zu verwenden da eine Anzeige Dezimalwerte anzeigen kann Im Moment setze ich die maximale Gesundheit einfach auf fünf und verwende den Tag on ready, um die aktuelle Gesundheit auf Max Health zu setzen Im Gegensatz zum Icon-Counter-Skript verändert eine Verletzungskiste den Wert der aktuellen Lebenspunkte hauptsächlich den Wert der aktuellen Lebenspunkte dadurch, dass sie Schaden durch die Trefferbox erleidet oder Lebenspunkte wiederherstellt. Das werden also unsere öffentlichen Funktionen sein, denen beide akzeptieren, dass eine bestimmte Menge an Lebenspunkten als Ganzzahl verloren oder gewonnen wird. Wenn wir Schaden erleiden, ziehen wir einfach den Betrag von der aktuellen Gesundheit des Charakters Wir können dann die Max-Funktion verwenden um entweder diesen Wert oder Null zurückzugeben, je nachdem, welcher Wert größer ist, und als neuen Wert für die aktuelle Gesundheit festlegen Dadurch wird verhindert, dass ihr Gesundheitszustand jemals unter Null fällt Wir können die Wiederherstellungsfunktion mehrfach verwenden, indem wir dem Parameter einen Standardwert geben. Wenn wir diese Wiederherstellungsfunktion ohne Argumente aufrufen, gehen wir davon aus, dass dies bedeutet, dass sie ihre gesamte Gesundheit bis zu ihrer maximalen Einstellung für aktuelle Gesundheit auf maximale Gesundheit wiederherstellen sollten Gesundheit bis zu ihrer maximalen . Wenn der Wiederherstellungsfunktion ein Argument übergeben wurde, addieren Sie diesen Betrag zur aktuellen Gesundheit des Charakters und verwenden die MIN-Funktion, um entweder dieses Ergebnis oder Max Health zurückzugeben , je nachdem, welcher Wert niedriger ist. Die aktuelle Gesundheit wird also niemals die maximale Gesundheit überschreiten. In beiden Fällen wird der Wert der aktuellen Gesundheit geändert und diese Änderung muss im Zähler auf dem HUD wiedergegeben werden Zähler auf dem HUD wiedergegeben Aber die Hurt-Box befindet sich in der Charakterszene und der Symbolzähler in der Spielszene In den meisten Fällen ist es am besten, wenn Informationen zwischen Knoten und verschiedenen Szenen ausgetauscht werden müssen Informationen , Signale zu verwenden und ihre Verbindung über ihren engsten gemeinsamen Vorfahren In der Spielszene ist der Stammknoten der Spielszene, der Spielmanager, der engste gemeinsame Vorfahr zwischen dem Charakter und dem Gesundheitszähler und dem Geben wir dem Gesundheitszähler einen eindeutigen Namen. Schnappen Sie sich dann im Game Manager-Skript einen Verweis darauf. Wir könnten versuchen, dem Gesundheitszähler mitzuteilen , dass er die Hurt-Box des Charakters überwachen soll. Wir können die Funktion Get Node verwenden , um die Hurt-Box des Charakters abzurufen. Aber dann stützt sich unser Icon-Counter-Skript auf bestimmte Funktionen oder Variablen die in der Entität vorhanden sind, die es überwacht. Es wäre also im Grunde nur als Gesundheitszähler nützlich , der nicht als Skript zum Zählen anderer Dinge wiederverwendet werden kann. diese Logik umzukehren, wäre es besser, der Hurt-Box mitzuteilen , dass sie von diesem Symbolzähler überwacht werden soll Rufen Sie dann eine Funktion auf, die wir noch nicht geschrieben haben, wie set counter, und übergeben sie als Argument an den Gesundheitszähler Denken Sie daran, dass diese Funktion zum Abrufen von Knoten fehlschlägt, wenn Sie den Namen Ihres Hurt-Box-Knotens ändern oder die Struktur Ihres Szenenbaums neu anordnen , sodass er kein direktes untergeordnetes Element mehr ist Ich bevorzuge diese Abhängigkeit dem Schreiben einer neuen Funktion im Charakterskript zum Abrufen des Hurt-Box-Knotens , da dieses Skript bereits ziemlich lang ist Zurück im Hurt Box-Skript schreiben wir diese neue Funktion akzeptieren einen Symbolzähler als Parameter der Typsteuerung, da wir ihr keinen bestimmten Klassennamen gegeben haben. Jetzt haben wir die Hurt-Box und den Gesundheitszähler im selben Skript, sodass wir problemlos zwischen ihnen kommunizieren können. Noch wichtiger ist, dass das Icon-Counter-Skript immer noch für alles verwendet werden kann, was wir wollen, und jede Hurt-Box in unserem Spiel die nicht durch einen Zähler überwacht werden muss, kann diese eine Funktion einfach ignorieren. Wir könnten die Icon-Counter-Funktionen direkt aufrufen, aber das würde dazu führen, dass jede Hurt-Box im Spiel ständig überprüft, ob sie über einen Icon-Counter verfügt sie überwacht, bevor sie diese Funktionen aufruft Es wäre besser, Signale zu verwenden , um diese Änderungen zu kommunizieren, eines für den Zeitpunkt, an dem sich die maximale Gesundheit ändert und ein anderes, wenn sich die aktuelle Gesundheit ändert Beide benötigen Integer-Parameter für ihre neuen Werte. Möglicherweise möchten wir auch einen anderen für den Fall, dass der Zustand Null erreicht , für den keine Parameter erforderlich sind. Wenn sich ihre aktuelle Gesundheit nun ändert, weil entweder Schaden erleiden oder ihre Gesundheit wiedererlangt haben, können wir dieses Signal aussenden, indem haben, können wir dieses Signal aussenden wir ihre neue aktuelle Gesundheit als Argument angeben. Wenn die aktuelle Gesundheit nach dem erlittenen Schaden Null ist, sollten wir das eingefärbte Signal Zwei ausgeben Wenn wir nun einen Zähler zur Überwachung dieser Hurt-Box einrichten, können wir diese Signale einfach mit den Sollwertfunktionen der Icon-Counter verbinden , da die von den Signalen übergebenen Parameter sowohl in der Menge als auch in der Art mit den Parametern der Icon-Counter-Funktionen übereinstimmen den Parametern der Icon-Counter-Funktionen sowohl in der Menge als auch in Es wäre auch eine gute Idee, diese Signale sofort auszugeben, damit der Symbolzähler seine Werte so einstellen kann, dass sie mit der Hurt-Box übereinstimmen. Um dies zu testen, können wir eine einfache Eingabefunktion in dieses Skript schreiben . Wenn ich die Taste nach oben drücke, erhält der Charakter eine Gesundheit zurück. Wenn ich nach unten drücke, erleidet der Charakter einen Schaden, und wenn ich springe, erhält der Charakter seine volle Gesundheit zurück. du das Spiel startest und nach unten drückst , erleidet der Charakter bei jedem Tastendruck einen Schaden. Schaden bei null Lebenspunkten zu erleiden, wird ignoriert. Wenn Sie nach oben drücken, wird eine Gesundheit wiederhergestellt, und die Wiederherstellung von Lebenspunkten bei Max wird ignoriert zuerst auf einen niedrigeren Wert zurückgehe, springe ich dann und stelle alle Lebenspunkte wieder her Denken Sie daran, diese Eingabefunktion nach dem Testen zu entfernen oder auszukommentieren . Wir haben unseren Charakter jetzt in der Lage, Schaden zu erleiden und seine Gesundheit wiederherzustellen, aber seine Gesundheit wird nicht gerettet. Wir sehen uns im nächsten Video. 41. 5-6 Daten: Hallo Freunde. In diesem Video erstellen wir eine benutzerdefinierte Ressource, mit der Sie die Statistiken und den Fortschritt des Spielers zwischen den Spielsitzungen verfolgen können Statistiken und den Fortschritt des Spielers . Wenn wir möchten, dass der Spieler maximale Gesundheits-Upgrades verdienen kann , dann behält er diese Upgrades, wenn er das nächste Mal spielt. Das Spiel muss wissen , was sie im Spiel gefunden haben und was nicht. Um das zu tun, können wir unsere eigenen Ressourcen schaffen. Wir haben in diesem Projekt bereits mehrere Ressourcen verwendet , wie die Atlas-Textur-Ressource für Charaktere oder die Animation-Tree-State-Machine-Ressource oder die Animation-Tree-State-Machine-Ressource Und das Thema. Diese Ressourcen sind alle Typen die von der Godot-Game-Engine definiert wurden, um spezifische Funktionen für die Knoten bereitzustellen, die sie verwenden. Aber wir können auch unsere eigenen erstellen , um unseren eigenen spezifischen Bedürfnissen gerecht zu werden. Lassen Sie uns einen neuen Ordner innerhalb des Ordners mit dem Namen resources erstellen . Wir können dann in diesem Ordner ein neues Skript mit dem Namen data erstellen , anstatt es vom Knoten zu erben . Dieses Skript erbt von Ressourcen werden im Szenenbaum nicht als Knoten dargestellt. Das Erste, was wir beim Erstellen einer benutzerdefinierten Ressource tun möchten , ist sicherzustellen, dass wir ihr einen Klassennamen geben. Andernfalls können wir keine Instanzen davon erstellen. Da der Zweck dieser Ressource besteht, den Überblick über die Spielerdaten zu behalten, können wir so viele Variablen hinzufügen, wie wir für alles benötigen , was wir zwischen den Spielsitzungen speichern möchten. Vorerst benötige ich Variablen für die Charaktere Max Health und Current Health als Ganzzahlen Ich füge auch ihre maximale Magie und ihre aktuelle Magie als Floats All diese Variablen werden andere Skripte öffentlich zugänglich Wir können auch Zeichenketten für Dinge wie ihren Namen oder boolesche Werte hinzufügen, um zu verfolgen, ob etwas ein- oder ausgeschaltet ist Arrays können verwendet werden, um Gruppen verwandter Informationen zu speichern, z. B. eine Reihe von booleschen Werten, um zu wissen , welche Upgrades vom Spieler gefunden wurden vom Spieler gefunden Wörterbücher sind sehr nützlich, um ganze Informationsklassen zu speichern, da wir Attributnamen als Schlüssel im Wörterbuch mit ihren entsprechenden Werten verwenden können Schlüssel im Wörterbuch mit ihren entsprechenden Werten ganze Informationsklassen zu speichern, da wir Attributnamen als Schlüssel im Wörterbuch mit ihren entsprechenden Werten verwenden können. Neben den grundlegenden Variablentypen können wir auch andere in Godot integrierte Klassen wie Vektoren zum Speichern von zwei D-Koordinaten, Farben oder sogar anderen benutzerdefinierten Klassen, die wir erstellen, einbeziehen Godot integrierte Klassen wie Vektoren zum Speichern von zwei D-Koordinaten, Farben oder sogar anderen benutzerdefinierten Klassen, die wir erstellen, Jede Variable, die Sie zwischen den Spielsitzungen speichern möchten , muss das Export-Tag haben Andere Variablen , die nicht über das Export-Tag verfügen , können dennoch nützlich sein, wenn du zum Beispiel nicht die aktuelle Gesundheit des Charakters speichern möchtest, sondern nur seine maximale Gesundheit und der Spieler jedes Mal, wenn er sein Spiel lädt, mit voller Gesundheit starten möchtest. Diese nicht exportierten Variablen bleiben jedoch erhalten wenn dein Spiel während der Spielsitzung die Szene wechselt , wenn dein Spiel während der Spielsitzung die Szene wechselt. Wenn Sie aus irgendeinem Grund die Spielszene verlassen, um eine Zwischensequenz abzuspielen, dann wieder zur Spielszene zurückkehren, behalten diese Variablen ihren Wert. Wir können zwar auch Funktionen in dieses Skript schreiben, aber das ist normalerweise nicht notwendig. Wenn Sie eine automatisierte Initialisierung Ihrer Ressource durchführen möchten , können wir die Init-Funktion überschreiben Diese Innit-Funktion wird automatisch von Godot aufgerufen wenn wir über ein Skript eine neue Instanz dieser Ressource erstellen dieser Ressource So können wir den Variablen einige Standardwerte geben, die Längen von Arrays festlegen oder unseren Wörterbüchern einige Schlüssel hinzufügen Stellen Sie sicher, dass Sie dieses Skript mit dem definierten Klassennamen speichern dem definierten Klassennamen bevor Sie versuchen, es in irgendeiner Weise zu verwenden Godot wird diesen Klassennamen also erkennen. Wir benötigen ein weiteres Skript , um auf unsere benutzerdefinierte Ressource zuzugreifen, die wir im nächsten Video behandeln werden Vorerst können wir unsere benutzerdefinierte Ressource testen, indem wir eine auf der Registerkarte Dateisystem erstellen. Wir klicken, wählen Neue Ressource erstellen aus und geben dann den Klassennamen ein oder wählen ihn aus der Liste aus. Dann gib ihr einen Namen. Wenn wir diese Ressource erstellen, öffnen wir sie automatisch im Inspektor, wo wir alle unsere exportierten Variablen sehen und bearbeiten können. Beim Erstellen einer Ressource auf diese Weise nicht die Funktion nit verwendet, sondern es werden Werte verwendet, die für Variablen bereitgestellt werden, die in ihren Deklarationen zugewiesen wurden. Wenn Sie etwas anderes auswählen und zur Bearbeitung dieser Ressource zurückkehren möchten, können Sie auf der Registerkarte Dateisystem darauf doppelklicken. Ich werde schnell testen, wie eine Datenressource im Game Manager-Skript erstellt wird. Wir können eine Instanz unserer Ressource erstellen indem wir zuerst eine Variable mit dem Klassennamen als Typ deklarieren mit dem Klassennamen als Typ Weisen Sie dann den Wert dieser Variablen dem Klassennamen zu , gefolgt vom Punkt Nu Wir können dann auf alle Variablen zugreifen , die wir in dieser Klasse deklariert haben, sowohl exportiert als auch nicht exportiert, ihre Werte überschreiben und sie beim Spielen nach Bedarf verwenden Denken Sie daran, diesen Testcode zu entfernen oder auszukommentieren und die Testdatenressourcendatei zu löschen Wir haben jetzt eine Datenressource, die die maximale Gesundheit und die aktuelle Gesundheit unserer Charaktere enthält, aber sie wird noch nicht gespeichert. Wir sehen uns im nächsten Video. 42. 5-7-Datei: Hallo Freunde. In diesem Video speichern und laden wir die Spielerdaten mithilfe unserer neuen benutzerdefinierten Ressource. Dazu benötigen wir ein weiteres Skript, das den Zugriff auf die Ressource verwaltet , die wir im vorherigen Video erstellt haben. Auf dieses Skript muss von überall im Projekt aus zugegriffen werden können. Der Charakter muss seine Statistiken kennen. Die Räume müssen wissen, ob der Spieler eine Tür geöffnet, ein Upgrade gefunden oder einen Boss besiegt hat . Sogar die Benutzeroberfläche und die Karte benötigen Zugriff auf die Speicherdaten. Wir können einige Knoten auf diese Weise leicht zugänglich machen, indem wir sie global machen. Lassen Sie uns im Skriptordner einen neuen Ordner mit dem Namen Globals erstellen Skriptordner einen neuen Ordner mit dem Namen Globals Erstellen Sie dann in diesem Ordner ein neues Skript mit dem Namen file. Der Zweck dieses Skripts besteht darin, schnellen und einfachen Zugriff auf den Spielern schnellen und einfachen Zugriff auf die Speicherdaten aller anderen Skripte zu ermöglichen, die wir im gesamten Projekt schreiben, sowie sie auf dem System des Spielers zu speichern und auch zu laden. Wir benötigen eine Variable vom Typ unserer benutzerdefinierten Ressource. Ich nenne sie Daten mit einem kleinen D. Wir benötigen dann drei öffentliche Funktionen, um diese Daten zu verwalten, ein neues Spiel zu starten, das Spiel zu speichern und das Spiel zu laden Ein neues Spiel zu starten ist einfach. Wir müssen nur den Wert der Daten auf unseren Klassennamen setzen , gefolgt von einem Punkt neu. Dadurch wird eine neue Instanz der Ressource erstellt und initialisiert Wenn wir bereit sind, unser Spiel zu speichern, müssen wir auch wissen, wo wir es speichern möchten Dafür deklariere ich eine String-Konstante, da ich das nie ändern werde, den Pfad zu dem Ort, an dem ich die Datendatei des Spielers speichern möchte. Godot bietet eine einfache Abkürzung , die auf jeder Plattform funktioniert Windows, Mac, Linux, Web und Konsolen können dies alle verwenden Der Benutzer Colon leitet einen Schrägstrich weiter . Do ersetzt dies automatisch durch den entsprechenden Pfad für Plattform als Speicherort, der sowohl für den Benutzer des Systems als auch für das Spiel spezifisch ist sowohl für den Benutzer des Systems als auch für das Spiel spezifisch Wenn ich eine Variable für den Dateinamen auch als Zeichenfolge deklariere, nenne ich meine Datei save, gefolgt von Punkt TRS, der Abkürzung für Text Resource Um das Spiel zu speichern, können wir auf eine Singleton-Klasse des Godot zugreifen, Resource Saver, die dann als Speicherfunktion bezeichnet wird Übergeben Sie die Ressource, die wir speichern möchten, und den Speicherort, an dem wir sie speichern möchten, indem Sie den Pfad und den Dateinamen anhängen Wenn wir mehrere Speicherplätze haben möchten, müssen wir nur den Dateinamen für jeden Slot ändern Das Laden unseres Spiels ähnelt dem Speichern. Alles was wir tun müssen, ist Godot Loader Singleton zu verwenden. Die Ladefunktion benötigt nur den Standort der Ressource, die wir Und sie gibt die Ressource zurück. Also weisen wir es unserer Datenvariablen zu. Da unser Spiel keine Titelszene hat, gehe ich einfach automatisch davon aus , dass ich eine Speicherdatei laden möchte, falls sie existiert , oder wenn sie kein neues Spiel startet. In der REDI-Funktion verwende ich also den Resource Loader, um zu überprüfen, ob eine Datendatei zum Laden vorhanden ist, und wenn ja, lade ich sie Andernfalls starte ein neues Spiel. Selbst bei einer Titelszene ist es hilfreich, dein Spiel direkt von der Spielszene aus starten zu können dein Spiel direkt von der Spielszene aus ohne jedes Mal den Titelbildschirm aufrufen zu müssen , während du entwickelst und testest. Wir haben unsere Datenressource hier. Wir können sie erstellen, speichern und laden. Jetzt müssen wir nur noch dafür sorgen, dass dieses Skript von überall in unserem Projekt aus leicht zugänglich ist. Öffnen Sie die Projekteinstellungen und wechseln Sie zur Registerkarte Globals Klicken Sie auf die Ordnerschaltfläche , um einen Browser zu öffnen und zu dem Dateiskript zu navigieren, das wir gerade erstellt haben. Klicken Sie dann auf Öffnen. Wir können einen anderen Namen für diesen globalen Knoten angeben , wenn wir möchten, oder den angegebenen verwenden. Klicken Sie dann auf Hinzufügen, um das Skript zur Liste der globalen Knoten hinzuzufügen. Jetzt kann jedes Skript, das wir schreiben nur mit seinem Namen auf dieses Dateiskript zugreifen. Ähnlich wie wir die Singletons Input, Resource Saver und Resource Loader verwendet haben Singletons Input, Resource Saver und Resource Loader Um das zu testen, stelle ich die maximale Gesundheit des Charakters so ein, dass sie dem entspricht, was im Safle steht , anstatt sie ganz oben im Skript zu platzieren Also füge ich diesem Skript eine initialisierte Funktion hinzu, nachdem ich einen neuen Maximalwertparameter akzeptiert den alten Maximalwert auf den neuen Maximalwert setze Dann setze ich den aktuellen Wert auf den Maximalwert und gebe beide geänderten Signale Jetzt kann der Spielmanager, nachdem er die Hurt-Box des Charakters erhalten die Hurt-Box des Charakters hat, sie mit dem maximalen Gesundheitswert aus der Datendatei des Spielers initialisieren dem maximalen Gesundheitswert aus der Datendatei des Spielers Ich werde auch eine Eingabefunktion hinzufügen, die beim Drücken der Aufwärts- oder Abwärtspfeiltasten erhöht oder verringert maximale Gesundheit des Charakters in der Datendatei erhöht oder verringert und die Hurt-Box entsprechend neu initialisiert Speichere dann das Spiel, indem du file dot save game aufrufst. Ich muss die Reihenfolge dieser Operationen umkehren , um die richtigen Werte anzuzeigen. Beim Ausführen des Spiels beginnt der Charakter mit fünf maximalen Lebenspunkten, aber ich kann diesen Wert ändern, indem ich die Aufwärts- oder Abwärtspfeiltasten drücke. Ich schließe dann das Spiel und starte es erneut, um zu überprüfen, ob seine maximale Gesundheit gespeichert und geladen wurde. Um die Datendatei, die wir gespeichert haben, im Projektmenü zu finden, wähle Benutzerdatenordner öffnen. Dadurch wird ein Dateibrowserfenster geöffnet, und wir können unsere dotTRS-Datei zum Speichern sehen Klicken Sie mit der rechten Maustaste auf diese Datei und öffnen Sie sie mit einem beliebigen Texteditor Wir können sehen, dass nur die maximale Gesundheit gespeichert wurde. Godot verfolgt, welche Variablen vom Spiel verwendet werden und speichert nur die Variablen, die wir tatsächlich verwenden und ändern Behalte das also im Hinterkopf. Wir können diese Datei hier tatsächlich bearbeiten, und das Spiel lädt sie tatsächlich mit den bearbeiteten Werten, solange die Formatierung übereinstimmt. Das ist großartig für uns, während wir unser Spiel entwickeln und testen. Aber vielleicht möchtest du es deinen Spielern nicht einfach ermöglichen, ihre sichere Datei zu bearbeiten, wenn du bereit bist, sie zu veröffentlichen. Ändern Sie im Dateiskript einfach die TRS-Erweiterung im Dateinamen in den Punkt RES. Anstatt als Textressource wird diese nun als binäre Ressource gespeichert, die nicht in einem Texteditor geöffnet und bearbeitet werden kann. Wenn ich das Spiel erneut starte, öffne ich die Datei mit den Speicherpunkten, die ich gerade erstellt habe. Es ist für mich jetzt unmöglich, das zu bearbeiten. Wir haben jetzt die Möglichkeit, Daten über den Fortschritt des Spielers in unserem Spiel zu speichern und zu laden . Im nächsten Abschnitt werden wir unsere freischaltbaren Fähigkeiten hinzufügen Wir sehen uns im nächsten Abschnitt. 43. 6-1 Doppelsprung: Hallo Freunde. In diesem Video geben wir unserem Charakter die Fähigkeit, doppelt zu springen. Während viele Charaktere in unserem Spiel möglicherweise die Fähigkeit benötigen , zu gehen, zu rennen, zu springen und zu fallen, sind die freischaltbaren Fähigkeiten normalerweise nur dem Spielercharakter vorbehalten Im Charakterskript können wir, anstatt diesem Skript, das schon ziemlich lang ist, weitere Variablen und Funktionen hinzuzufügen , diesem Skript, das schon ziemlich lang ist, weitere Variablen und Funktionen hinzuzufügen, ein neues Skript erstellen, das nur vom Spielercharakter verwendet wird Vergewissere dich, dass dein Charakterskript einen Klassennamen hat und gespeichert ist, bevor du fortfährst. der Charakterszene Klicke in der Charakterszene mit der rechten Maustaste auf den Stammknoten des Charakters und wähle Skript anhängen. Anstatt von CharacterBody zwei D zu erben, können wir vom Klassennamen unseres ursprünglichen Skriptcharakters erben, können wir vom Klassennamen unseres ursprünglichen Skriptcharakters unseres ursprünglichen Geben Sie diesem neuen Skript dann einen Namen und speichern Sie es im entsprechenden Ordner Da dieses neue Skript von Character erbt, hat es Zugriff auf dieselben Variablen und Funktionen , die wir für diese Klasse erstellt haben, und alle Werte für die exportierten Variablen und Signalverbindungen werden ebenfalls dieses neue Skript kopiert Aber wir können jetzt weitere hinzufügen, die nur für den Spielercharakter nützlich sind Nach diesem Vererbungsmuster wird der Charakter als Superklasse bezeichnet und unser Spielercharakter ist eine Unterklasse Zunächst benötigen wir eine Variable, die uns sagt , ob dieser Charakter die Fähigkeit zum Doppelsprung freigeschaltet hat oder nicht dieser Charakter die Fähigkeit zum Doppelsprung freigeschaltet hat Und um den Charakter darauf zu beschränken , nur einmal doppelt zu springen, benötigen wir eine weitere Variable, um zu wissen, ob sein Doppelsprung bereit ist. Es könnte auch hilfreich sein, ein Signal zu haben, das ausgegeben wird, wenn wir erfolgreich einen Doppelsprung ausgeführt um einen Partikeleffekt zu erzeugen, wenn Sie möchten, genau wie wir es beim anderen Sprung getan haben. Da beim Doppelspringen normalerweise dieselbe Taste wie beim normalen Springen verwendet wird, müssen wir keine zusätzliche Arbeit mit der Eingabemap in den Projekteinstellungen vornehmen oder das Player-Skript bearbeiten , um neue Funktionen aufzurufen. Wir können die Jump-Funktionsdeklaration einfach überschreiben. Beim Überschreiben einer Funktionsdeklaration muss die Funktionssignatur gleich bleiben Der Name der Funktion, ihre Parameter, Menge, Reihenfolge und Typen sowie der Rückgabetyp Da die ursprüngliche Sprungfunktion im Zeichenskript keine Parameter akzeptierte und einen booleschen Wert zurückgab, darf diese Sprungüberschreibung auch keine Parameter haben und einen booleschen Wert zurückgeben Wir wollen immer noch, dass die gesamte ursprüngliche Funktionalität des Sprungs zur Verfügung steht Dieser Charakter kann also springen, wenn die richtigen Bedingungen erfüllt sind. Wir können mit dem Schlüsselwort super auf die Funktionen der Superklasse zugreifen und dann einen Punkt, den Funktionsnamen und Klammern verwenden , genau wie wir eine Funktion auf jede andere Weise aufrufen würden Da die Sprungfunktion der Superklasse einen booleschen Wert zurückgibt, können wir auch das Ergebnis zurückgeben, um die Anforderung zu erfüllen Wenn der Spieler die Sprungtaste drückt, ruft das Spielerskript diese Funktion zum Sprung des Spielercharakters auf, die dann die allgemeinere Funktion zum Sprung von Charakteren aufruft diese Funktion zum Sprung des Spielercharakters auf, die dann die allgemeinere Funktion zum Sprung von Charakteren aufruft. Diese Struktur ermöglicht es uns, den Vorgang abzufangen , indem wir zusätzlichen Code über der Rücklaufzeile hinzufügen, sodass wir überprüfen können, ob dieser Spielercharakter als Antwort auf die Aufforderung, zuerst zu springen, doppelt springen kann, danach nur mit dem Standard-Sprungverhalten fortfahren dem Standard-Sprungverhalten Wenn dieser Spielercharakter also einen Doppelsprung machen kann und der Doppelsprung bereit ist und sich der Charakter nicht auf dem Boden befindet, dann sollten wir ihm erlauben, einen Doppelsprung auszuführen und „Wahr“ zurückgeben Wenn eine dieser Bedingungen falsch ist, müssen wir mit der Sprungfunktion kann normalen Bedingungen der Charakter-Superklasse prüfen, ob dieser Charakter unter normalen Bedingungen springen Wir können so ziemlich einfach die Codezeilen kopieren , die bei einem Doppelsprung einen Sprung implementieren, aber ein anderes Signal ausgeben Und wir müssen die Variable Doppelsprung ist bereit auf Stürze setzen , um zu verhindern, dass der Spielercharakter mehr als einen Doppelsprung ausführt. In den meisten Spielen mit einem Doppelsprung wird die Fähigkeit, den Doppelsprung auszuführen , nach der Landung auf dem Boden wiederhergestellt. Da die Charakterklasse bereits über eine Funktion verfügt , die aufgerufen wird, wenn der Charakter landet, können wir diese Funktion auch überschreiben. Jedes Mal, wenn dieser Charakter landet und sein Doppelsprung noch nicht bereit ist, können wir die Variable wieder auf true setzen, um sie bereit zu machen. Rufen Sie dann die Superklassenfunktion auf. In diesem Fall spielt die Reihenfolge , ob wir die Superklassenfunktion davor oder danach ausführen möchten , keine Rolle Um das zu testen, füge ich eine Print-Anweisung hinzu, wenn der Doppelsprung des Zeichens erfolgreich ist. Und noch eine, wenn der Doppelsprung wiederhergestellt ist. Setzen Sie dann den Standardwert von C double jump auf true. Wenn wir das Spiel starten, können wir die Sprungtaste drücken, um doppelt zu springen. Wenn Sie die Taste dreimal oder öfter drücken, werden keine Sprünge mehr erzeugt, und die Fähigkeit zum Doppelsprung wird bei der Landung wiederhergestellt Jetzt müssen wir nur noch diese Fähigkeit zum Doppelsprung sperren und freischalten Also setze ich den Standardwert von C double jump wieder auf False. In den Speicherdaten des Players entferne ich all diese unnötigen Variablen. Wir benötigen Variablen, die uns sagen , welche Fähigkeiten der Spieler freigeschaltet hat, die wir in einer Reihe von Booleschen Werten speichern können Arrays werden mit Ganzzahlen indexiert Jeder unserer Fähigkeiten muss nacheinander eine Zahl zugewiesen werden, beginnend bei Null, bis sie als ihre Indizes für dieses Array dienen Wenn Sie sich nicht viele ganze Zahlen merken möchten, können wir eine Aufzählung erstellen, um jeder Ganzzahl einen Namen zu geben, der für uns einfacher zu verwenden ist Ich füge diese Aufzählungen gerne in ein separates Skript mit dem Namen enums ein Während Godot uns zwingt, bei der Erstellung des Skripts von einer vorhandenen Klasse zu erben , können wir diese Zeile nach der Erstellung aus unserem Skript entfernen unserem Skript Geben Sie diesem Skript dann einen Klassennamen, damit wir in anderen Skripten darauf verweisen können Normalerweise verwende ich dasselbe Skript, um jede Aufzählung für das gesamte Projekt zu speichern Wir können eine Aufzählung mit dem Schlüsselwort num, gefolgt von geschweiften Klammern, deklarieren dem Schlüsselwort num, gefolgt von geschweiften Klammern, Innerhalb der geschweiften Klammern können wir die Namen jeder unserer Fähigkeiten in eine durch Kommas getrennte Liste schreiben jeder unserer Fähigkeiten in eine durch Kommas Ich habe bereits einen Doppelsprung als meine erste freischaltbare Fähigkeit erstellt , und ich werde einen Wall Jump, einen Dash, einen Hut und das Abfeuern eines Projektils erstellen Dash, einen Hut und das Abfeuern eines Projektils Aufzählungen werden üblicherweise in Pascal-Groß- und Kleinschreibung benannt, während die Aufzählungseinträge in Schlangengroßbuchstaben geschrieben werden. Die Aufzählung weist dem ersten Eintrag den Wert Null, dann Eins, Zwei usw. zu, was bedeutet, dass wir diese ganz einfach als Indizes für unser Array verwenden können diese ganz einfach als Indizes Diese müssen nicht in der Reihenfolge sein, in der sie vom Spieler freigeschaltet werden Die Reihenfolge ist willkürlich und dient nur dazu, jeder Fähigkeit eine eindeutige Nummer zuzuweisen. Bei der Initialisierung der Speicherdaten des Spielers können wir die Größe des Arrays an die Größe der Aufzählung anpassen. Dadurch erhalten wir automatisch die richtige Anzahl von Booleschen Werten und setzen sie standardmäßig Denken Sie daran, dass Variablen das Export-Tag haben müssen , um gespeichert zu werden. Zurück im Player-Skript können wir auf das Array mit den freigeschalteten Fähigkeiten verweisen und es mit dem Tag on ready in einer Variablen mit demselben Namen speichern . Beachten Sie, dass dadurch nicht nur eine Kopie des Arrays in seinem aktuellen Zustand erstellt wird. Dadurch wird ein Verweis auf das Array erstellt, sodass sich alle Änderungen auf beide auswirken. Das bedeutet, dass wir, um eine Fähigkeit für den Charakter freizuschalten, eine Fähigkeit für den Charakter freizuschalten, nur ihren Wert in der Speicherdatenressource angeben müssen. Wir können jetzt die C-Doppelsprung-Variable ersetzen , indem wir das Array mit den freigeschalteten Fähigkeiten mit dem Punkt Enums Dot Double Jump indexieren Array mit den freigeschalteten Fähigkeiten mit dem Punkt Enums Dot Double Dieses Array mit freigeschalteten Fähigkeiten kann jetzt im gesamten Skript für jede Fähigkeit verwendet werden im gesamten Skript für jede Im Game Manager-Skript verwende ich die Eingabefunktion, um zu testen, ob die Doppelsprungfähigkeit freigeschaltet wenn ich die Aufwärtspfeiltaste drücke Einstellung von Dateipunktdaten, Punktfähigkeiten freigeschaltet, Indexpunkt-Aufzählungen, Punkt-Fähigkeiten Punkt Double Jump auf True Wir können das Spiel dann speichern , um es dauerhaft zu machen. Beim Ausführen des Spiels kann mein Charakter nicht doppelt springen. Zurück im Godot-Editor wechsle ich zum Remote-Tab, um mir den Szenenbaum des Spiels anzusehen , das gerade läuft Hier sehe ich den globalen Dateiknoten , der über eine Datenressource verfügt Innerhalb dieser Datenressource enthält das Array mit den freigeschalteten Fähigkeiten fünf Boolesche Werte, die alle falsch sind Der Spielercharakterknoten enthält auch einen Verweis auf dasselbe Array Sie zur Simulation zurückkehren und nach oben drücken, wird die Doppelsprungfähigkeit freigeschaltet Im Remote-Szenenbaum kann ich sehen, dass der boolesche Wert im Array sowohl in der Datenressource als auch in der Figur auf true gesetzt wurde sowohl in der Datenressource als auch in der Figur auf true Schließe das Spiel und starte es erneut. Der Doppelsprung ist seit dem Speichern bereits freigeschaltet. Wir können die Druckanweisungen jetzt entfernen, da bestätigt wurde, dass der Doppelsprung funktioniert. Wir haben jetzt eine freischaltbare Doppelsprungfähigkeit, aber wir müssen noch einige weitere freischaltbare Wir sehen uns im nächsten Video. 44. 6-2 Wandfolie: Hallo Freunde. In diesem Video lassen wir den Charakter eine Wand hinunterrutschen, wodurch Reibung entsteht , um den Abstieg zu verlangsamen. Zunächst müssen wir entscheiden, was diese Fähigkeit bewirken soll und wann sie eingesetzt werden soll. Wenn Sie eine neue Funktion wie diese implementieren, ist es eine gute Idee, zuerst Tests einzurichten , die Sie bestehen möchten. Ich fange mit der Rauminhaltsszene und verstecke die Bäume, damit ich besser sehen kann. Um eine Mechanik zum Verschieben von Wänden zu erstellen, erstelle ich zwei Wände in meinem Zimmer Ich betrachte meine Mechanik als abgeschlossen , wenn der Charakter springen und dann mit reduzierter Fallgeschwindigkeit eine der beiden Wände hinunterrutschen kann dann mit reduzierter Fallgeschwindigkeit eine der beiden Wände hinunterrutschen Ich würde auch gerne eine andere Animation abspielen , während das passiert Die Wandrutsche sollte enden, wenn die Figur keinen Kontakt mehr mit der Wand hat, wenn sie den Boden berührt oder wir die Bewegungsrichtung drücken, um die Figur von der Wand wegzubewegen. wir das umsetzen, wird also Luftphysik des Charakters verändert Im Spielercharakter-Skript überschreiben wir den Prozess der Luftphysik des Charakters Rufen Sie dann den Air Physics-Prozess der Superklasse aus dem Charakterskript Hier können wir unseren Code in drei separate Blöcke unterteilen. Wenn der Charakter eine Wall Slide ausführt, prüft er, wann er mit der Ausführung einer Wall Slide beginnen kann, und jedes andere Mal rufen wir den Superclass-Airphysics-Prozess Wir müssen wissen, wann die Figur gerade eine Wall Slide ausführt, also sollten wir das als boolesche Variable deklarieren Es wäre auch hilfreich, ein Float zu exportieren, um es als Multiplikator für die Schwerkraft des Charakters zu verwenden Multiplikator für die Schwerkraft des Charakters zu während wir eine Wall Slide ausführen Ich werde 10% verwenden. Zurück zum Prozess der Luftphysik: Wir können nun anhand dessen verzweigen, ob die Variable Is Wall Sliding wahr oder falsch ist oder nicht. Wenn der Charakter bereits durch die Wand rutscht, können wir entweder den Vorgang fortsetzen oder beenden, je nachdem, ob andere Bedingungen erfüllt sind. Wenn der Charakter nicht durch die Wand rutscht, müssen wir prüfen, ob er die Wand rutschen kann, und wenn die Bedingungen erfüllt sind, um mit dem Wandrutschen zu beginnen, dann tun wir das. Und zu guter Letzt, wenn all das falsch ist, dann sollten wir mit der Oberklasse Air Physics als Standard weitermachen Oberklasse Air Physics als Standard weitermachen Wenn Sie Ihren Algorithmus in Pseudocode-Kommentaren wie diesem aufschreiben in Pseudocode-Kommentaren wie diesem ist es viel einfacher, ihn danach auszufüllen und bei Bedarf neu anzuordnen Außerdem wird das Endergebnis bereits kommentiert. Beginnen wir mit dem Starten einer Wall Slide indem wir überprüfen, ob die Fähigkeit Wall Jump freigeschaltet wurde. Füge dann auch die Bedingung , dass sich dieser Charakter an einer Wand befinden muss. Die Körperklasse des Charakters bietet diese Funktion, die sich genauso verhält wie auf dem Boden. Ich möchte auch weitere Bedingungen hinzufügen, dass ihre Y-Geschwindigkeit größer oder gleich Null sein muss. Ich möchte nicht, dass der Charakter anfängt, die Wand zu rutschen, wenn er sich nach oben bewegt, und der Spieler muss die eingegebene Bewegungsrichtung in Richtung Wand drücken . Der Körper des Charakters mit zwei Bezeichnungen gibt uns noch eine weitere Funktion Mach Wall normal. Dies gibt einen Vektor zurück, der von der Wand weg zeigt. Wenn wir also den X-Teil dieses Vektors verwenden, dieser immer negativ , wenn sich die Wand rechts der Figur befindet , oder positiv wenn sich die Wand links von der Figur befindet. Wenn ich das mit der Bewegungsrichtung des Charakters vergleiche, multipliziere ich beide Seiten mit minus eins und setze voraus, dass die Ergebnisse gleich sind. Dadurch kann die Bewegungsrichtung nicht Null sein. Diese I-Anweisung enthält mehrere Bedingungen , und sie passen nicht in mein Skriptfenster. Wenn Sie die Bedingungen Ihrer if-Anweisung über mehrere Zeilen schreiben möchten , können Sie sie in Klammern setzen. Dies kann das Lesen und Debuggen Ihres Codes erleichtern , wenn Sie dieses Format bevorzugen Meine Wände sind zwar perfekt vertikal, verwenden wenn Ihre Wände abgewinkelt sind, müssen Sie möglicherweise den Sinus der Wände als Normalwert X Wenn all dies zutrifft, erlaube ich der Figur, eine Wandrutsche zu starten , indem ich I Wall Sliding auf True setze und ihre Y-Geschwindigkeit mithilfe der Min-Funktion auf Null begrenze Dadurch wird die Fallgeschwindigkeit kurzzeitig zurückgesetzt , sodass sich die Wandrutsche langsamer anfühlt Ich werde auch eine Erklärung zu Testzwecken ausdrucken. Jetzt gehen wir davon aus , dass der Charakter bereits einen Wandrutsch ausführt, und wir wollen seine Schwerkraft außer Kraft setzen , um seinen Abstieg zu verlangsamen. Dazu addieren wir einfach die Y-Geschwindigkeit des Charakters, Schwerkraft mal Delta mal den Schwerkraftmultiplikator Wall Slide , den ich auf 10% der normalen Schwerkraft gesetzt habe Aus physikalischer Sicht ist das so, als würde man sagen, dass zwischen der Figur und der Wand ein Reibungskoeffizient von 0,9 Und zuletzt können wir darüber nachdenken, wann wir die Wall Slide beenden sollen. Wenn sich der Charakter nicht mehr an der Wand befindet oder wenn der Spieler die entgegengesetzte Bewegungsrichtung von der Wand weg drückt . Wenn also nicht an der Wand ist oder wenn das Zeichen der Bewegungsrichtung mit den Wandnormalen X übereinstimmt, setze ich Ist die Wand gleitet auf falsch und drucke eine Erklärung aus , dass die Wandrutsche beendet wurde Es wäre einfacher , die Wandfolie als den anderen Block zu dieser I-Anweisung weiterführen zu lassen , also schneide ich sie aus und füge sie hier Es gibt noch eine weitere Bedingung , die besagt, dass eine Wandrutsche beendet werden muss , wenn die Figur den Boden berührt. Da wir bereits eine Funktion haben, die automatisch aufgerufen wird , wenn der Charakter landet, füge ich hier einfach eine weitere I-Anweisung hinzu, die die Wall Slide beendet. Wenn es sich bei der Figur um Wall Sliding handelt, setze I Wall Sliding auf False und drucke dann eine weitere Anweisung aus. Es ist hilfreich, wenn diese beiden Aussagen unterschiedlich sind, damit wir während unserer Tests sehen können , wann sie tatsächlich vorkommen. Dies funktioniert für die Tastatur, aber nicht für einen Controller, da die Bewegungsrichtung ein Dezimalwert sein kann. Also muss ich die Zeichenfunktion auf diese beiden Prüfungen anwenden, um mit der Controller-Eingabe zu arbeiten. Als letztes muss ich dem Animations-Player des Charakters eine Wall Slide-Animation hinzufügen eine Wall Slide-Animation . Also werde ich ihre Laufanimation duplizieren. Ändern Sie die Y-Position des Bereichs der Tabelle, der gerade verwendet wird, und löschen Sie die Schrittspur Diese Animation wird der State-Machine-Ressource hinzugefügt. Ich lasse zu, dass der Charakter vom Springen oder Fallen in diesen Zustand übergeht , wenn I Wall Sliding auf true gesetzt ist. Wall Sliding“ auf „ Stürzen“ gesetzt ist, dann von einer Wandrutsche in einen Sturzmodus übergehen Wenn „I Wall Sliding“ auf „ Stürzen“ gesetzt ist, dann von einer Wandrutsche in einen Sturzmodus übergehen. Oder zur Fortbewegung, wenn sie den Boden berühren. Im Game Manager-Skript ändere ich das Freischalten des Doppelsprungs in das Entsperren des Wall Jump Entsperren des Das sollte ausreichen, um meinen Test zu bestehen , also führe ich das Spiel aus Der Charakter kann immer noch normal springen, und wenn er gegen die Wand springt, rutscht die Wand nicht , da die Fähigkeit immer noch gesperrt ist. Aber wenn ich nach oben drücke, um den Wandsprung freizuschalten Wenn ich jetzt springe, während ich mich zur Wand bewege, rutschen sie die Wand hinunter und hören auf, wenn sie den Boden berühren. das an der anderen Wand versuchen, endet die Rutsche, wenn sie den Boden der Wand erreichen. Und bei einem weiteren Versuch gegen die erste Wand startet die Wandrutsche erst, die Wandrutsche erst wenn die Figur zu fallen beginnt, und ich kann die Wandrutsche vorzeitig beenden, indem ich mich von der Wand entferne und ich kann die Wandrutsche vorzeitig beenden . Das normale Sprungverhalten des Charakters wird durch die Ausführung einer dieser Aktionen nicht beeinträchtigt. , die Druckaussagen auszukommentieren, nachdem alle Tests bestanden Denken Sie daran, die Druckaussagen auszukommentieren, nachdem alle Tests bestanden wurden. Wir haben jetzt unseren Charakter in der Lage, einen Wall Slide auszuführen, aber wir müssen noch den Wall Jump implementieren. Wir sehen uns im nächsten Video. 45. 6-3 Wandsprung: Hallo Freunde. In diesem Video lassen wir den Charakter von der Wand wegspringen , während er eine Wandrutsche ausführt. Im Zeichenskript haben wir die Sprungfunktion bereits überschrieben , um einen Doppelsprung auszuführen Wenn wir wollen, dass der Charakter von der Wand springt, können all diese Bedingungen auch beim Doppelsprung erfüllt sein Wir müssen also zuerst den Mauersprung als Möglichkeit in Betracht ziehen und ihn ausschließen bevor wir nach dem Doppelsprung suchen, da die Bedingungen für den Mauersprung spezifischer sind. Wir müssen nur überprüfen, ob die Fähigkeit Wall Jump freigeschaltet wurde und ob der Charakter gerade einen Wall Slide ausführt. Wenn diese Bedingungen nicht erfüllt sind, können wir überprüfen, ob der Charakter stattdessen doppelt springen kann. Dadurch kann der Charakter jedoch erst dann einen Wandsprung ausführen, wenn die Wall Slide gestartet wurde. Diese wartet , bis der Charakter den Scheitelpunkt seines Sprungs erreicht hat den Scheitelpunkt seines Sprungs erreicht Wenn du vor dem Start der Wall Slide Wandspringen zulassen möchtest , wenn die Y-Geschwindigkeit des Charakters negativ ist, können wir auch weitere Bedingungen hinzufügen Entweder führen die Figuren eine Wandrutsche durch oder sie befinden sich nicht auf dem Boden , sondern an einer Wand, und die Bewegungsrichtung ist zur Wand gerichtet. Bei der Reihenfolge der logischen Operationen müssen wir das oder in Klammern setzen damit es vor dem ersten und geprüft wird. Wir können mehrere Ebenen von Klammern und Einrückungen verwenden , um die Reihenfolge der Operationen einer komplexen Logik wie dieser visuell darzustellen um die Reihenfolge der Operationen einer komplexen Logik , damit sie bei Bedarf leichter zu verstehen Jetzt, wo wir bereit sind, einen Wandsprung durchzuführen, können wir all die gleichen Dinge tun wie wir es auch bei jedem anderen Sprung tun würden Sie dann true zurück, sodass der Eingabe-Handler weiß, dass das Drücken der Sprungtaste erfolgreich war. Was die Geschwindigkeit des Charakterkörpers angeht, so wollen wir, dass er sich nicht nur nach oben bewegt, sondern sich auch von der Wand weg bewegt. Anstatt also nur die Y-Geschwindigkeit des Charakters festzulegen, legen wir den gesamten Geschwindigkeitsvektor erstellen damit auch einen neuen Vektor. Für das X können wir den normalen Vektorpunkt X der Wände verwenden, und für Y können wir einen verwenden. Dadurch erhalten wir einen Vektor, der nach oben und von der Wand weg zeigt , sodass wir die richtige Richtung haben. dies mit der Sprungkraft multiplizieren, erhalten wir einen Vektor mit einer Größe, die größer ist als unser normaler Sprung, da der ursprüngliche Vektor bereits eine Länge von mehr als eins hatte Wir können diesen Richtungsvektor normalisieren, wenn wir wollen, aber die Art und Weise, wie er jetzt funktioniert , wird meiner Meinung nach tatsächlich zu einem besseren Ergebnis führen , wenn die volle Höhe des Sprungs plus die zusätzliche Kraft von der Wand weg aufgebracht wird Da die Sprungkraft jedoch eine negative Zahl ist, wird dadurch die Wand senkrecht umgekehrt, sodass sie zur Wand zeigt und nicht von ihr weg. Also füge ich ein Negativ an der Vorderseite der Wand hinzu (normal X), um daraus ein doppeltes Minus zu machen , das Um den Wall Jump zu animieren, benötigt die Zustandsmaschine der Figur einen Übergang von Wall Slide zu Jump , sofern die Figur Dies steht im Konflikt mit dem Übergang zum Fallen da die Figur nicht mehr gleichzeitig durch die Wand rutscht Für den Übergang zum Springen ist also ein niedrigerer Prioritätswert erforderlich , um zuerst berücksichtigt zu werden. Anstatt dass der Doppelsprung bereit ist, müssen wir bei der Ausführung des Wandsprungs die Einstellung Ist die Wand rutschen auf Stürze setzen. Wenn wir das Spiel starten, können wir den Wandsprung bereits ausführen , da er im vorherigen Video freigeschaltet wurde . Wenn wir gegen die Wand springen, können wir von ihr springen. Die Größe der Seitengeschwindigkeit von der Wand weg entspricht der ausgeübten vertikalen Kraft. Da die Schwerkraft den Charakter jedoch ständig nach unten zieht, ist den Charakter jedoch ständig nach unten zieht, dies viel weniger auffällig als die Kraft, die von der Wand weggeht, die nur durch die Luftregelung des Charakters oder durch Luftbremsen reduziert wird Luftregelung des Charakters oder durch Luftbremsen Ich würde es vorziehen, wenn auf meinen Charakter viel weniger Seitenkraft ausgeübt würde und er viel weniger Seitenkraft ausgeübt würde und könnte einem Wandsprung zur gleichen Wand zurückkehren und weiter nach oben klettern Das erfordert mehrere verschiedene Änderungen der Physik, um richtig zu funktionieren. Zum einen wird die Seitenkraft reduziert, die Seitenkraft reduziert die auf den Wandsprung von der Wand ausgeübt wird , erhält der Charakter mehr Luftkontrolle um in größerer Höhe zur Wand zurückzukehren Beschäftigen wir uns zunächst mit der Seitenkraft. Anstatt einen Wert fest zu codieren, ist es immer besser, exportierte Variablen zu verwenden , damit sie verdreht und optimiert werden können Ich exportiere einen zweiten Vektor mit dem Namen Wall Jump Force Multiplikator und gebe ihm einen Standardwert von minus eins positiv Wir können dann den resultierenden Geschwindigkeitsvektor mit den resultierenden Geschwindigkeitsvektor diesem neuen Wall Jump-Kraftmultiplikator multiplizieren Dieser negative Wert macht es überflüssig, das Negativ auf den Wandnormalenvektor anzuwenden, was ich intuitiver finde, da ich das Negativ als etwas außerhalb der Wand betrachte Wenn zwei Vektoren multipliziert werden, ist das Ergebnis das Produkt von beiden Xs und das Produkt von beiden Ys Mit diesen Werten funktioniert das genauso wie derzeit Aber da der Wert exportiert wird, kann ich ihn in meiner Charakterszene auf minus 0,5 ändern und so die X-Geschwindigkeit um die Hälfte reduzieren. Wenn Sie sich selbst daran erinnern möchten , wie Ihre Variablen funktionieren, Hinzufügen eines zusätzlichen Nummernzeichens vor einem Kommentar über der Variablendeklaration erstellt das Hinzufügen eines zusätzlichen Nummernzeichens vor einem Kommentar über der Variablendeklaration einen Tooltip, der angezeigt wird, wenn Sie im Inspektor mit der Maus über die Variable Wenn ich das Spiel erneut durchführe, hat mein Charakter die volle Aufwärtskraft des Sprungs, aber nur die Hälfte der Sprungkraft wird in X-Richtung angewendet Aber ich kann immer noch nicht an einem höheren Punkt zur Wand zurückkehren , um noch höher zu klettern. Dafür muss ich meinem Charakter viel mehr Luftkontrolle geben , aber ich möchte nicht, dass der Charakter zu einem anderen Zeitpunkt mehr Luftkontrolle hat. Deshalb muss ich den Luftkontrollwert speziell nur bei einem Wandsprung überschreiben den Luftkontrollwert speziell nur bei einem Wandsprung ihn dann auf seinen normalen Wert zurücksetzen. In den für das Wandspringen exportierten Variablen exportiere ich einen neuen Float für Wall Jump Air Control und setze ihn auf einen sehr hohen Wert, z. B. vier. Dadurch beschleunigt der Charakter viermal schneller als am Boden und achtmal schneller als bei einem normalen Sprung , bei dem meine Luftkontrolle standardmäßig auf Ich werde das auch in einer anderen Variablen mit dem Ready-Tag speichern einer anderen Variablen mit dem Ready-Tag Wenn ich es also auf seinen normalen Wert zurücksetzen möchte , weiß ich, was das ist. Da ich nicht weiß, ob der Spieler von der Wand weg oder zurück zur Wand springt oder was auch immer er sonst tun möchte, die einzig zuverlässige Methode , die Luftregelung wäre die einzig zuverlässige Methode , die Luftregelung auf die Standardeinstellung zurückzusetzen, die Verwendung eines Timers. der Szene einen Timer-Knoten hinzufüge, ich ihn Wall Jump, gebe ihm einen eindeutigen Namen erhalte dann einen Verweis darauf mit dem Tag on ready 2. Ich nenne diese Übersteuerung der Luftregelung Wall Jump , um das in diesem Zusammenhang etwas übersichtlicher zu machen. Wenn wir nun den Wall Jump ausführen, können wir den Wert der Luftregelung auf Wall Jump Air Control ändern und den Timer zur Wall Jump Air Control ändern und Übersteuerung der Wall Jump-Luftregelung starten. den Timer-Knoten auswählen, können wir seine One-Shot-Eigenschaft auf true setzen und ihm eine kurze Wartezeit einräumen. Ich nehme eine halbe Sekunde. Dann verbinde das Timeout-Signal des Timers mit dem Skript. Wenn der Timer abgelaufen ist, können wir die Luftregelung des Charakters auf den Standardwert zurücksetzen das teste, ist es näher, aber ich komme immer noch nicht auf die Wand. Also muss ich meinen Wall Jump-Kraftmultiplikator und die Wall Jump-Luftsteuerungswerte anpassen Jump-Kraftmultiplikator und die Wall Jump-Luftsteuerungswerte , bis es funktioniert das Spiel erneut durchführe, hat mein Charakter jetzt, wenn ich einen Wall Jump ausführe, genug Beschleunigung um an einem höheren Punkt zur gleichen Wand zurückzukehren, sodass ich die Mauer hochklettern Unser Charakter ist jetzt in der Lage, von Wänden zu springen, um vertikale Oberflächen hochzuklettern. Als Nächstes fügen wir eine rasante Fähigkeit mit Unbesiegbarkeitsrahmen Wir sehen uns im nächsten Video. 46. 6-4 Strich: Hallo Freunde. In diesem Video geben wir dem Charakter eine freischaltbare Dash-Fähigkeit Ab den Projekteinstellungen der Karten-Eingabe-Tab benötigt der Karten-Eingabe-Tab eine Schaltfläche, die zum Sprinten verwendet werden kann Ich verwende die D-Taste oder die rechte Schultertaste auf meinem Controller dann im Player-Skript in der Eingabefunktion die Dash-Taste gedrückt wurde, Wenn dann im Player-Skript in der Eingabefunktion die Dash-Taste gedrückt wurde, versuche zu sprinten, und falls das nicht klappt, puffern Sie die Dash-Eingabe so, dass sie im nächsten Frame wieder trocken ist, genau wie wir es beim Sprung getan haben. Der Strich benötigt eine Richtung, die wir mit der Eingabe Singleton, get axis, move left, move right ermitteln können get axis, move left, move right Um Argumente für ein Callable bereitzustellen, verwenden wir die Bind-Funktion übergeben die Argumente dann stattdessen an diese Funktion Es wäre also besser , die Funktion input get axis nur einmal aufzurufen und das Ergebnis zu speichern Da dies nur während Frames passiert , wenn der Dash Button gedrückt wird, ist es nicht so schlimm, hier eine Variable zu deklarieren. Wenn die gepufferte Eingabe aufgerufen wird, übergibt sie die gebundenen Argumente Wenn der Strich ursprünglich gedrückt wurde , während der linke Stick geneigt war, wird er mit derselben Richtungseingabe gepuffert Jetzt können wir diese Strich-Funktion in unser Zeichenskript für Spieler schreiben , indem wir die Richtung für den Strich als Parameter akzeptieren und einen booleschen Wert zurückgeben, false zurückgegeben Bevor wir diese Funktion schreiben, benötigen wir einige Variablen Die Entfernung, zwischen der das Zeichen gestrichelt werden soll, setze ich auf 128 Pixel. Die Kraft, die erforderlich ist, um diese Entfernung zu erreichen , wird mit dem Tag on ready berechnet Wir können dieselbe Formel verwenden wie bei der Berechnung der Sprunghöhe, die Quadratwurzel der Entfernung multipliziert mit der negativen Kraft, was in diesem Fall Verzögerung mal zwei ist Ich würde auch gerne die Schwerkraft aussetzen, während der Sprung läuft . Deshalb speichere ich auch die Standardgravitation des Charakters in einer Variablen mit dem Tag on ready. Nun zur Dash-Funktion Wenn die Fähigkeit Strich freigeschaltet wurde, wollen wir, dass der Charakter Richtung des Strichs zeigt, was wir tun können, indem wir die Bewegungsrichtung auf diesen Wert setzen. Stellen Sie dann die Geschwindigkeit des Charakters auf einen neuen Vektor zwei ein, wobei die Strichrichtung mit der Strichstärke multipliziert wird , X und Null für das Y ist. Da der linke Analogstick gekippt werden kann, würde dies bedeuten, dass der Spieler langsamer oder schneller sprinten kann , je nachdem, wie weit er den Analogstick auf dem Controller neigt. Ich möchte nicht, dass das passiert, also verwende ich die Sinusfunktion, um die Neigung aus der Gleichung zu entfernen Wir können die Schwerkraft unterbrechen, während der Dash läuft, den Wert der Schwerkraft auf Null setzen und dann „true“ zurückgeben, weil der Strich erfolgreich war und nicht zwischengespeichert werden muss Was die Richtung des Sprintens angeht, gibt es mehrere Fälle, die berücksichtigt werden müssen, nicht nur, wenn der Spieler Richtungseingaben gibt, sondern auch, ob dies nicht der Fall ist und ob der Charakter gerade eine Wandrutsche ausführt Da das der speziellste Fall ist, werde ich diesen zuerst überprüfen. Wenn der Charakter durch die Wand gleitet, überschreibe ich den Wert von direction, sodass er ein Zeichen für WallNrMaltx Wenn sie nicht von der Wand rutschen und der Spieler Richtungseingaben gibt , wenn auf den Dash Button drückt, dann verwende ich die Richtungssünde als Richtungsangabe. Dabei entferne ich jegliche analoge Neigung aus dem Eingang, sodass ich sie dann verwende ich die Richtungssünde als Richtungsangabe. Dabei entferne ich jegliche analoge Neigung aus dem Eingang, entferne ich jegliche analoge Neigung aus aus der Zeile darunter entfernen kann Wenn der Spieler beim Drücken der Dash-Taste keine Richtungseingabe macht, gehe ich davon aus, dass er vorwärts sprinten möchte. Ich verwende einen Ternär, wenn die Richtung negativ eingestellt werden soll, wenn der Charakter nach links schaut, oder positiv, wenn die Schwerkraft nicht wieder normalisiert. Wir benötigen eine weitere Funktion , Wir benötigen eine weitere Funktion die am Ende des Strichs aufgerufen Das benötigt keine Parameter und gibt auch keinen Wert zurück. Wir setzen einfach die Schwerkraft des Charakters auf die Standardwerte zurück. In der Charakterszene benötigt der Strich eine Animation im Animation-Player-Knoten. die Frames pro Sekunde festlege und heranzoome, füge ich meine Keyframes hinzu, um den Strich zu animieren Wir müssen dieser Spur eine Spur für die Aufrufmethode und einen Keyframe hinzufügen, um am Ende der Animation die Funktion „Bindestrich beenden“ aufzurufen beenden Oder welchen Frame auch immer du möchtest , um die Schwerkraft des Charakters wiederherzustellen Wenn es mit diesem Verfahren möglich ist, diese Animation aus irgendeinem Grund zu unterbrechen, müssen wir trotzdem die Funktion End Dash aufrufen, um die Schwerkraft des Charakters wiederherzustellen, im Gegensatz zu dem Timer, den wir für die Wiederherstellung der Fehlerkontrolle des Charakters verwendet haben für die Wiederherstellung der Fehlerkontrolle des Charakters Behalte das also im Hinterkopf und mache einen Kommentar, um dich später daran zu erinnern diese Animation zur Zustandsmaschine hinzufügen, sollte es möglich sein, einen Strich von jedem unserer bestehenden Bewegungszustände aus auszuführen . Daher wäre es besser, diese Animation auf eine neue Ebene zu legen. Wenn ich die aktuelle Zustandsmaschine als Projektressource speichere, nenne ich sie Bewegung und lege sie in den Ordner mit den Charakterszenen. Erstellen Sie dann eine neue State-Machine-Ressource für den Animationsbaum. die Bewegungszustandsmaschine als Knoten in dieser neuen Zustandsmaschine hinzufüge , benenne ich sie in Bewegung um und erstelle einen Übergang vom Start zur Bewegung, sodass dies die Standardeinstellung ist. Wenn wir dieser Zustandsmaschine eine neue Strichanimation hinzufügen, können wir einen Übergang von Bewegung zu Armaturenbrett und zurück zur Bewegung hinzufügen. Um eine Animation einmal abzuspielen, sollte der Übergang, der zu ihr führt, aktiviert sein und für den Übergang, der aus der Animation heraus führt , sollte der Wechselmodus auf „Ende“ gesetzt sein , sodass der erweiterte Modus automatisch bleibt. Wir können diese Animation testen indem wir im Status auf die Play-Schaltfläche klicken. Bei jedem Klick wird sie einmal vollständig abgespielt und kehrt zum Bewegungsstatus zurück, wenn sie fertig ist Da der Übergang, der zur Animation führt , nicht automatisch erfolgt, liegt es an uns, diese Animation manuell über unser Skript auszulösen diese Animation manuell über unser Skript eine neue Variable deklariere, wird diese für mehrere verschiedene Fähigkeiten verwendet, also werde ich sie ganz oben platzieren und sie kurz Animation nennen Der Typ dieser Variablen wird eine maschinelle Wiedergabe eines Animationsknotens sein maschinelle Wiedergabe eines Animationsknotens Dies ist es, was Godot verwendet, um in der Zustandsmaschine zu navigieren und Animationen abzuspielen den Knoten im Szenenbaum auswählen, können wir diese Wiedergaberessource unter den Parametern Wiedergabe sehen unter den Parametern Wiedergabe Wir können diese Ressource abrufen, indem wir auf den Animationsbaum-Knoten klicken und ihn ziehen, um seinen Knotenpfad Verwenden Sie dann eckige Klammern , um eine Ressource von diesem Knoten diese Ressource klicken und sie aus dem Inspektor in die eckigen Klammern ziehen aus dem Inspektor in , erhalten wir den Pfad zur Ressource Wenn wir Bewegung und Fortbewegung erweitern, können Sie sehen, dass jede Ebene der Zustandsmaschine über eine eigene Wiedergabe-Ressource verfügt Aktuell benötigen wir diese nur, um den Dash manuell auszulösen, aber um den Dash manuell auszulösen, wir werden bald weitere Fähigkeiten hinzufügen Dieser Pfad wird sich ebenfalls ändern wenn wir der Zustandsmaschine weitere Ebenen hinzufügen, sodass sie aktualisiert werden muss Um die Strichanimation auszulösen, bei erfolgreicher Ausführung eines Strichs die Wiedergabe so einstellen, können wir bei erfolgreicher Ausführung eines Strichs die Wiedergabe so einstellen, dass sie in den Strichstatus wechselt, indem ihren Zeichenkettennamen als Argument angeben. Diese Codezeile entspricht dem Drücken der Play-Taste im Animationsbaum, als wir uns die Animation in der Vorschau angesehen haben Ich möchte dem Spieler auch die Möglichkeit nehmen den Charakter zu kontrollieren, während der Dash läuft. also den physikalischen Prozess außer Kraft setzen, können wir ihn schnell unterbrechen und mithilfe der Funktion G Current Node überprüfen, in welchem Zustand sich die Animationszustandsmaschine gerade befindet sich die Dies gibt den Namen der Zeichenfolge zurück, die wir auf den Knoten im Animationsbaum geschrieben haben. Wir können ihn vergleichen , um festzustellen, ob es sich um eine Bewegung handelt oder Wenn es etwas anderes als Bewegung ist, setze ich die Bewegungsrichtung auf Null, bevor mit dem normalen physikalischen Prozess der Superklasse fortfahre Dadurch wird verhindert, dass sich der Charakter bewegt oder in eine andere Richtung schaut während er eine der Fähigkeiten auf der obersten State-Machine-Ebene ausführt Fähigkeiten auf der obersten State-Machine-Ebene Im Game Manager-Skript ändere ich die Pfeiltaste nach oben, um die Dashabilität freizuschalten Das Spiel zu starten und die Dash-Taste zu drücken, bringt nichts. Nachdem wir die Aufwärtspfeiltaste gedrückt um die Dashabilität freizuschalten, können wir sprinten, wodurch der Charakter vorwärts sprintet Wenn Sie eine Richtung drücken, springt der Charakter in diese Und wenn wir beim Verschieben der Wand sprinten, flitzt der Charakter von der Wand weg. Wir haben unseren Spielercharakter jetzt Lage, durch die Umgebung zu rasen, aber wir müssen einen Cooldown-Timer hinzufügen , um zu verhindern, dass der Spieler ihn zu oft benutzt. Wir sehen uns im nächsten Video. 47. 6-5 Abklingzeit: Hallo Freunde. In diesem Video fügen wir Unbesiegbarkeits-Frames und eine Abkühlung unserer Sprint-Fähigkeit Bevor wir anfangen, dem Dash Unbesiegbarkeits-Frames hinzuzufügen, wäre es hilfreich, eine Trefferbox in unserer Szene zu haben , damit wir testen können, wie wir durch In der ersten Rauminhaltsszene füge ich einen Bereich zur Kennzeichnung hinzu und benenne ihn in Hit Box um Füge dann als Kind eine Kollisionsform hinzu. Geben Sie ihr als Ressource eine rechteckige Form und setzen Sie ihre Debug-Farbe auf Rot Du kannst dir vorstellen, dass es sich dabei um einen Feind handelt, der dem Spielercharakter bei Kontakt Schaden Ich mache es eine Kachel dick, 32 Pixel, und zwei Kacheln hoch, 64 Pixel. Dann verschiebe es nach links. Ich betrachte meinen Test als bestanden, wenn der Spielercharakter durch diesen Bereich rasen kann , ohne verletzt zu werden Damit dieser Kollisionsbereich dem Spieler Schaden zufügt, muss er überwacht werden Es muss nicht überwachbar sein, obwohl es keinen Unterschied macht , dieses Kästchen anzukreuzen Es muss auf keiner Ebene existieren, muss aber die Hurt Box-Ebene des Spielers maskieren Wenn es dir hilft, Kollisionen besser zu verstehen, ist es in Ordnung, davon auszugehen, dass diese Trefferbox auf einer Ebene der gegnerischen Trefferbox oder einer Ebene mit Umweltgefahren existiert einer Ebene der gegnerischen Trefferbox oder einer Ebene mit Umweltgefahren Die einzigen Voraussetzungen sind, dass sie die Hurt Box des Spielers überwacht und maskiert ein Script an diesen Node anhängen, verbinden wir sein On-Area-Enter-Signal mit dem Nachdem wir überprüft haben, ob es für den Bereich eine Schadensausfallmethode gibt, rufen wir diese Methode auf und geben eine Methode als Schadensbetrag Dadurch wird sichergestellt , dass der Bereich, der diesen Bereich betritt , über das Hurt-Box-Skript verfügt, das wir zuvor erstellt haben . Dieses hat die Methode Take Damage, die die Schadenssumme als Parameter akzeptiert. Wenn ein anderer Bereich das Signal ohne ein Hurt-Box-Skript auslöst , würde das zu einem Fehler führen, da es keine Take-Damage-Methode zum Aufrufen gäbe. Um beim Testen des Spiels unsere Kollisionsformen sehen zu können , können wir das Debug-Menü öffnen und sichtbare Kollisionsformen auswählen Wenn wir das Spiel starten, können wir die Trefferbox sehen und der Spielercharakter erleidet jedes Mal, und der Spielercharakter erleidet wenn er diesen Bereich betritt, einen Schaden Es gibt eine Fehlermeldung weil der Rauminhalt geladen wird geladen unser Charakter einen Kollisionsbereich betritt, und Godot es nicht mag, während eines Kollisionsereignisses einen weiteren Kollisionsbereich hinzuzufügen während eines Kollisionsereignisses einen weiteren Kollisionsbereich Wir werden das vorerst ignorieren , da wir nur einen Test durchführen und dies nicht Teil unseres endgültigen Spiels sein wird Wählen Sie in der Charakterszene den Animation Player-Knoten und die Dash-Animation aus. Um Unbesiegbarkeits-Frames zu unserer Dash-Animation hinzuzufügen, müssen wir lediglich die überwachbare Eigenschaft der Hurt-Box mit einem Keyframe der Hurt-Box Wir können den genauen Frame festlegen, wann die Hurt-Box ausgeschaltet und wann sie wieder eingeschaltet wird Wenn du möchtest, kannst du die Sichtbarkeit deiner Hurt-Box auch per Keyframe an ihre überwachbaren Eigenschaften anpassen , sodass du sehen kannst , wie sie sich während des Spiels aus- und wieder einschaltet So kannst du leichter erkennen, wann dein Charakter tatsächlich unbesiegbar ist Es könnte auch hilfreich sein, die Sichtbarkeit der Kollisionsform des Charakters auszuschalten , die Verletzungsbox besser sehen zu können das Spiel ausführen, können wir jetzt durch die Trefferbox rasen, ohne Schaden zu nehmen Betreten des Bereichs verursacht immer noch Schaden, ebenso wie das Beenden des Sprints innerhalb des Jetzt fügen wir dem Dash eine Abklingzeit hinzu. Wir beginnen damit, der Charakterszene einen Timer-Knoten hinzuzufügen Charakterszene einen Timer-Knoten hinzuzufügen Ich nenne diesen Timer Dash Cooldown und setze seine One-Shot-Eigenschaft auf true Ich belasse die Gewichtungszeit bei 1 Sekunde. Das wird die Abkühlzeit der Fähigkeit sein. Da es sich um die zweite Fähigkeit handelt , der ein Timer-Knoten zugeordnet und wir in Zukunft möglicherweise weitere hinzufügen möchten, sollten Sie erwägen, einen normalen Knoten als zusammenklappbaren Ordner zu verwenden , um sie zu speichern Es ist jedoch hilfreich, ihm einen eindeutigen Namen zu geben falls wir den Szenenbaum umstrukturieren möchten Wir müssen das Signal nicht mit dem Skript verbinden, um diesen Timer-Knoten zur Abkühlung zu verwenden In den Variablendeklarationen für die Dashability verwende ich das Tag on ready, um einen Verweis auf diesen neuen Timer-Knoten zu erhalten Alles, was wir tun müssen, ist den Timer entweder beim Starten oder Beenden oder beim Dash Es liegt an dir, was du bevorzugst, aber wenn du die Abklingzeit am Ende des Dash starten möchtest , eine weitere Bedingung erforderlich, um zu verhindern, dass der Spieler zweimal hintereinander sprintet Ich starte den Cooldown-Timer, wenn der Dash vorbei ist. Kehren Sie dann zur I-Anweisung zurück, wo wir prüfen, ob dieser Charakter mit dem Sprinten beginnen kann. Wir können überprüfen, ob der aktuelle Knoten der Animationszustandsmaschine Bewegung ist Das wird später auch zusätzliche Vorteile haben, da wir dem Charakter nicht erlauben werden, zu sprinten während er andere ähnliche Actionfähigkeiten ausführt. Um den Cooldown-Timer durchzusetzen, müssen wir nur überprüfen, ob dieser Timer gestoppt ist , um zu wissen, ob wir wieder sprinten können sollten Wenn die Dash-Animation bereits abgespielt wird oder der Cooldown-Timer nicht gestoppt ist, bedeutet das, dass der Dash fehlschlägt du das Spiel jetzt startest und die Dash-Taste drückst, kann der Charakter nur einmal sprinten und erzwingt dann eine Abklingzeit von 1 Sekunde, erzwingt dann eine Abklingzeit von 1 Sekunde bevor er wieder sprinten kann Das funktioniert, wird dem Spieler aber in keiner Weise mitgeteilt. Normalerweise haben Spiele wie dieses eine diagetische Anzeige, etwas, das im Spiel vorhanden ist, nicht auf dem HUD, um dem Spieler mitzuteilen , wann der Cooldown Fügen wir also der Charakterszene einen Animated Sprite Two-D-Node hinzu und nennen ihn eine Sprite-Frames-Ressource für diesen Knoten erstellen, können wir ein Sprite-Sheet importieren Ich lege das vorerst einfach in den Dust-Ordner , anstatt einen neuen Asset-Ordner für ein Sprite-Sheet zu erstellen einen neuen Asset-Ordner für ein Sprite-Sheet Und füge die Sprite-Frames aus dem Sprite-Sheet hinzu. Ich deaktiviere das Looping, setze die Frames pro Sekunde auf 12 und füge am Ende der Animation ein leeres Bild hinzu Da die Figur nicht zentriert ist, verschiebe ich sie um 12 Pixel nach oben Diese Animation ist länger als 1 Sekunde, aber ab der 1-Sekunden-Marke möchte ich , dass der Cooldown als abgeschlossen betrachtet wird. Ich gebe diesem Knoten einen eindeutigen Namen. Zurück im Skript müssen wir nur noch einen Verweis auf diesen Knoten abrufen. Und sag ihm, er soll spielen , wenn der Dash endet. Aber da meine Animation länger ist als der Dash Cooldown Timer, muss ich die Animation tatsächlich beenden bevor ich sie abspiele, falls sie noch läuft Dadurch wird die Animation wieder auf den Start zurückgesetzt. A nun Wenn wir nun das Spiel starten und die Sprint-Fähigkeit verwenden, die Animation abgespielt, aber sie folgt nicht dem Charakter. Das liegt daran, dass ein normaler Knoten keine Transformation besitzt. Daher hat er keine Position. Dadurch wird die Vererbungslinie vom Wurzelknoten des Charakters unterbrochen . Der Animated Sprite Two-D-Knoten beginnt jetzt also mit seiner eigenen Abstammung für zwei D-Transformationen, beginnend an Wir können den Typ des Fähigkeiten-Ordners auf zwei D ändern , sodass er eine Reihe von Sequenzen durch den Szenenbaum bietet und das animierte Sprite dem Stammknoten folgt Dem Spieler ist jetzt klar, dass seine Fähigkeit „Sprinten“ auf Abklingzeit ist, und genau wann er wieder sprinten kann, ohne zusätzliche Informationen auf dem HUD hinzufügen zu müssen ohne zusätzliche Informationen auf dem HUD hinzufügen Wir verfügen jetzt über unsere Fähigkeit, durch Trefferboxen zu rasen, ohne getroffen zu werden, und abzukühlen, bevor wir sie erneut einsetzen können Als Nächstes fügen wir eine passive Fähigkeit , die das Aussehen des Charakters verändert. Wir sehen uns im nächsten Video. 48. 6-6 Hüte: Hallo Freunde. In diesem Video werden wir eine passive Fähigkeit implementieren , die das Aussehen des Charakters verändert. Ausgehend von der Rauminhaltsszene werde ich für diesen Test den Kollisionsbereich von zuvor duplizieren . Dieses Mal wird der Kollisionsbereich speziell die intensive Hitze aus dem Inneren eines Vulkans repräsentieren . Ich ändere die Farbe auf Orange, damit ich weiß, was was ist. Ich möchte, dass der Spieler diesen Bereich erst durchqueren kann wenn er einen magischen Hut freigeschaltet hat es ihm ermöglicht , unversehrt voranzukommen Aber wenn sie den Hut tragen, können sie trotzdem Schaden durch normale Trefferboxen Anstatt also die Hurt Box-Ebene für normale Spieler zu maskieren , verwende ich eine andere Ebene Ich verwende Ebene 14 als Ebene , die diesem Wärmeeffekt in der Umgebung gewidmet ist kann mir das leicht merken, da es direkt unter zehn liegt. In den Projekteinstellungen nenne ich diese Ebene Heat. Dann werde ich in der Charakterszene dafür sorgen, dass die Hurt-Box auch auf dieser Ebene existiert. Das funktioniert jetzt genauso wie der Kollisionsbereich zuvor und fügt dem Spieler jedes Mal, wenn er diesen Bereich betritt, einen Schaden zu . Es sucht nur auf Ebene 14 und nicht auf Ebene zehn nach Kollisionen Ebene 14 und nicht auf Ebene zehn Alles, was wir tun müssen, um den Spielercharakter immun gegen Hitzeschaden zu machen , während er den Hut trägt, ist, die Ebene 14 aus der Kollisionsebene der Hurt-Box zu entfernen . Um das Aussehen des Charakters zu ändern, lege ich zusätzliche Sprites über den Charakter Ich importiere neue Spritesheets für drei verschiedene Upgrades einen Edelstein, einen Umhang und einen Hut Dann füge ich in der Charakterszene für jeden von ihnen einen zusätzlichen Sprite Tu Di-Knoten Alle mit Atlas-Texturen, genau wie beim Body-Sprite. Weisen Sie dann jedem Knoten die Spritesheets als Atlas-Eigenschaft zu So wie diese Objekte gezeichnet wurden, muss ich sie speziell in der Reihenfolge der Katze, dann des Umhangs, dann des Hutes und der Marmelade darüber schichten speziell in der Reihenfolge der Katze, dann des Umhangs, dann des Hutes und der Marmelade darüber Ich beginne jeweils mit dem ersten Sprite an Position 00 mit einer Größe von 32 mal 36 Pixeln und gebe ihnen den gleichen Offset, um sie um 18 Pixel nach oben zu verschieben Diese Elemente werden so gezeichnet, dass sie synchron mit dem normalen Charakter-Sprite animiert synchron mit dem normalen Charakter-Sprite animiert Somit sind alle Regionswerte für jede Ebene zur gleichen Ich muss nur die Atlas-Texturregion jedes Sprites zur Animation hinzufügen Atlas-Texturregion jedes Sprites zur Animation Kopieren Sie dann die Keys aus der Sprite-Hauptspur und fügen Sie sie in die anderen Spuren Und ändern Sie ihren Aktualisierungsmodus auf diskret. Jetzt enthält die Animation auch alle Sprite-Ebenen in perfekter Synchronisation Ich muss das für alle meine Animationen tun, aber es wird nicht so viel Aufwand erfordern Um jedes dieser Sprites umzudrehen, könnten wir alle ihre Flip-H-Eigenschaften jedes Mal festlegen , wenn sie die Richtung ändern Aber es gibt einen einfacheren Weg Vererbung des Szenenbaums zu nutzen Wenn wir alle anderen Sprites zu Kindern des Body-Sprites machen , erben sie ihre Transformation Und wir können ein Sprite mithilfe seiner Transformation umkehren , indem wir seine X-Skala auf einen negativen Wert setzen Beachten Sie, dass dieser Trick nicht für Dinge verwendet werden sollte , die mit Physik oder Kollisionen zu tun Es funktioniert hier gut, weil wir nur Sprites zeichnen. In der Face-Left-Funktion in unserem Zeichenskript anstelle von Flip H können wir anstelle von Flip H den Skalierungspunkt X auf einen negativen Wert setzen, wenn er links ist, andernfalls auf einen positiven Wert Dadurch wird nun das Umdrehen aller Sprites synchronisiert das Umdrehen aller Sprites Wenn die gesamte Einrichtung der Sprites abgeschlossen ist, ich die Sichtbarkeit der anderen Sprites standardmäßig aus und schalte sie dann ein, sobald Fähigkeiten freigeschaltet Im Spielercharakter-Skript benötigen wir eine Funktion, mit der wir festlegen können, welche Sprite-Ebenen sichtbar sind , je nachdem, welche Fähigkeiten der Spieler Ich nenne es Update Sprite visibility. Geben Sie dann jedem der Sprites einen eindeutigen Namen und stellen Sie ihre Sichtbarkeit so ein, dass Wert der freigeschalteten Fähigkeiten für die entsprechende Fähigkeit entspricht Durch den Doppelsprung wird der Umhang hinzugefügt. Der Hut ist offensichtlich. Und die Fähigkeit, Projektile abzuschießen, wird den Edelstein hinzufügen. im Game Manager-Skript Wenn wir im Game Manager-Skript das Spiel zum ersten Mal spielen, können wir diese Funktion aufrufen, um die Sprite-Sichtbarkeit des Charakters sofort zu aktualisieren , falls wir ein Safe-Ale mit bereits freigeschalteten Fähigkeiten geladen haben ein Safe-Ale mit bereits freigeschalteten Fähigkeiten Während des Spiels möchten wir diese Funktion auch immer dann aufrufen, wenn der Spieler eine neue Fähigkeit freischaltet Deshalb fügen wir diesem Skript ein Signal hinzu, wenn eine Fähigkeit freigeschaltet wurde, mit der Ganzzahl der Fähigkeiten als Parameter Schreiben Sie dann eine öffentliche Funktion, um eine neue Fähigkeit freizuschalten Dabei wird dieselbe Fähigkeitsnummer akzeptiert und das Signal weggelassen Dieses Signal können wir dann mit dem Spielercharakter verbinden. Wir haben die Sprite-Sichtbarkeitsfunktion zum Aktualisieren jedoch nicht so geschrieben , dass sie irgendwelche Parameter akzeptiert Wenn wir also das Signal verbinden, sollten wir die Bindung eines Arguments aufheben , um Fehler zu vermeiden Dadurch wird das Aussehen des Charakters verändert, aber er wird trotzdem Hitzeschaden erleiden , wenn er den Hut trägt Bei der Aktualisierung der Sichtbarkeit von Sprites im speziellen Fall, dass der Hut geschmückt wird, werde ich auch die Kollisionsebene für Hitzeschaden entfernen , um ihn davor immun zu machen Um eine einzelne Ebene aus einer Bitmaske zu entfernen, zuerst den Mauszeiger über die Ebene und notieren Sie sich ihren Wert Ebene 14 hat einen Wert von 8.192, was zwei hoch 13 oder zwei hoch 14 minus eins Die Kollisionsebene ist eigentlich eine Ganzzahl, die binär eine Folge von Nullen und Einsen ist Derzeit sind es nur Nullen, außer dass das zehnte und das 14. Bit eins sind Alles, was wir tun müssen, ist das 14. Bit auf Null zu ändern , um es aus dieser Ebene zu entfernen Wir beginnen damit, einen Verweis auf die Jetbox zu finden. Da diese Funktion nicht sehr oft aufgerufen wird, ist es in Ordnung, einen Knotenpfad zu verwenden Um die Kollisionsebene zu entfernen, könnten wir ihren Wert 8.192 subtrahieren Dies hängt jedoch der Kollisionsebene ab, die derzeit auf Ebene 14 vorhanden ist Wenn wir diese Funktion aus irgendeinem Grund aufrufen würden , obwohl Layer 14 bereits ausgeschaltet ist, würde eine einfache Subtraktion nicht funktionieren mit dem Bit-Operator und auf der Kollisionsebene unserer Hurt-Box Wenn wir mit dem Bit-Operator und auf der Kollisionsebene unserer Hurt-Box eine Sequenz aller Einsen angeben können , bei der nur das 14. Bit Null ist, wird das 14. Bit unabhängig von seinem aktuellen Wert auf 20 gesetzt unabhängig von seinem aktuellen Wert auf 20 Um diese Zahl zu erhalten, können wir die Bits von 8.192, dem Ebenenwert, umkehren 8.192, dem Ebenenwert, Dies geschieht mit dem Bitwise Naught-Operator, in GDScript ein Tilday Dies ist eine mathematisch sehr effiziente Methode , Kollisionsebenen zu entfernen. Wenn Sie eine Kollisionsebene hinzufügen und ihr Bit auf eins setzen möchten , müssen Sie lediglich den Operator oder anstelle von und verwenden und den Knoten entfernen Aber wir sind nicht daran interessiert, das hier zu tun. Im Game Manager-Skript aktualisiere ich meine Eingabefunktion, um jede neue Fähigkeit nacheinander freizuschalten jede neue Fähigkeit nacheinander wenn ich für meinen Test den Aufwärtspfeil drücke. deklariere hier eine neue Variable, damit sie mit meinem Testcode gebündelt wird Ich werde daran denken, dies zusammen mit der Eingabefunktion zu löschen , wenn ich sie nicht mehr zum Testen benötige Ich nenne sie nächste Fähigkeit als Ganzzahl, die natürlich standardmäßig Null ist Jedes Mal, wenn ich den Aufwärtspfeil drücke, schalte ich die nächste Fähigkeit und drucke den Namen dieser Fähigkeit aus Wir können die Tastenfunktion für eine Aufzählung verwenden , um eine Reihe von Zeichenketten zu erhalten , die mit denen identisch sind, die wir als Aufzählungseinträge geschrieben haben wir also das Schlüssel-Array mit der Fähigkeitsnummer indizieren , erhalten wir den Namen dieser Fähigkeit Ich inkrementiere dann die nächste Fähigkeit, halte sie aber auf einen Wert zwischen Null und der Größe der Fähigkeitsaufzählung minus Eins Fähigkeitsaufzählung minus gedrückt, um Fehler zu vermeiden Ich lösche die aktuelle sichere Datei , sodass meine Fähigkeiten zunächst gesperrt sind und sichtbare Kollisionsformen aktiviert werden gesperrt sind und sichtbare Kollisionsformen aktiviert das Spiel ausführen, beginnen wir ohne freigeschaltete Fähigkeiten und mit dem Standardcharakter Sprite Ich öffne den Remote-Szenenbaum und wähle die Charaktere Hurt Box aus, um zu überprüfen, ob sie sich auf den Ebenen 10 und 14 befinden Sie den Aufwärtspfeil einmal drücken, ist die Fähigkeit Doppelsprung jetzt freigeschaltet, sodass der Charakter einen Umhang trägt erneut den Aufwärtspfeil drücken, wird der Wandsprung freigeschaltet, aber das Aussehen des Charakters bleibt unverändert , da diese Fähigkeit nicht mit einer kosmetischen Änderung verbunden war einen der Kollisionsbereiche berühren Sie einen der Kollisionsbereiche berühren , erleidet der Charakter Schaden. Wenn Sie erneut nach oben drücken, ist jetzt auch das Armaturenbrett freigeschaltet und der Charakter sieht immer noch genauso aus. Wieder hoch, um den magischen Hut freizuschalten, und wir können sehen, dass sich die Hurt-Box des Charakters nicht mehr auf Ebene 14, sondern immer noch auf Ebene zehn befindet . Das Berühren der normalen Trefferbox verursacht Schaden, aber das Betreten der neuen Trefferbox mit vulkanischer Hitze nicht, was bedeutet, dass der Charakter dagegen immun ist , solange er den Hut trägt. ein letztes Mal nach oben drücken, schalten wir die Schussfähigkeit frei und fügen den Edelstein hinzu, aber das haben wir noch nicht implementiert. Wir lassen unsere Charaktere jetzt ihre Outfits wechseln , um sie an ihre Fortschritte im Spiel anzupassen Die letzte Fähigkeit, die wir hinzufügen werden, ist das Abfeuern eines Projektils. Wir sehen uns im nächsten Video. 49. 6-7 Geschoss: Hallo Freunde. In diesem Video fügen wir einen Projektilzauber hinzu, den der Spieler abfeuern kann, indem er seine magischen Punkte Zuerst müssen wir diesem Charakter magische Punkte geben , die er ausgeben kann Im Spielercharakter-Skript werde ich eine neue Exportkategorie für Zaubersprüche hinzufügen Dann zwei Variablen für ihre maximale Magie und ihre aktuelle Magie, beide als Floats Wir benötigen außerdem Signale, die Änderung dieser Werte ausgegeben werden müssen, damit wir das HUD aktualisieren können Indem wir die Bereitschaftsfunktion außer Kraft setzen, können wir den maximalen Magiewert auf den Wert aus den Speicherdaten des Spielers Dann starte ich den Player einfach mit voller Magie, setze den aktuellen Wert auf den Maximalwert und gebe die geänderten Signale aus, um das HUD zu aktualisieren Von der Spielszene aus können wir verbinden Signale der Spielercharaktere einfach mit der Magieanzeige da sie in derselben Szene existieren Der Magieanzeige ist kein Skript angehängt, aber sie benötigt auch keins. Da der Fortschrittsbalken bereits die Funktionen bereitstellt, die wir benötigen, müssen wir nur die Skriptmethoden ausschalten Die Range-Klasse gibt uns die Funktion set max, die einen Float-Parameter akzeptiert Ebenso wie die Set-Value-Funktion, auch einen Float-Parameter akzeptiert. Jetzt aktualisiert sich die Magieanzeige automatisch mit den magischen Variablen des Spielercharakters. In den Projekteinstellungen benötigt der Karten-Eingabe-Tab eine Taste , die vom Spieler gedrückt werden kann, um einen Zauberspruch zu sprechen. Ich verwende die C-Taste oder die obere Gesichtstaste auf meinem Controller. Dann können wir im Spielerskript das gleiche Format wie beim Sprung kopieren, um zu versuchen, einen Zauberspruch zu wirken. Falls das nicht gelingt, können wir die Eingabe zwischenspeichern, um es im nächsten Frame erneut zu versuchen. Zurück im Player-Charakter-Skript können wir die Cast-Funktion schreiben, die keine Parameter akzeptiert und einen booleschen Wert zurückgibt Alles, was wir hier wirklich tun müssen, ist zu überprüfen, ob die Fähigkeit freigeschaltet wurde und ob der Charakter gerade keine anderen Aktionen ausführt, ob der aktuelle Knoten der Animation Bewegung ist Dann weisen Sie die Animation an, zur Besetzungsanimation zu wechseln und true zurückzugeben, wenn die Eingabe erfolgreich war, oder false, wenn dies nicht der Fall war. Falls wir nicht möchten unser Zauberspruch sofort ausgeführt wird, muss alles andere in einer separaten Funktion geschehen Wir werden dieses eine Schießprojektil nennen. Es benötigt keine Argumente oder muss irgendeinen Wert zurückgeben, und wir haben noch keine Informationen, um diese Funktion zu schreiben, aber wir müssen diese Funktion deklarieren und speichern, bevor wir sie in die Casting-Animation aufnehmen können zur Charakterszene wechseln, wir zunächst ein animiertes Sprite zu Dende hinzu , das wir als Casting-Effekt verwenden können Dazu wird eine Sprite-Frames-Ressource benötigt. Bevor ich meine Spritesheets für Spell Casting importiere, erstelle ich einen neuen Ordner für magische Sprites und verschiebe den Dash Cooldown-Effekt Importiere dann Sprites für das Casting, das Projektil Hinzufügen der Casting-Animations-Sprites zur Sprite-Frames-Ressource zur Sprite-Frames-Ressource Y Ich stelle es auf 12 Bilder pro Sekunde ein, kein Und ich füge am Ende der Animation ein leeres Bild hinzu und verschiebe es dann mit dem Y-Offset um 18 Pixel nach oben Das sieht gut aus, aber wenn wir es auf die Figur Sprite ausrichten, wird sie ebenfalls in dieselbe Richtung gedreht wie die Figur den Animation Player-Knoten auswählen, können wir jede der vorhandenen Animationen duplizieren , um eine Casting-Animation zu erstellen Nachdem wir nicht benötigte Spuren entfernt und alle Sprite-Region-Keyframes aktualisiert haben, fügen wir Callmethoden-Tracks sowohl zum Stammknoten des Charakters Casting-Effekt Animiertes Sprite auf zwei D hinzu. Für den Casting-Effekt müssen wir ihm lediglich sagen, dass er abgespielt werden soll Für den Charakter fügen wir einen Keyframe Diese Keyframes können einfach so angepasst werden sie jederzeit während der Casting-Animation auftreten Ich starte den Cast-Effekt im zweiten Frame und feuere das Projektil im dritten Der Rest der Animation dient als Wiederherstellung. Im Animationsbaum müssen wir nur den gleichen Vorgang wiederholen, müssen wir nur den gleichen Vorgang wiederholen den wir mit dem Strich verwendet haben. Übergang zur Besetzung ist aktiviert, und am Ende der Animation kehren wir zur Bewegung zurück am Ende der Animation kehren wir zur Bewegung Als Nächstes bauen wir das eigentliche Projektil zusammen. Sie der Charakterszene zunächst eine D-Note für den Bereich zwei hinzu Charakterszene zunächst eine D-Note für den Bereich zwei Geben Sie ihr dann eine Kollisionsform und eine Formressource. Ich verwende einen Kreis, reduziere aber seinen Radius auf acht Pixel und ändere seine Debug-Farbe in eine Farbe, ich noch nicht verwendet habe, wie Lila Fügen Sie dann ein animiertes Sprite als Denode hinzu und geben Sie ihm eine Sprite-Frames-Ressource Zuerst fügen wir die Sprite-Frames für das Projektil so hinzu, wie es starten soll , und verwenden diese als Das Ganze wird wiederholt und ich stelle meine Bildrate auf 12 Bilder pro Sekunde ein Dann klicken wir auf die Schaltfläche „ Animation hinzufügen“, um eine zweite Sprite-Animation zu erstellen eine zweite Sprite-Animation und nennen diese etwa Impact Jetzt können wir weitere Sprite-Frames für eine Impact-Animation hinzufügen , die von demselben Projektil abgespielt wird , wenn es mit etwas kollidiert Möglicherweise möchten Sie am Ende dieser Animation auch ein leeres Bild hinzufügen , damit das letzte Bild während seiner gesamten Dauer gezeichnet Denken Sie daran, die Standardanimation auf Autoplay einzustellen, damit wir diese Animation abspielen, wenn das Projektil automatisch erzeugt das Projektil immer noch innerhalb der Charakterszene Sie das Projektil immer noch innerhalb der Charakterszene an der Stelle, an es im Verhältnis zum Charakter beginnen soll Du kannst das einfacher machen, indem du das Projektil und den Szenenbaum auswählst und die Alt-Taste gedrückt hältst, während du Meins befindet sich 12 Pixel weiter rechts und oben vom Ursprung des Charakters Als Nächstes fügen Sie eine Markierung mit zwei D-Knoten als untergeordnetes Objekt des Projektils Dadurch wird sichergestellt , dass seine Position exakt mit dem Projektil übereinstimmt Die Markierung zum D-Knoten entspricht exakt der eines zweiten D-Nodes, mit der Ausnahme, dass im Editor ein kleines Gizmo gezeichnet wird, sodass wir genau sehen können, wo Das gibt uns die Position, an der wir das Projektil beim Wirken des Zauberspruchs in unsere Szene spawnen wollen Projektil beim Wirken des Zauberspruchs in unsere Szene So können wir den Marker Tutti-Knoten entsprechend benennen. Dann ordnen Sie den Marker Tutti-Knoten dem Charakter Sprite neu zu Da es sich um ein untergeordnetes Element des Charakters Sprite handelt, kehrt er seine Ausrichtung um, wenn der Charakter seine Blickrichtung automatisch ändert . Speichern Sie den Projektilzweig als eigene Szene und speichern Sie ihn in einem neuen Szenenordner Lösche ihn dann aus der Charakterszene. Wir haben jetzt ein Projektil und wir wissen, wo wir es spawnen wollen, also kehren wir zum Spielercharakter-Skript Wir können das Projektil als gepackte Szene exportieren und es in den Inspektor einfügen Wir können uns auch einen Verweis auf die Spawn-Markierung holen. Es wäre besser, wenn es einen eindeutigen Namen hätte. Und wir müssen die magischen Kosten für das Abfeuern dieses Projektils angeben magischen Kosten für das Abfeuern dieses Projektils Ich setze meins auf 16 magische Punkte. Bevor der Spieler mit dem Wirken des Zauberspruchs beginnen kann, sollten wir auch überprüfen, ob er genug Magiepunkte hat, indem wir überprüfen, ob seine aktuelle Magie höher oder gleich den Magiekosten ist . Wenn dann die Zauberanimation die Funktion Projektil abschießen aufruft, da zwischen dem Aufruf dieser beiden Funktionen ein sehr kurzes Zeitfenster liegt , ist es keine schlechte Idee, auch noch zu überprüfen, ob der Charakter noch genug Magie hat um den Zauber hier erneut Prüft man also, ob die aktuelle Magie geringer ist als die Kosten, wird das Projektil beim Verlassen dieser Funktion nicht abgefeuert wissen, dass das nicht der Fall ist, können wir die Kosten von unserer aktuellen Magie abziehen und das aktuelle Magie-Signal ausgeben , um das HUD zu aktualisieren Dann erstellen wir ein neues Projektil indem wir die gepackte Szene instanziieren Wir wollen nicht, dass es dem Charakter als Kind folgt , sondern als Geschwisterkind innerhalb der Welt, sodass er sich selbstständig bewegen kann Also holen wir uns zuerst den Elternteil bevor wir als Kind dieses Projektil hinzufügen Stellen Sie dann seine Position innerhalb der Welt so ein, dass sie der globalen des Projektil-Spawn-Markers entspricht Wir müssen hier die globale Position verwenden, da sich die lokale Position des Markers auf die Position des Charakters bezieht, aber das Projektil wird zum Weltknoten hinzugefügt , nicht zum Wir wollen also die Position des Markers im Verhältnis zur Welt Und zum Schluss sagen wir diesem Projektil, in welche Richtung es abgefeuert wird Wir können ein Argument als Vector mit zwei Punkten links übergeben , wenn der Charakter nach links oder rechts zeigt, andernfalls Jetzt müssen wir diese Funktion für unser Projektil schreiben, die Projektilszene öffnen dann ein Skript zu ihrem Stammknoten hinzufügen, wir nennen es Projectile und speichern es im Es ist hilfreich, diesem Skript einen Klassennamen zu geben , damit wir später darauf verweisen können. Dieses Projektil benötigt einige exportierte Variablen, wie die Geschwindigkeit, mit der es sich bewegt, und die Höhe des Schadens, den es verursacht, wenn es auf etwas trifft Ich nenne diesen Standardschaden, damit er überschrieben werden kann , und gebe ihm den Wert eins Wir benötigen außerdem einen Verweis auf den Knoten Animated Sprite Tu Di um ihm mitzuteilen, welche Animation Es muss wissen, in welche Richtung es abgefeuert wird und wie viel Schaden es tatsächlich anrichten wird, wenn nicht die Standardeinstellung, und ob es sich gerade bewegt oder nicht Wenn wir aufgefordert werden, zu feuern, können wir die Richtung als Vektor zwei und die Höhe des Schadens als Ganzzahl mit einem Standardwert von Null akzeptieren zwei und die Höhe des Schadens , was ihn zu einem optionalen Parameter macht. Wir setzen die Richtung auf den Richtungsparameter und drehen das Sprite um, wenn der Richtungspunkt X kleiner als Null ist, also links Setzen Sie dann Schaden auf Schaden wenn ein Schadenswert angegeben wurde, andernfalls verwenden Sie den Standardwert für Schaden, und schließlich wird der Wert auf „Wahr“ gesetzt Überschreiben der Prozessfunktion. Wenn sich dieses Projektil bewegt, können wir seine Position so einstellen, dass plus gleich Richtung mal Geschwindigkeit mal Delta ist können wir seine Position so einstellen, dass plus gleich Richtung mal Geschwindigkeit mal Delta Dieses Projektil muss sowohl mit Körpern als auch mit Bereichen kollidieren sowohl mit Körpern als auch mit Also müssen wir sowohl die Signale für den eingegebenen Bereich als auch für den Körper mit dem Skript verbinden Signale für den eingegebenen Bereich als auch für den Körper mit dem den Körpern, mit denen dieses Projektil kollidieren wird , handelt es sich um das Gelände, während es sich bei den Bereichen um verletzte Boxen handelt Beide werden im Großen und Ganzen das Gleiche tun . Also rufen wir von beiden eine separate private Funktion auf und benennen sie beim Aufprall. Wenn das Projektil auf etwas trifft, lassen wir es aufhören, sich zu bewegen, deaktivieren dann weitere Kollisionen, indem wir seine Kollisionsmaske auf Null setzen Dadurch werden alle Ebenen der Kollisionsmaske ausgeschaltet. Spielen Sie dann die Aufprallanimation ab und verbinden Sie das Signal „Animation abgeschlossen der Viertelfunktion, um den Knoten automatisch aus der Szene zu entfernen. Wenn das Projektil eine Verletzungskiste trifft, können wir diese Verletzungsbox anweisen, den Schaden zu nehmen, bevor sie den Aufprall auslöst wir den Körperparameter nicht verwenden, können wir ihn mit einem Unterstrich als unbenutzt markieren Wenn das Projektil nichts trifft, müssen wir es trotzdem reinigen Eine einfache Möglichkeit besteht darin, dass der Raum automatisch zerstört, wenn es den Raum verlässt, in dem es gespawnt wurde , wäre es einfacher, dies über das Raumskript Anstatt dieses Signal jedes Mal für jeden Raum über den Inspektor zu verbinden , wäre es einfacher, dies über das Raumskript zu tun Also schreiben wir eine Funktion, bei der ein Bereich verlassen wird, einen Bereich als ein D ohne zwei akzeptiert und keinen Wert zurückgibt Falls es sich bei dem Bereich, der diesen Raum verlassen hat, um ein Projektil handelt, stellen wir es in die Warteschlange, bis es vom Szenenbaum befreit wird Verbinden Sie dann das Signal, das das Gebiet verlassen hat, mit der Bereitschaftsfunktion Wir können dies auch tun , um die vom Körper eingegebenen Signale automatisch miteinander zu verbinden Denken Sie nur daran, dass Sie, falls in einer Ihrer Raumszenen diese Signale bereits angeschlossen sind, Ihrer Raumszenen diese Signale bereits angeschlossen sind, diese trennen sollten, um Fehler zu vermeiden. Da wir jedoch Hunderte von Räumen einrichten, diese Signalverbindungen automatisch sparen wir viel mehr Zeit und Mühe, wenn wir diese Signalverbindungen automatisch per Skript Damit der Collider des Raums ein aus ihm austretendes Projektil erkennen kann, muss er die Kollisionsschicht maskieren, auf der das Projektil Wenn ich das Spiel starte, beginne ich bereits mit allen Fähigkeiten die im vorherigen Video freigeschaltet und meine Magieleiste Ich öffne den Remote-Szenenbaum, damit ich sehen kann , wie mein Projektil erscheint und wie es aufgeräumt wird ich zum Spiel zurückkehre, drücke den Schießknopf und wirf einen Zauberspruch aus, der das Projektil abfeuert Das Projektil kollidiert mit der Wand und explodiert Meine Magieanzeige wird um die Kosten des Zauberspruchs reduziert. das Projektil in die andere Richtung zielt , kann es nichts treffen und verlässt daher den aktuellen Raum Aber anstatt weiter in die Unendlichkeit zu fliegen, wird es zerstört, sobald es die Grenzen dieses Raums verlässt Wir haben jetzt all unsere freischaltbaren Fähigkeiten im Spiel und sind bereit, Feinde hinzuzufügen Wir sehen uns im nächsten Abschnitt. 50. 7-1 Tempo: Hallo, Freunde. In diesem Abschnitt werden wir unserem Spiel einige Feinde hinzufügen. Ich beginne damit, einen neuen Ordner für meine feindlichen Sprites zu erstellen und ein Spritesheet von meinem ersten Feind, der blinden Maus, zu importieren meinem ersten Feind, der blinden Maus, Wir benötigen auch einen neuen Szenenordner für Feinde. Wir können es einfacher machen, wenn wir unseren bestehenden Spielercharakter duplizieren unseren bestehenden Spielercharakter , um ihn als Vorlage zu verwenden, um uns zum Feind zu machen. Verschiebe ihn dann in den Ordner des Feindes. Wenn ich die neue Szene öffne, benenne ich den Stammknoten so um, dass er dem Namen der Szene entspricht. Gehen Sie dann die Szenenhierarchie durch und entscheiden Sie, welche Knoten für den Feind benötigt werden und welche nicht. Wir benötigen immer noch eine Kollisionsform um mit dem Gelände zu kollidieren, eine Hurt-Box , um Schaden zu erleiden, und einen Sprite, um den Charakter zu zeichnen Aber die Kinder des Sprites sind nicht notwendig, da dieser Feind weder andere Sprites noch die Fähigkeit besitzt, Projektile abzuschießen Wir behalten die Knoten Animation Player, Baum und Soundeffekt bei, obwohl du vielleicht die Sounds ändern möchtest Der Coyote-Timer wird nicht benötigt. Ob du möchtest, dass deine Feinde auf der Karte gezeichnet werden, liegt ganz bei dir, aber du musst natürlich die Textur ändern , wenn du dich dafür entscheidest, das Kartensymbol beizubehalten Und wir können auch alle Fähigkeitsknoten löschen. An den Stammknoten ist das Spielercharakterskript angehängt. Wir müssen es durch das normale Charakterskript ersetzen , da dies nicht der Spielercharakter ist und sie keine der Fähigkeiten des Spielercharakters haben. den Sprite Toti-Knoten auswählen, können wir die Atlas-Eigenschaft Atlas-Texturen durch ein Sprite-Blatt für unseren Feind ersetzen ein Sprite-Blatt für Da sich das Spritesheet von dem für meinen Spielercharakter unterscheidet, muss ich jede meiner Animationen in meinem Animation Player-Knoten durchgehen und überprüfen , ob sie die richtige Anzahl von Frames und die richtigen Frames und die richtigen Dieser Feind hat weniger Animationen als der Spielercharakter, sodass ich alles löschen kann, bis auf Idle und Walk Die Animation im Leerlauf funktioniert einwandfrei, da die eingegebenen Regionswerte exakt übereinstimmen, die Walk-Animation aber nicht. Deshalb muss ich sie korrigieren, damit sie mit den Regionswerten für das Spritesheet übereinstimmt den Regionswerten für das Spritesheet Ich aktualisiere schnell auf die Werte der eingegebenen Y-Region, damit diese Animation funktioniert Wir werden die Hit-and-Dead-Animationen vorerst ignorieren , da wir sie noch nicht testen können Der Animationsbaum wird eine viel einfachere Zustandsmaschine für diesen Feind benötigen , nicht dieselbe, die der Spielercharakter benutzt. Also werden wir eine neue Zustandsmaschinen-Ressource erstellen. Fügen Sie dann die Animationen „Idle“ und „Walk standardmäßig vom Start zum Leerlauf übergehen , wenn die X-Geschwindigkeit nicht Null ist, dann zurück zu Idle, wenn die X-Geschwindigkeit Null ist Das ist alles, was dieser Feind vorerst tun muss. Wenn wir uns das Charakterskript für einen Moment ansehen, das Drehbuch bereits alles, was wir brauchen, um einen Charakter hin und her bewegen zu können. Da ich allerdings nicht möchte, dass meine Gegner Kojotenzeit haben, muss ich entweder jeglichen Code, der sich darauf bezieht , so verschieben er nur im Charakterskript des Spielers enthalten ist, oder ich kann einfach sicherstellen, dass der Code, der sich auf die Kojotenzeit bezieht, nicht ausgeführt wird, wenn es keine Coyote-Zeit oder keinen Coyote-Knoten gibt Da ich bereits die Funktion get node oder null verwendet habe die Funktion get node oder null um nach dem Coyote-Timer-Knoten zu suchen, diese Variable Null, wenn kein solcher Knoten existiert. Das einzige Mal, dass wir den Coyote-Timer-Knoten verwenden , ist der Physikprozess, und wir können einfach überprüfen, ob es einen Coyote-Timer-Knoten gibt , bevor wir versuchen ihn als Startfunktion aufzurufen , um Fehler zu Derselbe Prozess könnte auch verwendet werden , wenn du nicht alle exakt gleichen Knoten in deine verschiedenen Charakter- und Feindeszenen für Dinge wie Sounds oder Partikeleffekte einbauen exakt gleichen Knoten in deine verschiedenen Charakter- und möchtest Lasst uns zu einer unserer bestehenden Rauminhaltsszenen wechseln unserer bestehenden Rauminhaltsszenen und diesen neuen Feind zum Raum hinzufügen. Mein Plan für diesen Feind ist , ihn hin und her bewegen zu lassen. Wenn sie gegen eine Wand stoßen, möchte ich, dass sie sich umdrehen, eine Sekunde warten und dann in die entgegengesetzte Richtung gehen. Also bearbeite ich mein Terrain, um eine einfache Plattform mit Wänden auf beiden Seiten zu erstellen . Also wird dieser Feind hier hin und her rennen. Ich werde auch eine weitere Plattform ohne Wände hinzufügen, und der Feind sollte in diesem Fall vom Felsvorsprung weggehen Vielleicht möchtest du ein anderes Skript schreiben, wie das vom Charakter erbte Spielercharakterskript, das auch dieses Verhalten beinhaltet Es ist jedoch besser, sich dieses Verhalten als Alternative zum Spielerknoten in der Spielszene vorzustellen , über den der Spieler den Spielercharakter steuern kann den Spielercharakter steuern Stattdessen schreiben wir ein Skript das das Verhalten dieses Feindes kontrolliert. Also werden wir als Kind des Feindes einen neuen Knoten erstellen. Ich nenne diesen Knoten Pace. Auf diese Weise kann dasselbe Verhaltensskript für mehrere verschiedene Gegner verwendet werden, und derselbe Feindtyp könnte auch mehrere verschiedene Verhaltensskripte haben. Wenn dieser Knoten in die eigene Szene des Feindes aufgenommen wird, wird er automatisch auf alle Gegner desselben Typs angewendet. Wenn man ihn in die Rauminhaltsszene einfügt, kann es sein , dass sich dieselben Gegner möglicherweise unterschiedlich verhalten. Wir werden ein Skript an diesen Knoten anhängen und es in einem neuen Skriptordner für Feinde ablegen. Um einem Feind zu sagen, was er tun soll, benötigen wir einen Verweis auf den Feind selbst, der in einer Variablen gespeichert ist. Wir können die Funktion G parent aufrufen , um das direkte Elternteil dieses Knotens zu ermitteln und es der Variablen mithilfe des Ready-Tags zuzuweisen . Beachten Sie, dass dies nur funktioniert, wenn der Verhaltensknoten ein direktes Kind des Feindes ist. Wir sollten auch eine Variable exportieren, um anzugeben , in welche Richtung sich dieser Feind zuerst bewegen wird. Also nenne ich sie Richtung und gebe ihr den Standardwert Eins, also nach rechts. wir die Prozessfunktion außer Kraft setzen, müssen wir nur die Bewegungsrichtung des Feindes in diese Richtung setzen , damit er anfängt zu laufen Wenn sich der Feind an einer Wand befindet, können wir dem Charakter sagen, dass er nach links schauen und seine Bewegungsrichtung auf Null setzen, sodass er stoppt Um eine kurze Zeit zu warten, benötigen wir einen Timer. Da dieser Knoten keinen Typ hat, können wir diesen Knoten selbst als Timer verwenden , indem wir seinen Typ ändern. Der Typ, den dieses Skript erweitert, muss ebenfalls in Timer geändert werden, um auf einen der Timer-Knoten, Eigenschaften oder Funktionen zugreifen zu können. Wir müssen das Timeout-Signal nicht verbinden, da wir nur wissen müssen ob der Timer gestoppt ist oder nicht Wenn der Timer gestoppt ist, setzen wir die Bewegungsrichtung des Feindes in die richtige Richtung Andernfalls können wir ihn auf Null setzen , da dieser Feind gerade wartet. Wenn der Charakter auf eine Wand trifft, stellen wir den Richtungswert so ein, dass er dem Sinus der Wände X normal ist, und starten den Timer. Damit der Charakter nach rechts schaut, wenn er gegen eine Wand zu seiner Linken stößt, müssen wir dies auch vom Sinus der Wände als Normalwert abhängig machen . Außerdem wollen wir den Charakter nur anhalten und ihn umdrehen, wenn seine aktuelle Bewegungsrichtung nicht der normalen Richtung der Wände entspricht Wir rufen diese Funktion get Wall normal mehrmals auf, daher wäre es effizienter sie in einer lokalen Variablen zu speichern Lassen Sie uns hier etwas leichtes Refactoring durchführen. In der Rauminhaltsszene können wir die Wartezeit anpassen und die One-Shot-Eigenschaft auf true setzen Ich dupliziere den Tempoknoten und füge ihn dem anderen Feind hinzu. Dann gebe ich meinen beiden Feinden unterschiedliche Werte für ihre anfängliche Temporichtung Wenn wir nun das Spiel mit Hilfe unseres Verhaltensskripts starten , bewegen sich die Gegner, einer nach links und der andere nach rechts Der zweite Feind verlässt die Kante, aber der erste trifft auf die Wand, dreht sich um und wartet eine Sekunde bevor er sich umdreht und in die andere Richtung geht Und beide wiederholen dieses Verhalten. Aber Sie haben vielleicht bemerkt, dass ihre Animationen nicht immer ihrer Geschwindigkeit entsprechen. Beide Charaktere animieren tatsächlich synchron Das liegt daran, dass sie, genau wie die Gesundheitssymbole, eine Ressource gemeinsam nutzen In der feindlichen Szene müssen wir den Sprite Two D-Knoten auswählen und die Atlas-Texturressource lokal für diese Szene einrichten Jetzt hat jede Instanz dieses Feindes ihre eigene Atlas-Textur und wir können unabhängig voneinander animieren Wenn jedoch eine Ihrer Animationen die Textureigenschaft des Sprite-Two-D-Knotens ändert, kann dies dazu führen, dass die Animationen, die darauf verweisen , beschädigt werden Ich lösche diesen Track aus meiner Reset-Animation. Wir benötigen auch nicht die Signalverbindung, die aus der Spielercharakterszene kopiert wurde, die zum Spielen von Jump Efforts verwendet wird. das Spiel erneut ausführen, können wir jetzt sehen, dass sie ihre Animationen im Leerlauf und beim Gehen korrekt abspielen können. Wir haben jetzt einen Feind, der hin und her laufen und sich an Wänden umdrehen kann , aber wir müssen auch sicherstellen, dass er den Raum nicht verlassen kann. Wir sehen uns im nächsten Video. 51. 7-2 Unsichtbare Wände: Hallo Freunde. In diesem Video werden wir verhindern, dass unsere Feinde den Raum verlassen, in dem sie erschienen sind Dazu müssen unsere Feinde mit unsichtbaren Wänden kollidieren, die den Spielercharakter nicht beeinträchtigen Wir haben den Körper des Spielercharakters auf Kollisionsebene neun maskiert das Terrain auf Ebene eins In unserer Feindeszene setzen wir die Körperkollisionsebene auf etwas anderes wie Ebene 17. Sie müssen immer noch die Terrainebene maskieren, aber wir werden auch eine zweite Ebene maskieren lassen , die wir für unsichtbare Wände verwenden werden. Ich werde Ebene fünf verwenden. Wenn ich die Projekteinstellungen öffne, benenne ich die Ebene Physik zwei D. Ich nenne Ebene 17 für Feind und Ebene fünf für unsichtbare Wände. In meiner Raumszene kopiere ich den Ebenenknoten „Kachelkarte“, der die Karte zeichnet, da dieser bereits die Grenzen des Raums enthält. Fügen Sie ihn dann in die Inhaltsszene ein und benennen Sie ihn in Unsichtbare Wände um. die Layer-Notiz „Kachelkarte“ ausgewählt auf die Ressource „ Kachelset“ klicken, müssen wir diesem Kachelsatz eine Physik-Ebene hinzufügen, sich auf Ebene fünf für unsichtbare Wände befindet. Im Bereich „Kachelset“ können wir diese Physikebene auf die Kachel malen. dem Malwerkzeug und der ausgewählten Kachel zum Bereich „Kachelkarte“ wechseln mit dem Malwerkzeug und der ausgewählten Kachel zum Bereich „Kachelkarte“ wechseln, können wir die Türen dieses Raums schließen und den Raum auf allen Seiten vollständig versiegeln, wobei eine Physikebene nur von Feinden und nicht vom Spielercharakter maskiert von Feinden und nicht vom Spielercharakter Wir wollen nicht, dass diese unsichtbaren Wände auf der Karte gezeichnet werden, also sollten sie sich auch nicht auf Sichtbarkeitsebene zwei befinden, und wir wollen sie sehen können, während wir testen Lassen Sie uns sie auf Sichtbarkeitsebene eins platzieren. Ich bearbeite das Terrain und bewege meine Gegner so, dass sie sich frei im gesamten Raum bewegen können . Wenn wir jetzt das Spiel starten, laufen die Gegner zum Rand des Raums, werden aber von den Wänden umgedreht. Während unser Spielercharakter sie direkt durchqueren kann. Ich würde es vorziehen, wenn sich diese Wände außerhalb des sichtbaren Bereichs des Raums befinden würden , also schiebe ich sie jeweils um ein weiteres Feld heraus. Alles, was wir tun müssen, um die Wände für den Spieler komplett unsichtbar zu machen , ist ihre sichtbare Eigenschaft auszuschalten, entweder im Szenenbaum oder im Inspektor Jetzt müssen wir dafür sorgen, dass dieser Feind den Spieler tatsächlich bedroht, was wir bereits zuvor getan haben Alles, was wir tun müssen, ist ein Gebiet zum D-Knoten hinzuzufügen und es Hit Box zu nennen. Geben Sie ihm als Kind dem D-Knoten eine Kollisionsform und geben Sie dem Tut-Knoten der Kollisionsform eine Shape-Ressource. Stellen Sie das Trefferfeld so ein, dass es die Verletzungsbox des Spielers maskiert. Und es muss überwacht werden. Hängen Sie dann das Hit-Box-Skript an und verbinden Sie das Signal im eingegebenen Bereich. A Wenn wir jetzt das Spiel starten, der physische Kontakt mit verursacht der physische Kontakt mit einem Feind, dass der Spielercharakter Schaden erleidet. Wir werden uns im nächsten Abschnitt damit befassen, den Kampf spannender zu gestalten. Lassen Sie uns zunächst mit diesen Fehlermeldungen umgehen. Diese Fehlermeldungen treten , wenn wir den Inhalt eines Raums laden. Das liegt daran, dass wir den Rauminhalt als Reaktion auf ein Kollisionsereignis laden den Rauminhalt als Reaktion auf , wenn der Körper des Spielercharakters einen Raum betritt. Und Godot mag es nicht, wenn wir weitere Kollisionsbereiche oder Objekte hinzufügen weitere Kollisionsbereiche oder Objekte während er bereits damit beschäftigt ist Kollisionen für diesen aktuellen Frame zu lösen Wenn wir also den Hinweis in den Fehlermeldungen befolgen und den Befehl „Deferred“ verwenden, wird die Game-Engine angewiesen, den Inhalt des Raums zu laden, nachdem die Kollisionsauflösung für den aktuellen Frame abgeschlossen ist nachdem die Kollisionsauflösung für den aktuellen Frame abgeschlossen für den Godot-Zyklus beginnt mit Eingabeverarbeitung, gefolgt von der Physik, die Kollisionen einschließt, verarbeitet und endet mit verzögerten verarbeitet und endet Wir können dies also verwenden, um jede beliebige Aktion als letztes vor dem Ende eines Frames Wenn das Spiel erneut ausgeführt wird, gibt es keine Fehlermeldungen mehr. Unser Feind bleibt jetzt in diesem Raum und kann den Spielercharakter verletzen. Aber wir müssen unserem Spiel mehr Feindvielfalt verleihen. Wir sehen uns im nächsten Video. 52. 7-3 Kantenerkennung: Hallo Freunde. In diesem Video fügen wir einen weiteren Feind hinzu, der Keile erkennen und sich umdrehen kann , anstatt von ihnen wegzulaufen. Wir werden damit beginnen, unseren bestehenden Feind zu duplizieren. öffnen die feindliche Szene und Wir öffnen die feindliche Szene und ändern den Namen des Stammknotens so, dass er dem Feind entspricht Importieren Sie ihr Spritesheet und legen Sie es im Inspektor als Atlas Alle Sprites für das Spritesheet sind dieselben wie beim ersten Feind, es gibt also nichts zu korrigieren , was die Animationen angeht In meiner Rauminhaltsszene entferne ich die beiden Gegner und füge diesen neuen Feind hinzu. Dann bearbeite ich das Terrain so, dass sie sich auf einer erhöhten Terrasse mit einem Felsvorsprung auf beiden Seiten befinden einer erhöhten Terrasse mit einem , der Ich möchte, dass dieser Feind am höheren Felsvorsprung anhält, einen Moment wartet, sich dann umdreht und in die andere Richtung läuft Aber dann sollten sie von der kürzeren Kante weggehen. Was die Mauern angeht, sollten sie sich genauso verhalten wie der vorherige Feind Da dieses Verhalten so ähnlich ist, wäre es gut, dasselbe Skript zu verwenden. Also füge ich als Kind des Feindes eine Timer-Notiz hinzu. Benennen Sie es um, hängen Sie das Temposkript und setzen Sie seine One-Shot-Eigenschaft auf true. Dieser Feind sollte sich also genau wie die blinde Maus verhalten. Jetzt müssen wir nur noch herausfinden, wann der Feind auf einen Felsvorsprung zugeht können wir mit einem neuen Knotentyp tun, einem Cast Two-D-Knoten Wir werden diesen Knotenkantendetektor nennen. Bewege es dann ein kurzes Stück zur Rechten des Charakters und dann nach oben. Der Strahl hat eine Kollisionsmaske, die bereits auf Ebene eins für das Terrain eingestellt ist. den Kollisionsbereich erweitern, ist unser Terrain ein physischer Körper, der Strahl wird also mit diesem kollidieren Wenn Sie einen Ray-Cast-Knoten verwenden, um Bereiche zu erkennen müssen Sie die Bereiche hier überprüfen, bevor es funktioniert Der Strahlwurf wird im Editor als Pfeil dargestellt, aber unsichtbar, während das Spiel läuft, genau wie unsere Kollisionsbereichsknoten. Er feuert einen Strahl ab, der von seiner Position in Pfeilrichtung ausgeht und meldet, ob er auf etwas trifft oder nicht. In diesem Fall, ob er auf Gelände trifft oder nicht. Wenn es also auf Gelände trifft, sich der Feind weiter vorwärts, und wenn nicht, muss der Charakter anhalten. Die Entfernung rechts vom Charakter bestimmt , wie weit er nach dem Felsvorsprung Ausschau hält Die Entfernung vom Boden hat keine große Wirkung solange sie sich über dem Boden und unter der Körpergröße des Charakters Die Zielposition sollte nach unten zeigen , um den Boden zu erkennen, aber wie weit der Strahl schießt, beeinflusst was er als Felsvorsprung betrachtet und was nicht Ich stelle meinen auf eine Tiefe von 64 Pixeln oder zwei Kacheln ein. Das heißt, wenn der Feind auf einen Felsvorsprung trifft , der nur ein Kachel hoch ist, wird er trotzdem davonlaufen Aber wenn er zwei oder mehr Steine hoch ist, trifft der Strahl kein Terrain und der Feind hält daher Im Gegensatz zu Kollisionsgebieten sendet der Ray-Cast-Knoten jedoch keine Signale aus, auf die wir reagieren können. Also müssen wir unser eigenes Skript an diesen Knoten anhängen. Ich lege es in den Ordner Enemy Scripts. Wir können damit beginnen, unser eigenes Signal zu deklarieren, das wir zulassen wollen, wenn ein Felsvorsprung entdeckt wird, und weiterleiten als Ganzzahl die Richtung des Felsvorsprungs im Verhältnis zum Feind Es ist allerdings nicht ganz so einfach, ob der Strahl auf etwas trifft oder nicht Ähnlich wie wir dafür gesorgt haben, dass der Coyote-Timer nur genau dem Frame startet wenn der Charakter von einem Felsvorsprung weggeht, wollen wir eine Kante nur einmal während des exakten Frames erkennen , wenn der Strahl aufhört, mit dem Gelände zu kollidieren exakten Frames erkennen , wenn der Strahl aufhört, mit dem Gelände zu kollidieren Wir benötigen also eine boolesche Variable dafür, ob der Strahl im letzten Frame auf das Terrain traf oder nicht, und weitere vier, wenn er in diesem Frame auf Terrain trifft letzten Frame auf das Terrain traf oder nicht, und weitere vier, wenn er in diesem Frame auf Terrain weitere vier Während des physikalischen Prozesses setzen wir was colliding auf den vorherigen Wert von is colliding und dann I colliding auf den aktuellen Wert, der durch den Strahlwurf zurückgegeben Wenn der Strahl im letzten Bild kollidiert , aber nicht mit diesem Bild kollidiert, ist dies genau der Moment, in dem wir eine Kante erkannt haben und Die Richtung der Kante kann nur das Zeichen für die Position des Knotens sein Zeichen für die Position des Knotens Lassen Sie uns unser von der Leiste erkanntes Signal mit dem Pace-Skript verbinden und eine Funktion namens wait and turnaround aufrufen Wir können diese drei Zeilen von oben kopieren, die dem Feind sagen, dass er anhalten soll, die Temporichtung ändern und den Timer starten Ersetzen Sie sie dann durch einen Aufruf unserer Funktion. Aber wir müssen das Gegenteil der Wandnormalen X als Richtungsargument angeben, damit es dem entspricht, was vom Kantendetektor passiert wird. Der Leistendetektor sendet die Richtung zur Kante. Hier müssen wir also die Richtung zur Wand angeben. Die neue Schrittrichtung ist daher das Gegenteil des Richtungsparameters Das funktioniert, solange sich der Feind nach rechts bewegt, aber wir müssen den Einsatzknoten links des Feindes neu positionieren , wenn er sich umdreht Zum Glück haben wir bereits jedes Mal ein Signal ausgegeben , wenn ein Charakter die Richtung ändert Wir müssen dieses Signal also nur mit dem Kantendetektor verbinden , um darauf zu reagieren. Benennen wir es um, wenn der Feind die Richtung geändert hat. Da wir dadurch ihre neue Richtung erhalten, setzen wir die Position des Knotens einfach auf den absoluten Wert seiner Position, multipliziert mit minus Eins, falls Richtung kleiner als Null ist, andernfalls positiv Rückverfolgung dieser Richtungsänderung signalisiert, dass das Auslassen bis zum Zeichenskript zurückgeht Ich habe das ursprünglich geschrieben, indem ich die Bewegungsrichtungsvariable als Signalparameter übergeben die Bewegungsrichtungsvariable als Signalparameter Dies funktioniert jedoch nicht in dem Kontext, in dem wir diesen feindlichen Charakter verwenden, da der Wert der Bewegungsrichtung nicht unbedingt der Richtung entspricht, in die wir ihnen sagen, dass sie zuschauen sollen. Anstatt die Bewegungsrichtung zu übergeben, ist es genauer, eine negative Richtung zu übergeben, wenn der Charakter angewiesen wird, nach links zu schauen, oder eine positive Richtung für rechts. Jetzt befindet sich der Strahl immer vor dem Charakter, egal ob er nach links oder rechts schaut. Lassen Sie uns die sichtbaren Kollisionsformen einschalten, damit wir den Strahlwurf sehen können , während das Spiel läuft, und drücken Sie auf Play. Der Strahlwurf wird rot dargestellt , wenn er mit etwas kollidiert Unser Feind nähert sich dem ersten Felsvorsprung. Der Strahl färbt sich blau, um anzuzeigen, dass er nichts trifft Der Feind hält für kurze Zeit an, dreht sich dann um und geht in die andere Richtung Nähert man sich dem kürzeren Felsvorsprung, ist der Strahlwurf so lang , dass er immer noch das Terrain trifft, sodass der Feind davonläuft und in dieselbe Richtung weitergeht Schließlich treffen sie auf die unsichtbare Wand am äußersten Rand des Raums und drehen sich wie der vorherige Feind um. Wir haben jetzt einen zweiten Feindtyp , der sich anders verhält als der erste, aber wir brauchen viel mehr Abwechslung, damit unser Spiel Spaß macht Wir sehen uns im nächsten Video. 53. 7-4 Fliegen: Hallo Freunde. In diesem Video fügen wir einen fliegenden Feind hinzu , der durch einen Raum springt Beginnen wir mit dem Import eines neuen Spritesheets für den fliegenden Feind Dann duplizieren Sie eine der vorhandenen feindlichen Szenen. Nachdem wir die neue feindliche Szene geöffnet haben, benennen wir den Stammknoten entsprechend um und tauschen den Atlas durch das richtige Spritesheet aus den Atlas durch das richtige Spritesheet Diese Sprites haben im Gegensatz zu den anderen Gegnern bisher eine Größe von 32 Pixeln im Quadrat im Gegensatz zu den anderen Gegnern bisher eine Größe von 32 Pixeln im Deshalb passe ich jetzt die Y-Position des Sprites an, um sie etwas abzusenken Dieser Feind hat keine separaten Animationen im Leerlauf und beim Gehen Deshalb entferne ich die Walk-Animation und bearbeite die Idle-Animation , sodass sie die richtige Anzahl von Frames hat Bearbeiten Sie dann die eingegebenen Werte für die Animation im Leerlauf so, dass sie die richtige Pixelhöhe Jetzt sieht die Animation im Leerlauf korrekt aus. Wenn ich die Sichtbarkeit der Kollisionsform des Charakters aktiviere, drehe ich sie um 90 Grad, sodass die Kapsel waagerecht ist, drehe ich sie um 90 Grad, sodass die Kapsel waagerecht ist, was der Form dieses Feindes besser entspricht , und passe Radius und Höhe nach Bedarf an. Machen Sie dann dasselbe mit der Hurt-Box. Und die Trefferbox mit Kontaktschaden. Achten Sie darauf, dass sie der Größe und Form des Feindes entspricht, damit sich jeder Schaden, der dem Spieler zugefügt wird, fair anfühlt Was die Animationsbaum-Zustandsmaschine angeht, da es momentan nur eine Animation gibt, braucht sie nur einen Ruhezustand, der von Start zu Inaktivität übergeht von Start das Skript angeht, das an den Wurzelknoten dieses Feindes angehängt ist, so brauchen wir diesen Feind nicht, um zu laufen oder zu springen, aber wir brauchen trotzdem, dass dieser Feind in der Lage ist, nach links oder rechts zu schauen, beschleunigen und zu bremsen, von der Schwerkraft und der Endgeschwindigkeit beeinflusst zu werden usw. Es hat also genug Vorteile, hier immer noch das gleiche Zeichenskript zu verwenden hier immer noch das gleiche Zeichenskript anstatt bei Null anzufangen Aber das Verhalten eines Feindes , der fliegen kann, ist so unterschiedlich, dass wir eine neue Unterklasse schreiben sollten , die vom Charakter erbt Lassen Sie uns also ein neues Skript namens Flying Enemy erstellen, vom Charakter erbt, und speichern wir es im Ordner Enemy Unser fliegender Feind braucht eine Richtung, um fliegen zu können. Im Gegensatz zum Gehen oder Laufen, das als Schwebe dargestellt wird, da es sich nur um die X-Achse kümmern muss, kann eine Flugrichtung eine beliebige Richtung bis zum D-Raum sein, also speichern wir sie in einem Vektor zwei. Wir benötigen außerdem eine boolesche Variable, um zu wissen, ob dieser Feind gerade fliegt oder nicht Wir können dann den physikalischen Prozess überschreiben eine neue Prüfung hinzufügen, um zu sehen, ob der Feind fliegt, und wenn ja, eine fliegende Physikfunktion aufrufen Wenn der Feind nicht fliegt, können wir die Superklassen-Definition des physikalischen Prozesses als normal bezeichnen . Vielleicht möchtest du auch eine Fluggeschwindigkeit als Float exportieren, wenn du einen Feind haben möchtest, der unterschiedliche Geh - und Fluggeschwindigkeiten hat . Ich gebe ihm einen Standardwert von 100 Pixeln pro Sekunde. Ich halte die Strg- oder Befehlstaste gedrückt und klicke auf diesen Funktionsaufruf des Superclass-Physikprozesses, um direkt zu seiner Deklaration zu gelangen , sodass wir uns ansehen können, was er enthält Beachten Sie, dass sich der Funktionsaufruf von move and slide innerhalb der Superklassendefinition unseres physikalischen Prozesses befindet innerhalb der Superklassendefinition unseres physikalischen Prozesses Diese Funktion muss aufgerufen werden, um den Körper des Charakters auf die Geschwindigkeit von Dnode anzuwenden und Kollisionen zu prüfen Wir wollen auch weiterhin, dass unser fliegender Feind in die Richtung schaut, in die er Also müssen wir das in der Flugphysik-Funktion machen. Ich kopiere diesen Codeblock und kehre zum Flying Enemy-Skript zurück und füge ihn in meine Flugphysik ein. Anstatt den Wert der Bewegungsrichtung zu überprüfen, müssen wir den Wert von Flugrichtungspunkt X überprüfen Außerdem müssen wir weiterhin die Bewegungs- und Gleitfunktion aufrufen , wenn der Feind fliegt. Wir können dann eine ähnliche Logik, die wir für die Luftkontrolle verwendet haben, auf unsere nicht fliegenden Charaktere anwenden Luftkontrolle verwendet haben, auf unsere nicht fliegenden Charaktere , um unseren fliegenden Feind zum Fliegen zu bringen. Wenn die Flugrichtung einen Wert hat, bewegen wir die Geschwindigkeit des Feindes in Richtung der Flugrichtung multipliziert mit der Fluggeschwindigkeit in Richtung der Flugrichtung multipliziert mit der Fluggeschwindigkeit zwar bei einer Beschleunigungsrate multipliziert mit der Beschleunigungsrate multipliziert mit Luftkontrolle multipliziert mit Delta Oder wenn keine Flugrichtung angegeben ist, können wir ihre Geschwindigkeit mit einer Geschwindigkeit von Verzögerung multipliziert mit Luftbremsen multipliziert mit Delta in Richtung Vektor zwei Punkt Null bewegen einer Geschwindigkeit von Verzögerung multipliziert mit Luftbremsen multipliziert O. Als wir nur Velocity Punkt X bearbeitet haben, was ein Float ist, ein primitiver Datentyp, mussten wir Godot move toward function aufrufen, um toward function Aber da ein Vektor Zwei eine Klasse ist, kann er seine eigenen Funktionen haben - oder Befehlstaste gedrückt halten und auf den Klassennamen klicken , gelangen wir zur Dokumentation für diese Klasse, in der wir bei Bedarf alle ihre Eigenschaften und Funktionen einsehen können . Hier haben wir also die Möglichkeit velocity dot move toward aufzurufen, was sich von der Godot-Funktion move toward dadurch unterscheidet , dass der erste Parameter bereits als der Vektor selbst bekannt ist Möglicherweise möchtest du auch verschiedene Werte für Flugbeschleunigung, Verzögerung, Luftsteuerung und Luftbremsen für deine fliegenden Gegner exportieren für Flugbeschleunigung, Verzögerung, , wenn du möchtest, dass sie unterschiedliche Werte verwenden, während sie Außerdem benötigen wir eine öffentliche Funktion , die diesem Feind mitteilt, dass er fliegen soll ein Vektor-Zwei-Parameter für die Flugrichtung akzeptiert für die Flugrichtung Und noch einen für den Zeitpunkt, an dem wir aufhören sollen zu fliegen. Dadurch wird die Flugvariable gesteuert und gleichzeitig die Flugrichtung festgelegt. Denken Sie daran, dieses fliegende Feind-Skript an den Wurzelknoten des Feindes in seiner eigenen Szene anzuhängen . In der Rauminhaltsszene unserem neuen fliegenden Feind tun, genauso wie unsere bestehenden Feinde einen separaten Knoten haben, der ihnen sagt, wie sie sich verhalten sollen werden wir dasselbe mit unserem neuen fliegenden Feind tun, genauso wie unsere bestehenden Feinde einen separaten Knoten haben, der ihnen sagt, wie sie sich verhalten sollen. Ich lösche diesen Feind aus der Szene und füge zwei dieser neuen fliegenden Feinde hinzu. Dann bearbeite ich das Terrain so , dass es einen von ihnen in eine Geländebox einschließt , damit wir sehen können, wie es sich etwas einfacher verhält Ich möchte, dass diese Fledermäuse in diagonaler Richtung fliegen und von jeder Wand, Decke oder jedem Boden abprallen , mit denen sie in Kontakt kommen also beiden einen Basisknoten anhänge, nenne ich ihn Ricochet Hängen Sie dann ein Skript an diesen Knoten an und speichern Sie es im Ordner Enemy Dieses Skript benötigt eine exportierte Variable für die anfängliche Flugrichtung. Ich verwende den Vektor 21 , der sich unten rechts befindet. Wir benötigen außerdem einen Verweis auf den Feind , dessen Verhalten wir kontrollieren, auf diesen Knoten gesetzt, Elternteil den Tag on ready verwendet. die Bereitschaftsfunktion außer Kraft zu setzen, wäre es eine gute Idee, die Flugrichtung zu normalisieren Durch die Normalisierung eines Vektors wird sichergestellt , dass er eine Länge von genau eins hat Da ein Vektor mit einem Wert von 11 länger als eins ist, würde dies dazu führen, dass die Fledermaus schneller als ihre Fluggeschwindigkeit fliegt Aber wenn wir den Vektor normalisieren, verwenden wir nur die Richtung des Vektors, nicht seine Länge. Indem wir die Prozessfunktion außer Kraft setzen, können wir dem Feind sagen, dass er in die gewünschte Flugrichtung fliegen soll in die gewünschte Flugrichtung fliegen Aber bevor wir das tun, müssen wir überprüfen, ob dieser Feind gerade Kontakt mit einer Wand, Decke oder einem Boden In jedem dieser Fälle können wir dann den Punkt X oder Punkt und Y für die Flugrichtung auf den entsprechenden Wert setzen. Für die Decke entspricht der Wert dem absoluten Wert des Flugrichtungspunktes Y, sodass er immer positiv ist, also nach unten. Beim Boden ist das Gegenteil der Fall, der absolute Wert mit dem negativen Wert multipliziert wird, also nach oben Bei Wänden können wir einfach den absoluten Wert des Punktes X in Flugrichtung mit dem Vorzeichen des Wandnormalpunkts X multiplizieren , der von der Wand weg zeigt Ich hänge das Ricochet-Skript auch dem anderen Feind an und drücke dann auf Play Wenn wir das Spiel ausführen, können wir sehen, dass die Fledermaus herumspringt und von allen Wänden , Decken und Böden abprallt, die sie berührt, wodurch ein interessantes Hindernis entsteht, ein interessantes Hindernis Wir haben jetzt einen fliegenden Feind, den wir bekämpfen müssen, aber wir sollten mindestens einen weiteren Feindtyp haben , mit dem sich unsere Spieler auseinandersetzen Wir sehen uns im nächsten Video. 54. 7-5 Kriecheln: Hallo Freunde. In diesem Video machen wir uns einen Feind, der auf jeder Oberfläche kriechen kann, auch an Wänden und Decken Beginnen wir mit dem Import eines Spritesheets für diesen Feind. Dann duplizieren Sie den fliegenden Feind. Nachdem ich die neue feindliche Szene geöffnet habe, benenne ich den Stammknoten um. Tauschen Sie dann die Atlas-Textur des Sprite-Atlas mit zwei D-Knoten gegen das entsprechende Sprite-Blatt Im Animation Player des Feindes aktualisiere ich die Animation im Leerlauf , sodass sie die korrekte Anzahl von Frames enthält, die das Spritesheet zur Verfügung stellt Aktualisierung der eingegebenen Regionswerte nach Bedarf. Da wir wollen, dass dieser Feind nicht nur auf dem Boden, sondern auch auf den Wänden und der Decke kriecht , wäre es hilfreich, wenn wir den Feind rotieren Da der Feind seinen Ursprung zu Füßen hat, so wie wir jeden anderen Feind geschaffen haben, wird seine Rotation alles um diesen Punkt Um die Sache ein wenig einfacher zu machen, wäre es besser, den Ausgangspunkt kriechender Gegner in ihrer Mitte zu platzieren, damit diese Rotationen flüssiger aussehen Also werde ich das Sprite und alle Kollisionsformen so zentrieren , dass sie am Ausgangspunkt zentriert sind Wenn wir diesen Feind nun drehen, bleibt er in derselben relativen Position Ich werde die Hurt-Box und die Trefferbox schnell anpassen , damit sie besser zur Form dieses Feindes passen. Für die Kollisionsform des Charakters verwende ich jedoch eher einen Kreis als eine Kapsel. Da dieser Feind rotieren kann, die Kollisionsform, dass es bedeutet die Kollisionsform, dass es sich bei der Kollisionsform um einen Kreis , bewirkt handelt, keine Änderung der Art und Weise, mit der der Feind kollidiert Wenn du strikte 90-Grad-Drehungen verwendest, würde auch eine quadratische Kollisionsform funktionieren, aber bei konvexen Ecken wären einige zusätzliche Schritte erforderlich bei Also bleibe ich bei der Verwendung eines Kreises. In der Szene mit dem Rauminhalt entferne ich die Fledermäuse und ersetze sie durch zwei Schnecken Das Ziel ist, dass diese Schnecken sowohl auf der Innen- als auch auf der Außenseite dieser Kiste herumkrabbeln sowohl auf der Innen- als auch auf der Außenseite So wie wir ein neues Skript erstellt haben, das vom Charakter für fliegende Feinde übernommen wurde, schreiben wir ein anderes für kriechende Feinde und speichern es im Ordner Feindliche Skripte Ersetze dann das an den Feind angehängte Skript durch dieses neue Ich werde meine Schnecke verlangsamen, indem ihre Gehgeschwindigkeit auf nur 32 Pixel pro Sekunde setze Zuerst müssen wir die Richtung zur Oberfläche, auf der dieser Feind gerade kriecht, als Vektor zwei kennen die Richtung zur Oberfläche, auf der dieser Feind gerade kriecht, als Vektor Dann auch die Vorwärtskriechrichtung als weiterer Vektor zwei Wir müssen hier auch unsere eigenen Kollisionen regeln, anstatt uns darauf zu verlassen , dass die Bewegungs- und Gleitfunktion des Charakters die gesamte Physik für uns erledigt Wir können also Kollisionsdaten in einer anderen Variablen vom Typ kinematische Kollision zwei D speichern vom Typ kinematische Kollision zwei . Indem wir den physikalischen Prozess außer Kraft setzen, prüfen wir, ob dieser Feind gerade an einer Oberfläche feststeckt, und wenn ja, rufen wir den physikalischen Prozess für das Wenn sie nicht an einer Oberfläche haften, können wir den physikalischen Prozess der Superklasse nennen Das funktioniert, weil ein Vektor zwei mit seinen Standardwerten Null, Null von der if-Anweisung als falsch und jeder andere Wert als wahr behandelt wird als falsch und jeder andere Wert als wahr Wenn sie nicht an einer Oberfläche haften, werden wir auch prüfen wollen, ob dieser Feind auf einer Oberfläche haften kann. Wenn wir eine etwas andere Funktion als Move und Slide aufrufen, rufen wir Move and Collide Diese Funktion akzeptiert die Bewegung der Figur als ersten Parameter, h. ihre Geschwindigkeit multipliziert mit Delta Die Funktion gibt eine kinematische Kollision zwei D zurück, die wir unserer Variablen zuweisen können Ähnlich wie unser Vektor zwei in einer if-Anweisung verwendet werden kann, können auch diese Kollisionsdaten Wenn keine Kollision aufgetreten ist, wird sie als falsch betrachtet. Und wenn es zu einer Kollision gekommen ist, wird sie als wahr angesehen. Wenn dieser Feind mit etwas kollidiert ist, gehen wir davon aus, dass er sich daran halten möchte, und legen den Wert „An der Oberfläche kleben “ fest Wir können auf normale Kollisionen zugreifen , indem wir die Funktion get normal aufrufen Das ist ein Vektor, der von der Oberfläche wegzeigt, mit der der Charakter am Kollisionspunkt kollidiert Da wir möchten, dass der Wert dieser Variablen zur Oberfläche zeigt nicht von ihr weg, können wir sie einfach um 180 Grad drehen und die gedrehte Funktion aufrufen Aber Rotationen in Godot verwenden keine Grade. Sie verwenden Radiant, und 180 Grad entspricht Pi-Radiant Oh, wenn der Feind mit keiner Oberfläche kollidiert ist, dann sprechen wir von einem physikalischen Prozess der Superklasse Aber der physikalische Prozess der Superklasse wendet auch die Geschwindigkeit des Charakters wenn er Move und Slide aufruft Gemäß diesem Code wird die Geschwindigkeit der Figur zweimal in jedem Frame angewendet solange sie keine Oberfläche berührt Wir können dies beheben, indem wir einen zweiten optionalen Parameter an die Funktion Move and Collide übergeben einen zweiten optionalen Parameter , sich um einen booleschen Test handelt Wenn der Wert wahr ist, sucht diese Funktion nur nach Kollisionen, bewegt den Charakter aber nicht . Jetzt, da unser Feind automatisch an einer beliebigen Oberfläche haften bleibt, können wir uns mit der Physik des Krabbelns auf dieser Oberfläche befassen Zuerst wenden wir die Schwerkraft auf die Oberfläche an, an der der Feind feststeckt, da wir das vorher nicht für den Kollisionstest gemacht haben. Das hilft auch, den Feind auf der Oberfläche zu halten , auf der er kriecht bewegen und kollidieren aufrufen, die Richtung zur Oberfläche wechseln, multipliziert mit der Schwerkraft, multipliziert mit Delta, unsere Kollisionsdaten nun die Kollision enthalten unsere Kollisionsdaten nun die Kollision mit der Wir können uns dann danach verzweigen, ob eine Kollision stattgefunden hat oder nicht Falls sich der Winkel der Oberfläche geändert hat, können wir die Richtung zur kriechenden Oberfläche aktualisieren und dann die Vorwärtsrichtung berechnen handelt es sich lediglich um die um 90 Grad gedrehte Richtung zur Oberfläche Wenn Pi 180 Grad beträgt, dann ergibt Pi geteilt durch zwei 90 Grad. Die Drehrichtung hängt jedoch davon ab , ob der Feind nach links oder rechts schaut. Wenn sie nach links zeigen, müssen wir uns im Uhrzeigersinn drehen Wenn sie nach rechts zeigen, drehen wir Uhrzeigersinn, um ihre Vorwärtsrichtung als Vektor zwei Und wenn sich diese Werte seit dem vorherigen Frame geändert haben , müssen wir auch die Rotation des Feindes aktualisieren, um sie in die richtige Richtung zu zeichnen Da der Feind in seiner Szene mit einer Drehung um Null nach rechts schaut, müssen wir nur die Vorwärtsrichtung verwenden und dann die Winkelfunktion aufrufen. Die Winkelfunktion gibt den Winkel zwischen einem beliebigen Vektor zwei und der positiven X-Achse zurück . Aber da wir die negative X-Skalierung verwenden um den Charakter umzudrehen, wenn er nach links zeigt, müssen wir das auch bei der Drehung korrigieren , indem wir ihn um weitere 180 Grad oder Pi-Radiant drehen, wenn der Feind nach links schaut Jetzt, wo der Feind an der Oberfläche feststeckt und wir wissen, in welche Richtung er kriechen will, können wir, wenn dem Feind gesagt wird, dass er sich bewegen soll, wenn dem Feind gesagt wird, dass er sich bewegen soll, endlich wieder die Bewegungs- und Kollisionsfunktion verwenden , um ihn in seine Vorwärtsrichtung zu bewegen, multipliziert mit der Bewegungsgeschwindigkeit, multipliziert mit Delta. Falls es aufgrund dieser Bewegung zu einer Kollision kommt, bedeutet das, dass er mit einer konkaven Ecke kollidiert Alles, was wir hier tun müssen, ist Richtung zur neuen Oberfläche neu zu berechnen Der nächste Physik-Frame erledigt den Rest. Wenn es keine Kollision gab, kriecht der Feind sanft über eine ebene oder konvexe Oberfläche Wenn keine Bewegungsrichtung angegeben wurde, bleiben sie still Gehen wir zurück zur ersten WF-Aussage: Wenn die Schwerkraft zur Oberfläche nicht zu einer Kollision geführt hat, bedeutet das, dass der Feind irgendwie den Kontakt zu der Oberfläche verloren hat , auf der er gekrochen Also sollten wir eine Funktion aufrufen, die sie wieder auf eine normale Ausrichtung zurücksetzt Ich nenne es Unstick und mache es öffentlich, damit andere Skripte es aufrufen können Diese Funktion setzt die Richtung zur Oberfläche zurück Vektor 20 und die Drehung auf Null, sie wieder in einen Verhaltenszustand versetzt werden, der genau wie bei jedem anderen Feind ist In unserer kriechenden Physik fehlt jedoch immer noch eine Sache , nämlich dem Feind zu sagen, dass er in die Richtung schauen soll , in die er sich bewegt, da das im Prozess der Superklassenphysik gemacht wurde der Superklassenphysik Anstatt den gleichen Code hier zu kopieren und einzufügen, verschieben wir ihn in eine private Funktion in der Dann können wir diese Funktion sowohl in diesem Zeichenskript als auch im Crawling Enemy-Skript aufrufen sowohl in diesem Zeichenskript als auch im Crawling Enemy-Skript auch im Crawling Enemy-Skript Anstatt einen separaten Knoten und ein separates Skript zu erstellen , um diesem Feind einfach mitzuteilen, dass er kriechen soll, exportiere ich eine Integer-Variable für die Krall-Richtung Dann überschreiben Sie die Prozessfunktion und machen Sie es hier. Zu Testzwecken überschreibe ich auch die Eingabefunktion, überschreibe ich auch die Eingabefunktion sie mit dem Abwärtspfeil gezwungen werden, sich von der Oberfläche zu lösen, auf der sie kriechen Wenn wir das Spiel ausführen, kriecht die Schnecke um diese Kiste herum und dreht sich sowohl an den konkaven als auch an den konvexen Ecken, dreht sich sowohl an den konkaven als auch an den konvexen um an die Wände zu klettern und wieder an der Decke den Abwärtspfeil drücken , lösen sie sich von der Oberfläche und fallen der Schwerkraft zu Wir haben jetzt unseren letzten Feindtyp, einen, der an Wänden und Decken kriechen kann Aber unsere Feinde sollten aggressiver gegenüber dem Spielercharakter Wir sehen uns im nächsten Video. 55. 7-6 Sehkraft: Hallo Freunde. In diesem Video geben wir einigen unserer Feinde die Möglichkeit, die Präsenz des wahrzunehmen und darauf zu reagieren Spielercharakters wahrzunehmen und darauf zu reagieren. In der Szene mit dem Rauminhalt entferne ich die Schnecken und die Kiste mit dem Gelände Ersetze es durch einen Block auf zwei Seiten füge dann eine Mausnotiz ein , die zwischen ihnen hin und her wechselt. Ich füge den Timer-Knoten hinzu, hänge das Pace-Skript an und setze dessen One-Shot-Eigenschaft auf true. Damit dieser Feind aggressiv auf den Spielercharakter reagieren kann, muss er ihn aufspüren können. Um dies zu erreichen, müssen wir mehrere Tools verwenden. Zuerst fügen wir unserem Feind einen D-Node der zweiten Zone hinzu. Und einen Kollisionsformknoten für das Gebiet. Dieser Bereich repräsentiert den gesamten Sichtbereich des Feindes. Vielleicht möchtest du ein um 45 Grad gedrehtes Quadrat, eine Kapsel oder einen Kreis verwenden 45 Grad gedrehtes Quadrat, eine . Wenn Sie ein Kollisionspolygon mit zwei D-Knoten anstelle eines Kollisionspolygons mit zwei D-Knoten verwenden , können Sie tatsächlich ein benutzerdefiniertes Polygon erstellen, anstatt voreingestellte Formen können Sie tatsächlich ein benutzerdefiniertes Polygon erstellen zu verwenden Klicken Sie einfach in den Editor, um jeden Scheitelpunkt der gewünschten Form zu zeichnen Auf diese Weise können wir ein Dreieck oder einen Fächer erstellen, wodurch ein Sichtfeld besser dargestellt wird die Polygoneigenschaft im Inspektor erweitern, können wir die Positionen der einzelnen Scheitelpunkte sehen, sie bearbeiten und bei Bedarf neu anordnen. Für welche Form Sie sich auch entscheiden, achten Sie darauf, dass Ihre Form nur konvexe Winkel hat Wenn Ihr Polygon konkav ist, teilt Godot es in mehrere kleinere konvexe Formen auf und verdoppelt dadurch die Kosten für Kollisionsberechnungen Wenn Sie sich jedoch für eine normale symmetrische Kollisionsform entscheiden , ist es viel einfacher, den Feind nach links und rechts umzudrehen , da Sie einfach dieselbe Methode verwenden können, die wir beim Kantendetektor-Cast verwendet haben, und seine Positionseigenschaft jedes Mal einstellen, wenn der seine Positionseigenschaft jedes Mal einstellen jedes Mal Beim Kollisionspolygon mit zwei D-Knoten ist der Vorgang jedoch etwas komplizierter Wir können seine Position nicht einfach verschieben, und wir sollten auch seine Skalierungseigenschaft nicht ändern Wenn wir die Dokumentation für diesen Knoten öffnen, ausdrücklich davor gewarnt angegeben, dass er sich wahrscheinlich nicht wie erwartet verhalten wird. Wenn wir uns dafür entscheiden, diese Kollisionspolygone für unsymmetrische Formen zu verwenden diese Kollisionspolygone für , die wir umdrehen müssen, müssen wir die Positionen der einzelnen Scheitelpunkte in unserem Skript manuell bearbeiten die Positionen der einzelnen Scheitelpunkte in Das Sichtfeld allein wird jedoch nicht ausreichen, da nichts es daran hindert, Wände zu durchdringen Wenn wir wollen, dass der Feind den Spieler mit ungehinderter Sichtlinie entdeckt , benötigen wir einen weiteren Knoten, um zu überprüfen , ob ein Strahl zwei D-Knoten wirft Du solltest ihn in der Nähe der Augen des Feindes positionieren, von wo aus er eigentlich zuschauen Augen des Feindes positionieren, von wo würde, aber ihn horizontal zentriert halten Ich benenne das in Sichtlinie um. Die Sichtlinie wird sowohl mit dem Gelände als auch mit dem Körper des Spielercharakters kollidieren , die beide Körper sind Dadurch kann das Gelände ihre Sichtlinie blockieren, selbst wenn sich der Spielercharakter in ihrem Sichtfeld befindet Wenn das Sichtfeld ausgewählt ist, benötigen wir es nur zur Überwachung und zum Maskieren des Körpers des Spielers Ich entferne den Formknoten und verwende das Polygon einfach als Kollisionsbereich Dann gib ihm und dem Darsteller eindeutige Namen. ein Skript an den Sichtfeldbereich anhängen, speichern wir es im Ordner Enemy Scripts Lassen Sie uns mithilfe des Ready-Tags Verweise auf die Form oder den Polygonknoten und den Sichtlinienknoten abrufen den Polygonknoten und den Sichtlinienknoten Ready-Tags Verweise auf die Form oder den Polygonknoten und den Sichtlinienknoten Ich wünsche mir von diesem Aufbau, dass der Feind auf den Spielercharakter reagiert, nachdem beide das Sichtfeld betreten haben und der Feind eine direkte Sichtlinie zum Spieler hat Wenn der Spielercharakter beide das Sichtfeld verlässt und die Sichtlinie unterbrochen wird, möchte ich, dass der Feind zu seinem normalen Verhalten zurückkehrt Überlegen Sie, wie wir wollen, dass dieser Knoten über Signale mit anderen Knoten kommuniziert Wir benötigen diesen Knoten , um zwei Dinge zu melden , wenn der Feind ein Ziel erreicht hat und wenn er sein Ziel verloren hat. Das werden genau die Momente sein denen wir ihr Verhalten von ihrem voreingestellten Hin - und Her-Tempo ändern und ihnen stattdessen sagen wollen ihrem voreingestellten Hin - und Her-Tempo ändern und ihnen stattdessen sagen , dass sie aggressiver handeln sollen oder umgekehrt Wir können die Signale, die der Körper betreten hat, und die vom Körper ausgehenden Signale aus dem Sichtfeld mit dem Drehbuch verbinden ausgehenden Signale aus dem Sichtfeld Und das sagt uns ganz einfach , wann der Spielercharakter das Sichtfeld betritt und verlässt Wir müssen das in einer Variablen namens target speichern. Da der Parameter ein D ohne zwei ist, setzen wir den Variablentyp auch auf ein D ohne zwei, um die Dinge einfach zu halten. Wir benötigen außerdem eine boolesche Variable dafür ob der Feind gerade anvisiert oder nicht, ob sich das Ziel gerade im Sichtfeld befindet und ob der Feind derzeit Sichtlinie zum Ziel hat Wenn ein Körper das Sichtfeld betritt, dann setzt man sein Sichtfeld auf true und setzt das Ziel auf Wenn der Körper das Sichtfeld verlässt, können wir ihn wieder auf Falsch setzen. Denken Sie daran, dass wir nur den Spielercharakter maskieren, sodass wir bereits wissen, dass dieser Körper der Spielercharakter ist den physikalischen Prozess außer Kraft setzen, , wenn es noch kein Ziel können wir einfach zurückkehren, wenn es noch kein Ziel gibt, da es nichts zu tun gibt Jetzt können wir davon ausgehen, dass der Spielercharakter das Sichtfeld mindestens einmal betreten hat Als Nächstes richten wir die Sichtlinie auf das Ziel. Wir können einen Vektor erzeugen, der von A nach B zeigt , indem wir A von B subtrahieren Die Zielposition des Raycasts ist also die des Ziels abzüglich unserer globalen Position Dann ist der Wert von ist in Sichtlinie wahr, wenn das, worauf der Collider trifft, mit dem Ziel identisch ist Wenn der Strahl auf Gelände trifft oder gar nichts trifft, ist das falsch Beachten Sie, dass Kollisionen bereits von Godot berechnet wurden, wenn der physikalische Prozess stattfindet Kollisionen bereits von Godot berechnet wurden Wenn wir also die Sichtlinie auf den Spielercharakter in der obigen Zeile richten, die resultierenden Kollisionsdaten erst im nächsten Frame verfügbar Was wir hier überprüfen, sind die Kollisionsergebnisse aus dem vorherigen Frame. Wenn Sie aus irgendeinem Grund unbedingt sofortige Aktualisierung eines Casts benötigen, können Sie dessen Force-Funktion RycastuDate aufrufen das Spiel jedoch mit 60 Bildern pro Sekunde läuft, wird die Verzögerung nicht spürbar sein und das Spiel wird so wie es ist einwandfrei funktionieren Jetzt müssen wir nur noch unsere Signale zur richtigen Zeit aussenden . Wenn der Feind gerade nicht anvisiert, sich das Ziel aber in seinem Sichtfeld befindet und er Sichtlinie zum Ziel hat, dann wurde das Ziel erfasst. Also setzen wir die Zielerfassung auf Wahr“ und senden das empfangene Zielsignal aus, wobei wir das Ziel als Argument weitergeben. Und im völlig gegenteiligen Szenario, wenn sie gerade zielen, aber das Ziel nicht in ihrem Sichtfeld ist und sie keine Sichtlinie haben, dann haben wir das Ziel verloren. In diesem Fall wäre es auch eine gute Idee, den Wert von Target wieder auf Null zu setzen, wodurch der physikalische Prozess daran gehindert wird, weitere Überprüfungen vorzunehmen, bis sie wieder in das Sichtfeld gelangen. Lassen Sie uns auch ausdrucken, wann diese Ereignisse eintreten, damit wir sie testen können. Das Letzte, was wir tun müssen, ist unser Kollisionspolygon umzudrehen , wenn der Feind die Richtung ändert. Das können wir tun, indem wir das geänderte Richtungssignal mit unserem Skript verbinden das geänderte Richtungssignal mit unserem Skript Wenn du eine symmetrische Form verwendest, musst du sie nur auf der anderen Seite des Charakters neu positionieren sie nur auf der anderen Seite des Charakters Aber ich verwende ein Polygon, was bedeutet, dass ich die einzelnen Scheitelpunkte bearbeiten muss Ich beginne damit, das bestehende Array aus dem Polygon abzurufen und es in einer Variablen zu speichern Der Typ ist ein gepacktes Vektor-Zwei-Array. Ich kann dann durch jeden der Scheitelpunkte iterieren und dieselbe Strategie anwenden , um ihre Exposition auf die andere Seite des Charakters umzukehren , wenn sie nach links zeigen Die Anordnung der Scheitelpunkte, die das Polygon hier bietet , ist nur eine Kopie, nicht Wenn wir die Werte bearbeiten, hat das also keine Auswirkungen auf das Kollisionspolygon Damit die Änderungen tatsächlich funktionieren, müssen wir das bestehende Array mit der bearbeiteten Kopie überschreiben das bestehende Array mit der bearbeiteten Lassen Sie uns sichtbare Kollisionsformen im Debug-Menü einschalten und es ausprobieren Wir können sehen, wie unser Feind zwischen den beiden Wänden hin und her läuft, und das Kollisionspolygon dreht sich um, wenn er sich umdreht beiden Wänden hin und her läuft, und das Kollisionspolygon dreht sich um, wenn er sich umdreht Beim Betreten des Sichtfeldes beginnt der Strahlwurfknoten, unsere Position zu verfolgen, aber der Feind hat noch nichts gesehen, da seine Sichtlinie durch das Gelände blockiert ist Wenn wir nach oben springen, wird die Sichtlinie nicht mehr behindert und wir erhalten die Nachricht, die das Ziel erfasst hat, ausgegeben wir das Sichtfeld und auch die Sichtlinie des Feindes verlassen , erscheint die Nachricht „Ziel verloren“ und der Wurf verfolgt unsere Position nicht mehr Unser Feind ist jetzt in der Lage, die Anwesenheit des Spielercharakters zu erkennen, aber er muss immer noch darauf reagieren Wir sehen uns im nächsten Video. 56. 7-7 Aggression: Hallo Freunde. In diesem Video werden wir den Feind den Spieler verfolgen und angreifen lassen. Beginnend mit der feindlichen Szene müssen wir einen Angriff für diesen Feind hinzufügen. die Animation im Leerlauf dupliziere, erstelle ich schnell Keyframes für die Angriffsanimation des Feindes Diese Angriffsanimation vermittelt nicht wirklich wie viel von einem Gebiet der Angriff treffen wird Sie zeigt nur die Bewegung des Feindes selbst. Dafür brauchen wir ein separates Sprite. Ich erstelle einen neuen Sprite-Ordner für Effekt-Sprites und importiere ein Spritesheet für den Angriffseffekt dieses Feindes Wir fügen ein animiertes Sprite hinzu, als untergeordnetes Element des Sprites des Feindes angezeigt wird. Es wird also automatisch horizontal umgedreht, wenn sich der Feind umdreht horizontal Erstellen Sie dann eine neue Sprite-Frames-Ressource und fügen Sie die Sprites aus dem Sprite-Sheet Wie immer füge ich am Ende der Animation ein leeres Sprite hinzu, setze dessen Bildrate auf 12 Bilder pro Sekunde Ich füge diese Animation dem ersten Sprite hinzu, die Größe und Form des Angriffs genau wiedergibt Dann positioniere es vor dem Feind. Dies macht es viel einfacher, diesem Angriff eine Trefferbox hinzuzufügen. Lassen Sie uns also die bestehende Hitbox duplizieren. Ich benenne die ursprüngliche Hitbox in Contact Damage um und belasse diese neue Hitbox als Hitbox. Jetzt können wir diese Trefferbox so gestalten, dass Kollisionsform dem Angriffseffekt entspricht. Im Gegensatz zum animierten Sprite sollten wir den Trick mit der negativen Skalierung nicht verwenden , um unsere Trefferbox umzudrehen Also müssen wir das geänderte Richtungssignal des Feindes mit dem Hitbox-Skript verbinden geänderte Richtungssignal des Feindes mit dem Hitbox-Skript und es manuell neu Wie schon zuvor nehmen wir nur einen Verweis auf die Kollisionsform Und setzen Sie ihre Position auf ihren Absolutwert, multipliziert mit minus Eins, wenn die Richtung kleiner als Null ist , oder auf positive Eins, andernfalls Im Standardstatus dieses Feindes wird er nicht angreifen, daher ist diese Trefferbox nicht aktiv Lassen Sie uns also seine Überwachungsfunktion und Sichtbarkeit ausschalten. Wechseln Sie dann zurück zur Angriffsanimation wo wir diese Eigenschaften per Keyframe einschalten können , um sie während der Angriffsanimation ein - und wieder auszuschalten. Dadurch werden auch beide mit ihren Standardwerten zum Reset-Track hinzugefügt . Und wir können den Angriffseffekt auch so einstellen, dass er gleichzeitig abgespielt wird. In der Rauminhaltsszene haben wir derzeit das normale Verhalten dieses Feindes, das hin und her läuft, und dem Feind die Möglichkeit, den Spielercharakter zu sehen Wenn dieser Knoten das vom Ziel erfasste Signal aussendet, sollten wir das Verhalten des Feindes von Tempo zu aggressiver ändern Verhalten des Feindes von Tempo zu Und wenn sie ihr Ziel aus den Augen verlieren, sollten sie ihr ursprüngliches Tempo wieder aufnehmen Aber wir wollen vielleicht nicht unbedingt, dass dies für alle Gegner oder andere Charaktere gilt alle Gegner oder andere Charaktere , die das Temposkript verwenden Deshalb sollten wir einen separaten Knoten für aggressives Verhalten einrichten. Ich werde einen anderen Timer-Knoten verwenden und ihn Aggression nennen. Hängen Sie dann ein Skript an diesen Knoten und speichern Sie es im feindlichen Skriptordner. Genau wie beim Pace-Skript benötigen wir einen Verweis auf den Feind, den dieses Script mithilfe des Ready-Tags kontrolliert. Wir müssen auch einen Verweis auf das Ziel in einer Variablen speichern , gegen das sich dieser Feind aggressiv verhält. Außerdem müssen wir die Richtung zum Ziel als Vektor zwei sowie die Entfernung zum Ziel als Float kennen die Richtung zum Ziel als Vektor zwei . der Feind diese Werte kennt, kann er sich seinem Ziel nähern, um in Angriffsreichweite zu gelangen , bevor er angreift. Wir müssen aber auch die Angriffsreichweite dieses Feindes als exportierte Variable angeben Angriffsreichweite dieses Feindes als , was ein Float wäre. Wenn du möchtest, kannst du auch eine minimale Angriffsreichweite angeben . Wenn wir den Typ der Angriffsreichweite auf einen Vektor zwei ändern , können wir den X-Wert als Mindestbereich und den Y-Wert als Maximalbereich verwenden . Ich stelle den Standardwert so ein , dass er mindestens 32 Pixel vom Player und maximal 64 Pixel entfernt ist. Wenn der Feind also mehr als 64 Pixel vom Spielercharakter entfernt ist , möchte ich, dass der Feind auf ihn zuläuft. Oder wenn der Feind weniger als 32 Pixel vom Spielercharakter entfernt ist , möchte ich, dass der Feind vor ihm wegläuft. Aber innerhalb dieser Reichweite wird der Feind angreifen. Indem wir die Prozessfunktion außer Kraft setzen, können wir Delta ignorieren, und wenn es kein Ziel für diesen Feind gibt, können wir zurückkehren Das sollte nicht passieren, aber es ist nie eine schlechte Idee, einen Failsafe zu haben Wir können die Richtung zum Ziel berechnen , indem wir die Position unseres Feindes von der Position des Ziels subtrahieren und dann die Entfernung ermitteln , indem wir denselben Vektor nehmen und seine Länge berechnen Wenn die Entfernung zum Ziel größer ist als unsere maximale Angriffsreichweite, sollte sich dieser Feind auf das Ziel zubewegen und seine Bewegungsrichtung auf das Richtungszeichen zum Zielpunkt X einstellen zubewegen und seine Bewegungsrichtung auf das Richtungszeichen . Wenn die Entfernung zum Ziel geringer ist als unsere minimale Angriffsreichweite, sollte sich dieser Feind vom Ziel entfernen genau das Gegenteil tun. Wenn beide Bedingungen falsch waren, befindet sich das Ziel in Angriffsreichweite. Der Feind sollte sich also auf einen Angriff vorbereiten. Ich sorge dafür, dass der Feind aufhört sich zu bewegen, indem ich seine Bewegungsrichtung auf Null setze und auch auf das Ziel zuschaue, falls er es noch nicht getan hat. Ich möchte nicht, dass der Feind sofort angreift, da meine Angriffsanimation sehr kurz ist und nicht telegraphiert Also starte ich den Timer hier und warte, bis er abgelaufen ist, bevor ich angreife Die One-Shot-Eigenschaft dieses Timers sollte auf true gesetzt werden, damit der Countdown nur einmal erfolgt. Bei der Eigenschaft Wartezeit handelt es sich um die Zeit, während der sich der Feind innerhalb der Angriffsreichweite befindet, bevor er angreift. das Timeout-Signal mit dem Skript verbinde, Wenn ich das Timeout-Signal mit dem Skript verbinde, sage ich meinem Feind, dass er angreifen soll Es ist auch eine gute Idee, erneut auf das Ziel zuzuschauen falls sich seit dem Start des Timers etwas geändert hat seit dem Start des Timers Ich möchte den Timer nur starten , wenn er gerade gestoppt ist. Ich werde den Timer auch jedes Mal stoppen , wenn sich das Ziel außerhalb der Angriffsreichweite befindet. Das sollte für unser Verhalten ausreichend sein. Jetzt müssen wir nur noch zu den entsprechenden Zeiten zwischen unseren beiden Verhaltensskripten hin und her wechseln . Wir möchten nicht, dass unser Aggressionsskript aktiv ist, wenn der Feind zum ersten Mal erscheint, also setzen wir seinen Prozessmodus auf Deaktiviert das Sichtfeld im Szenenbaum auswählen, verbinden wir das vom Ziel erfasste Signal mit dem Aggressionsskript und können diese Funktion umbenennen, wenn wir möchten Um die Konsistenz zwischen meinen verschiedenen Verhaltensskripten zu gewährleisten , nenne ich sie Zoom. Diese Funktion legt den Wert des Ziels fest, ändert den Prozessmodus auf „Vererben“ und weist den Feind an, zu rennen, wodurch er und weist den Feind an, zu rennen, anfängt, aggressiv gegen das Aber wir müssen auch das Temposkript pausieren. Also werden wir dasselbe Signal auch mit dem Tempoknoten verbinden. Und dieses Mal rufen wir eine Funktion namens Pause auf, aber dieses Signal liefert ein Argument, und wir brauchen es nicht, um dieses Verhalten zu unterbrechen. Wir können uns auch ein Szenario vorstellen in dem wir dieses Verhalten unter anderen Umständen pausieren möchten und kein willkürliches und unnötiges Argument angeben wollen willkürliches und unnötiges Argument um die Pause-Funktion aufzurufen. Wir werden also das vom Signal bereitgestellte Argument aufheben, sodass die verbundene Funktion keine Argumente hat Hier müssen wir nur den Prozessmodus auf Deaktiviert setzen Prozessmodus auf Deaktiviert setzen Wenn der Feind ein Ziel sieht, unterbricht er sein Tempo und setzt sein aggressives Verhalten fort Wenn sie also ihr Ziel verlieren, können wir das Gegenteil tun, das Signal mit den Skripten verbinden und die entgegengesetzten Funktionen aufrufen Stellen Sie ihren Prozessmodus auf Vererben ein, um sie zu aktivieren, oder auf Deaktiviert, um sie zu deaktivieren. Wenn wir das Tempoverhalten aktivieren, wollen wir dem Gegner auch sagen, dass er gehen soll Jetzt müssen wir im Charakterskript die Angriffsanimation auslösen, wenn wir dem Feind sagen, dass er angreifen soll Dazu benötigen wir einen Verweis auf Wiedergabe der Animations-Tree-Statusmaschine. Dies führt jedoch zu einem Fehler im Charakterskript des Spielers, wenn wir eine andere Variable mit demselben Namen haben, da der Spielercharakter vom Charakter erbt Es würde also eine Animationsvariable vom Charakter übernommen wird, aber auch eine andere, die im Spielercharakter deklariert ist, was nicht erlaubt ist, aber wir verwenden sie für den gleichen Zweck, also können wir diese Variable einfach aus dem Zeichenskript des Spielers entfernen diese Variable einfach aus dem Zeichenskript des Spielers Zurück im Charakterskript, als wir aufgefordert werden, anzugreifen, müssen wir dieser Wiedergabe nur sagen sie zur Angriffsanimation wechselt. Im Animationsbaum fügen wir die Angriffsanimation hinzu und wechseln von Inaktiv mit aktiviertem Advance zu ihr Inaktiv mit aktiviertem Advance und kehren am Ende der Animation in den Leerlauf zurück. Wenn Sie nicht möchten, dass sich der Feind beim Angriff bewegen oder die Richtung ändern kann , können wir Schnellprüfungen hinzufügen, um zu überprüfen, ob der aktuelle Knoten der Animationswiedergabe Angriff ist. Und entweder die Bewegungsrichtung auf Null setzen oder die Funktion komplett verlassen. Wenn wir jetzt das Spiel starten der Feind uns sowohl in seinem Sichtfeld als auch in seiner Sichtlinie hat und der Feind uns sowohl in seinem Sichtfeld als auch in seiner Sichtlinie hat, ändert sein Verhalten von Tempo zu aggressiver Sie werden uns hinterherjagen und nach einer kurzen Pause angreifen. Wir haben jetzt einen viel aggressiveren Feind mit dem sich unser Spielercharakter auseinandersetzen muss, aber unser Spielercharakter kann sich nicht wirklich wehren Wir sehen uns im nächsten Abschnitt. 57. 8-1 Kombi-Gruppe: Hallo Freunde. In diesem Video geben wir den Spielercharakteren eigene Angriffe , damit sie sich gegen unsere Feinde wehren können. Wir haben den Mausritter bereits angegriffen, und der Prozess wird sehr ähnlich sein. Unser Spielercharakter hat jedoch zwei verschiedene Angriffe. Wir können einige der Knoten aus der Mausnachtszene kopieren , um etwas Zeit zu sparen, die Hitbox und den Animated Sprite Two D-Knoten Wenn wir zur Charakterszene wechseln, können wir diese Knoten in die Szene einfügen sie dann nach Bedarf neu organisieren Der Knoten Animated Sprite Two D kann unter dem Sprite des Charakters angeordnet werden, sodass er automatisch umgedreht wird, je nachdem welche Richtung der Charakter blickt Ich benenne ihn um, um einen Angriffseffekt zu erzielen. Ich weiß, welcher spezielle animierte Sprite das ist. Die Hit-Box werde ich als Geschwister generell neben der Hurt-Box sortieren Damit die Trefferbox der Spielercharaktere der gegnerischen Hurt-Box Schaden zufügt, müssen wir sicherstellen, dass die Kollisionsebenen und Masken entsprechend eingestellt sind Da sich mein Spielercharakter auf Kollisionsebene neun und seine Verletzungsbox auf Kollisionsebene zehn befindet, habe ich meine Gegner dann auf Kollisionsebene 17 und ihre Verletzungsboxen auf Kollisionsebene 18. Wenn ich die Projekteinstellungen öffne, füge ich die gegnerische Hurt-Box als Ebene 18 zu meinen beiden D-Physik-Ebenennamen hinzu. Denke dann daran, alle meine vorhandenen feindlichen Szenen so zu bearbeiten , dass auch ihre Hurt-Boxen auf dieser Ebene platziert werden. Das Trefferfeld der Spielercharaktere kann dann so eingestellt werden, Ebene 18 maskiert, um ihnen Schaden zuzufügen. Um das Trefferfeld umzudrehen, müssen wir das Signal in dieser Szene erneut verbinden, da diese Signalverbindung nicht von der anderen Szene übernommen wurde Aber die Funktion, die wir zuvor im Hit-Box-Skript geschrieben haben und mit der wir dieses Signal verbinden wollen, ist nach Feind benannt, der die Richtung geändert hat Das spielt keine Rolle, aber wenn du konsistent sein willst , wie du Dinge in deinem Spiel benennst, solltest du diesen Funktionsnamen vielleicht in „Ein Charakter hat die Richtung geändert“ ändern . Dadurch wird dem Skript eine weitere Funktion hinzugefügt, und wir können den Code einfach zu dieser neuen Funktion verschieben und die alte löschen, da sie einfach dasselbe tut. Jetzt müssen wir jedoch in die feindliche Szene gehen und deren Signalverbindung bearbeiten , um eine Verbindung zur neuen Funktion herzustellen. Je früher Sie in Ihrem Projekt diese Probleme identifizieren können, desto weniger Zeit und Mühe müssen Sie später für das Refactoring aufwenden Zurück in der Spielercharakterszene wählen wir den Animation Player-Knoten aus der Szenenhierarchie aus und fügen eine neue Wir nennen diesen Angriff eins, da es zwei verschiedene Angriffsanimationen gibt zwei verschiedene Angriffsanimationen und wir sie unterscheiden müssen. Nach dem Hinzufügen der Sprite-Frames des Charakters. Ich kopiere die Keyframes für die Kleidung des Charakters in die anderen Tracks Wir können auch die Überwachungsfunktion der Hitbox einschalten. Und die Sichtbarkeit auch, wenn Sie möchten, dass sie im Debug-Modus ein- und ausgeschaltet Wenn man sich den Angriffseffekt anschaut, dieser nicht mit der Angriffsanimation überein Also importiere ich die richtigen Effekt-Sprites für diesen Angriff. Fügen Sie dann der Sprite-Frames-Ressource eine neue Animation hinzu. Ich nenne es Attack One, schalte Looping aus, stelle die Bildrate und füge am Ende ein leeres Bild Jetzt kann die Angriffsanimation den Angriffseffekt und den Animated Sprite Two D Node anweisen, den Attack-One-Effekt abzuspielen Der Keyframe-Funktionsaufruf ist einfach abspielen, was gut funktioniert hat, solange unser Animated Sprite Two-D-Knoten nur eine Animation zum Abspielen hat Aber jetzt haben wir zwei verschiedene Animationen, und wir müssen angeben , welche wir abspielen möchten auf den Keyframe klicken, können wir ihn im Inspektor bearbeiten den Abschnitt mit den Argumenten erweitern, können wir sehen, dass die Play-Funktion tatsächlich drei Argumente hat, die alle optional sind Wir befassen uns nur mit dem ersten Argument, dem Namen der Animation, wir in das Textfeld eingeben können. Falls Sie neugierig sind, die anderen Argumente beziehen sich auf die Anpassung der Animationsgeschwindigkeit oder die Rückwärtswiedergabe der Animation Die Schreibweise muss exakt mit dem Namen der Animation Ich benenne die Standardanimation Attack Two um, damit sie dem entspricht, was ich in die Animation eingefügt habe. die Angriffsanimation duplizieren, können wir auch eine Animation für Angriff zwei erstellen Nachdem ich die Sprite-Frames des Charakters geändert habe, kopiere ich die Keyframes in die anderen Ändern Sie dann das Argument , das an den Angriffseffekt übergeben wird , so, dass Angriff zwei statt Angriff eins gespielt Angriff zwei statt Angriff eins Wenn wir den Animationsbaumknoten auswählen, können wir die erste Attacke hinzufügen und zwei Animationen angreifen. auswählen den Animationsbaumknoten auswählen, können wir die erste Attacke hinzufügen und zwei Animationen angreifen. Fügen Sie dann einen Übergang von Bewegung zu Angriff eins und dann von Angriff eins zu Angriff zwei hinzu. Bei beiden wird der erweiterte Modus aktiviert sein, was bedeutet, dass wir diese Übergänge von unserem Skript aus auslösen werden . Wenn Übergänge hinzugefügt werden, sodass eine der Angriffsanimationen wieder zur Bewegung zurückkehrt, werden ihre Wechselmodi auf „Ende“ gesetzt. Beim Übergang von Angriff eins zu Angriff zwei wird der Wechselmodus ebenfalls auf „Ende“ gesetzt. diese Weise können wir zu Angriff eins übergehen , wenn die Angriffstaste gedrückt wird, und dann von Angriff eins zu Angriff zwei, wenn die Angriffstaste während der ersten Angriffsanimation ein zweites Mal gedrückt wurde . Um unserem Spiel einen Angriffsknopf hinzuzufügen, müssen wir in den Projekteinstellungen der Eingabekarte ein neues Eingabeereignis für Angriffe hinzufügen. Ich verwende die X-Taste auf der Tastatur und die linke Taste auf meinem Controller, was auch X ist. Dann können wir im Spielerskript ein weiteres Ich blockiere für Angriffe hinzufügen, die Eingabe genauso zwischengespeichert wird, wie wir es bei jeder anderen Aktion getan haben Da die Taste, mit der der erste Angriff und der zweite Angriff ausgelöst werden, identisch ist, sollte sich das Spielerskript nur darauf konzentrieren dem Charakter mitzuteilen, dass er angreifen soll, und nicht, welchen spezifischen Angriff er ausführen soll Im Spielercharakter-Skript können wir diese Angriffsfunktion hinzufügen, wie jede andere gepufferte Eingabe einen booleschen Wert zurückgibt Dies wird nicht gesperrt und ist im Gegensatz zur Cast-Funktion kostenlos im Gegensatz zur Wenn sich die Animationswiedergabe des Charakters gerade im Bewegungsmodus befindet, erlaube ich ihm, anzugreifen. Wenn das gelingt, können wir die Animationswiedergabe so einstellen, dass sie eine Animation zum Angriff zurückfährt und „ true“ zurückgibt oder „false“ zurückgibt wenn die Figur mit etwas anderem beschäftigt war. Es liegt ein Fehler vor, weil die Angriffsfunktion die Angriffsfunktion der Charakterklasse überschreibt, die Signatur aber nicht übereinstimmt Das bedeutet, dass entweder die Parameter oder der Rückgabetyp unterschiedlich sind, was nicht zulässig ist oder Befehlstaste gedrückt halten - oder Befehlstaste gedrückt halten und auf die Funktion klicken, gelangen wir zur Oberklassendefinition dieser Funktion wo wir sehen können, dass sie void und keinen booleschen Wert zurückgibt Um diese Vererbungsstruktur bei unseren Feinden und unserem Spielercharakter nutzen zu können und gleichzeitig gepufferte Eingaben zuzulassen, müssen wir dafür sorgen, dass die Superklassen-Angriffsfunktion auch einen booleschen Wert zurückgibt. diese Anforderung zu erfüllen, geben wir einfach true zurück und kehren zum Spielercharakter-Skript zurück, der der Aber was ist mit dem zweiten Angriff? Wir können einen Else-if-Block hinzufügen und prüfen, ob die Animationswiedergabe gerade in der Attack One Animation enthalten ist . Sagen Sie ihm dann, dass er stattdessen zur Animation „Angriff zwei“ reisen soll . Lassen Sie uns die sichtbaren Kollisionsformen im Debug-Menü aktivieren, dann auf Abspielen klicken und es ausprobieren Durch Drücken der Angriffstaste spielt unser Charakter den Angriff One Animation ab Das Trefferfeld ist aktiviert und die Effektanimation wird abgespielt. erneutes Drücken der Angriffstaste während des ersten Angriffs wird auch der zweite Angriff abgespielt. zurück zum Editor wechseln, können wir den Remote-Baum öffnen um zu sehen, wie unser aktuelles Spiel läuft. Wenn wir den Szenenbaum durchforsten, bis wir die Nacht der Maus gefunden haben, können wir ihre Hurt-Box auswählen und uns ihre Eigenschaften im Inspektor ansehen, einschließlich ihrer aktuellen Gesundheit. Zurück im Spiel können wir unseren Feind angreifen und zusehen, wie jeder Angriff ihn um eine Lebenspunkte trifft , bis er Null erreicht. Komm schon. Wir haben jetzt unseren Charakter in der Lage, Feinde anzugreifen, aber unsere Charaktere und Feinde reagieren nicht darauf, getroffen zu werden. Wir sehen uns im nächsten Video. 58. 8:2 Treffer: Hallo Freunde. In diesem Video werden wir unsere Charaktere dazu bringen, auf Angriffe zu reagieren. beginnen in der Spielercharakterszene wählen den Animations-Player-Knoten Danach müssen wir eine neue Animation für Treffer hinzufügen. Um die Sache zu vereinfachen, dupliziere ich die Dash-Animation , um die Trefferanimation zu erstellen. Nachdem ich die Sprite-Keyframes aktualisiert habe, kopiere ich sie und füge sie in die anderen Tracks ein, um auch die Kleidung des Charakters zu animieren Da ich die Dash-Animation dupliziert habe, enthält diese Trefferanimation jetzt auch Das ist sehr hilfreich, um zu verhindern, dass Charaktere erleiden schnell hintereinander Schaden durch mehrere Trefferboxen . Das fühlt sich dem Spieler gegenüber oft unfair an und führt auch dazu, dass der Charakter wiederholt Schaden durch anhaltende Trefferboxen erleidet, wie zum Beispiel Umweltgefahren, weil eine neue Kollision ausgelöst wird, wenn die Hurt-Box am Ende des Animation, wenn sich die Hurt-Box immer noch mit der Hit-Box überschneidet Wir haben auch die Methode Track, die die Funktion End Dash aufruft , die, wie Sie sich erinnern, aufgrund der Art und Weise, wie sie im vorherigen Abschnitt implementiert wurde, aufgerufen werden muss, wenn der Strich unterbrochen wurde Es wäre eine gute Idee, diesen Funktionsaufruf an den Anfang der Trefferanimation zu verschieben . Schauen wir uns diese Funktion im Player-Charakterskript an. Je nachdem, in welchen Frames du die Hurt-Box ein- oder ausschaltest, kann es sein, dass der Charakter getroffen wird, während die Sprint-Animation abgespielt wird wodurch die Sprint-Animation unterbrochen bedeutet, dass die Funktion „Strich beenden“ niemals aufgerufen würde, die Schwerkraft des Charakters niemals zurückgesetzt wird und die Abklingzeit für den Dash nie gestartet Das ist natürlich problematisch, aber wir können es leicht beheben Alles, was wir wirklich tun müssen, ist nachzuverfolgen, wann der Charakter mit einer booleschen Variablen stricht Wenn der Gedankenstrich beginnt, setzen wir ihn auf true. Wenn dann die Funktion „Bindestrich beenden“ aufgerufen wird, prüfen wir zuerst, ob der Charakter stricht, und wenn ja, machen wir alle die gleichen Dinge Danach wird der Wert für „Dash“ auf „False“ gesetzt. Jetzt können wir diese Funktion jederzeit aufrufen unabhängig davon , ob das Zeichen gerade schneidet oder nicht Wenn der Charakter nicht sprintet, die Funktion einfach nichts Wenn ich den Animationsbaumknoten auswähle und mir die Zustandsmaschine ansehe, möchte ich, dass die Trefferanimation jede dieser vorhandenen Aktionsanimationen sowie alle Spring- oder Bewegungsanimationen unterbrechen kann jede dieser vorhandenen Aktionsanimationen sowie alle Spring- oder Bewegungsanimationen unterbrechen sowie alle Spring- oder Bewegungsanimationen Daher wäre es eine gute Idee, eine andere Zustandsmaschine zu verwenden Also werde ich diese Zustandsmaschine wie bei den vorherigen speichern . Ich nenne es Aktionen und speichere es zusammen mit den anderen im Ordner meines Charakters. Ersetzen Sie dann diese Zustandsmaschine durch eine neue und laden Sie die Zustandsmaschine der Aktionen als Knoten. Okay. Sie können dann die Trefferanimation zu dieser Zustandsmaschine hinzufügen. Wenn Sie einen Übergang vom Start zu den Aktionen hinzufügen , wird dieser zum Standardstatus. Dann erfolgt ein Übergang von Aktionen zu Treffer, wobei der erweiterte Modus auf aktiviert gesetzt ist, und ein weiterer Übergang vom Zurückschlagen zu Aktionen, bei denen der Wechselmodus auf „Ende“ gesetzt ist. Auf diese Weise können wir die Animation von einem beliebigen Status aus auslösen , sofort abspielen und dann zu unseren anderen Zuständen zurückkehren. im Zeichenskript möchte, Da ich im Zeichenskript möchte, dass dies für alle Charaktere gilt, nicht nur für meinen Spielercharakter, müssen wir eine neue Variable erstellen, um die Wiedergabe für diese neue Zustandsmaschine zu speichern. Wir können die bestehende Variable duplizieren und sie in etwas wie Hurt-Animationen umbenennen. Der Pfad zu dieser Wiedergabeeigenschaft ist der Parameter Playback, da es sich dabei um das Stammverzeichnis des Animationsbaums handelt. Wenn wir den Animationsbaum im Szenenbaum auswählen und seinen Parameterbereich erweitern, können wir die Playbacks für jeden unserer Zustandsmaschinen sehen Der Eigenschaftspfad für die Wiedergabe von Action-State-Maschinen hat sich also geändert, und wir müssen ihn aktualisieren Um die Verwendung dieser Wiedergabe im Zusammenhang mit den Hurt-Animationen besser zu verdeutlichen , werde ich diese Playback-Action-Animationen nennen. Verwenden Sie dann die Ersetzungsfunktion, um alle Instanzen dieser Variablen mit ihrem neuen Namen zu ändern . Da das Spielercharakterskript diese Variable erbt, muss ich auch in diesem Skript alle Instanzen des alten Namens durch den neuen Namen ersetzen des alten Namens durch den neuen Namen in diesem Skript Das wird für den Spielercharakter funktionieren, aber damit es auch für die Gegner funktioniert, müssen wir auch deren Animationsbaum-Zustandsmaschinen aktualisieren deren Animationsbaum-Zustandsmaschinen damit sie diesem neuen Format entsprechen Ich aktualisiere meine Mausnacht nur , weil der Feind in meinem Startzimmer ist, und der Vorgang wird für jeden Feind derselbe sein . Ich mache die Trefferanimation im Animation-Player-Knoten. Speichern Sie dann den Animation Tree State Machine als Projektressource. Ersetzen Sie ihn durch einen neuen Zustandsmaschine. Fügen Sie die alte Zustandsmaschine als Knoten hinzu, fügen Sie die Trefferanimation hinzu, fügen Sie die Übergänge mit demselben Fortschritt hinzu und wechseln Sie den Modus. Benennen Sie es in Aktionen um, damit dem entspricht, wonach das Skript suchen wird. Jetzt hat dieser Feind dieselbe Animationsstruktur wie der Spielercharakter, sodass die Skripte genauso funktionieren Es gibt zwei separate Playbacks für das Abspielen der Trefferanimation und eine weitere für Aktionen Sobald die Zustandsmaschine eingerichtet ist, kann die gespeicherte Zustandsmaschine gelöscht werden Dadurch wird der Zustandsmaschine für die Szene lokalisiert und nicht mehr zu einer gemeinsam genutzten Ressource für mehrere Szenen. wir nun Zugriff auf die Wiedergabe unserer Zustandsmaschine haben, müssen wir die Animation auslösen. Wir beginnen mit dem Hurt Box-Skript. Wir haben ein Signal, das ausgegeben wird, wenn sich die Gesundheit des Charakters ändert. Dieses Signal verwenden wir, um das HUD-Element zu aktualisieren Dieses Signal wird aber auch ausgegeben, wenn wir die Gesundheit des Charakters zu Beginn initialisieren, sowie immer dann, wenn der Charakter seine Gesundheit wiedererlangen würde Es ist also nicht das beste Signal , um Schaden zu erleiden. Dafür werden wir ein neues Signal ausrufen. Wenn du möchtest, dass der Charakter auf unterschiedliche Mengen oder Arten von Schaden reagiert , kannst du diesem Signal Parameter geben. Ich füge als Faktor zwei einen Parameter für die Richtung hinzu, aus der der Schaden kommt. Aber wir können diese Information nicht von hier bekommen. Wir haben nur Zugriff auf die Hurt-Box und nicht auf die Hitbox , die den Schaden verursacht hat. also zum Hit-Box-Skript wechseln, haben wir hier Zugriff sowohl auf die Hit-Box als auch auf die Hurt Box. Also fügen wir das als weiteres Argument hinzu, das durch die Take Damage-Funktion übergeben wurde. Wir können die Richtung von A nach B berechnen , indem wir A von B subtrahieren dann das Ergebnis normalisieren Bei der Normalisierung ignorieren wir den Abstand zwischen A und B, indem wir die Länge des Vektors auf eins setzen Zurück im Hurt Box-Skript fügen wir den Richtungsparameter Wenn unsere Herd-Box beschädigt wird, senden wir das Signal und geben damit die Richtung weiter. Unser Charakterskript kann jetzt auf dieses Signal reagieren. Ich benenne die verbundene Funktion Einfachheit halber in On Damage Received um. Okay. Zuerst weisen wir Wiedergabe der Hurt-Animation an, in den Trefferstatus zu wechseln. Füge dann dem Körper des Charakters auch eine Kraft hinzu , die in Richtung des Schadens wirkt. Da die Richtung normalisiert ist, wird sie eine Länge von einem Pixel haben Wir können dies mit einer beliebigen Zahl multiplizieren , um zu ändern, wie stark sich die Rückstoßkraft anfühlt. Vielleicht möchtest du das sogar als neue Variable exportieren , sodass es für jedes einzelne Zeichen angepasst werden kann angepasst Wir müssen diese Signalverbindung auch in all unseren Charakterszenen herstellen diese Signalverbindung auch in all unseren Charakterszenen Lass es uns ausprobieren. Mein Charakter kann jetzt den Feind angreifen und der Feind reagiert darauf, sowohl durch das Spielen als auch durch die Animation getroffen zu werden sowohl durch das Spielen als auch durch die Animation und es wird auch eine Rückstoßkraft angewendet Das Gleiche passiert auch mit meinem Charakter, wenn der Feind mich angreift Unsere Charaktere reagieren jetzt auf Schaden, aber unser Kampf fühlt sich nicht besonders saftig Wir sehen uns im nächsten Video. 59. 8-3 Saft: Hallo Freunde. In diesem Video werden wir unserem Kampf einige Partikeleffekte hinzufügen , damit er sich wirkungsvoller anfühlt Beginnend mit unserer Spielercharakter-Szene fügen wir unserer Szene einen neuen Knotentyp hinzu, einen Partikelemitter-Knoten einen Partikelemitter-Knoten Godot hat zwei verschiedene Typen, CPU und GPU. Der CPU-Partikelknoten rendert Partikel auf die gleiche Weise, wie wir die Sprites unserer Charaktere zeichnen Sprites unserer Charaktere zeichnen den Zentralprozessor des Geräts verwenden , der weniger effizient, aber mit älteren Geräten kompatibler ist mit älteren Geräten kompatibler Ein GPU-Partikelknoten delegiert das Zeichnen dieser Partikel vollständig an die Grafikkarte des Geräts, was effizienter ist, aber nur auf modernen Der GPU-Partikelknoten kann eine viel höhere Anzahl von Partikeln verarbeiten viel höhere Anzahl von Partikeln ohne die Leistung zu beeinträchtigen. Ich würde die Verwendung von CPU-Partikeln nur empfehlen wenn Sie Ihr Spiel speziell auf Smartphones oder Tablets ausrichten Ihr Spiel speziell auf Smartphones oder Tablets ausrichten Andernfalls solltest du GPU-Partikel verwenden. unserer Charakterszene einen GPU Particles Two-D-Node hinzufüge, nenne ich ihn einfach Partikel, verschiebe ihn nach oben, sodass er sich in der Mitte des Charakters befindet, und schaue mir seine Eigenschaften im Inspektor an. Bevor ein Partikelemitter etwas zeichnen kann, benötigt er ein Prozessmaterial Dies ist eine Ressource, die dem Emitter mitteilt, wie Partikel erzeugt werden sollen und wie sich die Partikel nach dem Spawnen Partikel erzeugt werden sollen und wie sich die Partikel verhalten sollen Für unser Prozessmaterial gibt es zwei verschiedene Optionen: ein Partikelprozessmaterial oder ein Shadum-Material Das Material für den Partikelprozess wird als Projektressource erstellt , die wir direkt hier im Inspektor bearbeiten können, während ein Shader-Material es uns ermöglicht ein Shader-Skript zu schreiben, um dasselbe zu tun Shader-Skripte sind nicht wie alle unsere bisherigen Skripte in GDScript geschrieben wie alle unsere bisherigen Skripte in GDScript Sie sind in GD-Shader geschrieben, was in diesem Kurs nicht behandelt wird Deshalb werden wir stattdessen eine Materialressource für die Partikelverarbeitung verwenden stattdessen eine Materialressource für die Partikelverarbeitung Klicken Sie auf die Ressource, um ihre Eigenschaften anzuzeigen und zu bearbeiten. Da unser Partikelemitterknoten nun über ein Prozessmaterial verfügt, erzeugt er von seinem Ausgangspunkt aus einzelne weiße Pixel , die aufgrund der Schwerkraft herunterfallen Damit die Partikel besser zu erkennen sind, verstecke ich meinen Charakter Bevor wir uns mit den einzelnen Eigenschaften befassen, hilft es, zuerst die Schwerkraft auszuschalten befindet sich im Bereich Beschleunigung Und da diese Partikel im Kampf zum Aufprall verwendet werden, setze ich ihre Explosivität auf eins Ich habe ein Spritesheet, das ich für meine Partikel verwenden möchte, also importiere ich es in meinen Effektordner und weise es dann meiner Textureigenschaft für Partikelemitter Aber das zeichnet nur das gesamte Spritesheet für jeden Partikel Um ein Partikel zu animieren, müssen wir ihm unter den vom Canvas-Element übernommenen Eigenschaften ein benutzerdefiniertes Material unter den vom Canvas-Element übernommenen Eigenschaften Wir erstellen ein neues Canvas-Objekt als Material aktivieren dann dessen Eigenschaft „ Partikelanimation Jetzt können wir die Anzahl der Animationsframes horizontal und vertikal im Spritesheet ändern Animationsframes horizontal und vertikal im Spritesheet Die Partikel zeichnen jetzt nur das erste Bild. den Animationsbereich des Partikelprozessmaterials erweitern , können wir die Animationsgeschwindigkeit für die Partikel festlegen. Ich möchte, dass meine Partikel eine konstante Geschwindigkeit haben, daher setze ich sowohl das Minimum als auch das Maximum auf eins. Hier kann auch eine Kurve verwendet werden, um die Randomisierung der Animationsgeschwindigkeit der einzelnen Partikel zu ändern die Randomisierung der Animationsgeschwindigkeit der einzelnen Partikel Dieselben Werte können auch angegeben werden, um jedem Partikel seinen eigenen Animationsversatz zu geben die Erweiterung des Bereiches können wir die Position, an der die Partikel erscheinen, ihren Drehwinkel und ihre Anfangsgeschwindigkeit bearbeiten ihren Drehwinkel und ihre Anfangsgeschwindigkeit Wir können die Emissionsform von einem einzigen Punkt aus eine Vielzahl anderer Formen ändern und die Größe der Form ändern, wenn wir möchten Punktemissionsformen eignen sich normalerweise am besten zur Bekämpfung von Partikeln. Der Winkel ermöglicht eine zufällige Anordnung der Rotation der Partikel Um es völlig zufällig zu machen, stellen Sie einfach max auf 360 ein. Da ich Pixelkunst verwende, möchte ich nicht, dass meine Partikel gedreht werden. Durch die Anfangsgeschwindigkeit fühlen sich unsere Partikel explosiver an. Die Stärke der Kraft wird für jedes Partikel nach dem Zufallsprinzip zwischen Minimum und Maximum bestimmt, wodurch sich die Partikel weniger gleichmäßig anfühlen Durch die Verteilung entsteht eine fächerförmige Form. Bei maximaler Ausrichtung auf 180 Grad die Richtung völlig zufällig Der Bereich mit der animierten Geschwindigkeit enthält Variablen, die Sie verwenden können , um Ihren Partikeln im Laufe ihrer Lebensdauer eine Vielzahl verschiedener konstanter Geschwindigkeiten zuzuweisen Ihren Partikeln im Laufe Angular lässt sie rotieren. Directional bewegt sie weiterhin in die Richtung, in die sie sich bereits bewegen. Orbital lässt sie um den Spawnpunkt kreisen. Das Radio bewegt sie vom Spawnpunkt weg. Und die Geschwindigkeitsbegrenzung verwendet eine Kurve, um die Geschwindigkeit jedes Partikels zu begrenzen Der Abschnitt „Beschleunigungen“ enthält ähnliche Variablen, mit denen Sie die Geschwindigkeit der einzelnen Partikel im Laufe ihrer Lebensdauer schrittweise beeinflussen können , sodass sie sich realistischer anfühlen Die Schwerkraft ist eine konstante Kraft in einer Richtung für alle Partikel Linear ist die Richtung , in die sich das Partikel bereits bewegt. Radial ist vom Spawnpunkt entfernt. Und tangential ist ähnlich wie orbital. Dämpfung ist eine nützliche Kraft, die dafür sorgt, dass Partikel im Laufe ihrer Lebensdauer langsamer werden . Das ist nützlich bei explosiven Partikeln oder Aufprallpartikeln , ist nützlich bei explosiven Partikeln oder Aufprallpartikeln , wie Partikelattraktoren sind für zwei D nicht verfügbar, daher hat diese Einstellung keine Wirkung den Anzeigebereich erweitern, können wir die Art und Weise ändern, wie jedes Partikel gezeichnet wird Durch Skalieren werden die Partikel nach dem Zufallsprinzip ihre eigene Größe bestimmen. Wenn wir eine Maßstabskurve hinzufügen, ändert sich dadurch die Art und Weise, wie jedes Partikel seine Skala im Laufe seiner Lebensdauer ändert Wir werden bald den Kurveneditor durchgehen. Bei Skalierung über Geschwindigkeit wird stattdessen die Skala von Partikeln im Verhältnis zu ihrer Geschwindigkeit und nicht zu ihrer Lebensdauer berechnet. Dies ist besonders nützlich um Staubwolken zu erzeugen , die sich auflösen. Farbkurven haben mehrere unterschiedliche Eigenschaften, angefangen bei einer Grundfarbe für alle Partikel Farbverlauf ermöglicht es uns, einen Farbverlauf zu erstellen , bei dem jedes Partikel im Laufe seiner Lebensdauer von der Farbe nach links zur Farbe auf der rechten Seite Diese Farbe wird mit der Grundfarbe multipliziert , um das Ergebnis zu erhalten Beim ersten Farbverlauf wird die Anfangsfarbe der einzelnen Partikel im Verlauf nach dem Zufallsprinzip ausgewählt Die Emissionskurve kann verwendet werden, um drei D-Partikel im Laufe ihrer Lebensdauer unterschiedliche Lichtmengen emittieren zu lassen, was bei zwei D nicht verwendet wird. Die Alpha-Kurve ist nützlich, um nur den Alphawert Ihrer Partikel im Laufe ihrer Lebensdauer zu bearbeiten Lassen Sie uns hier eine neue Ressource für Kurventexturen erstellen. Diese Kurventexturressource benötigt eine weitere eigene Kurvenressource. Wenn Sie darauf klicken, wird ein Kurveneditor geöffnet, mit dem wir auf einfache Weise eine Vielzahl von Effekten erstellen können. Die X-Achse dieses Diagramms ist Zeit, wobei Null der Zeitpunkt ist, an dem das Partikel erzeugt wird, und Eins das Ende der Lebensdauer des Partikels. Nein, 1 Sekunde Die Y-Achse ist der Wert, den wir bearbeiten handelt es sich um die Partikelfarben Alpha, wobei eins undurchsichtig und Null unsichtbar Wir können die Minimal- und Maximalwerte für unsere Achse bearbeiten, müssen das aber in diesem Zusammenhang nicht tun Wenn Sie einfach auf das Diagramm klicken, wird ein Punkt hinzugefügt , den wir nach Bedarf verschieben können. Ich möchte, dass meine Partikel zunächst undurchsichtig werden und dann im Laufe ihrer Lebensdauer unsichtbar Das ist ideal, um Partikel verblassen anstatt einfach zu verschwinden Tangenten werden automatisch auf die Punkte angewendet , um eine Kurve zu erzeugen einen beliebigen Punkt im Diagramm auswählen, können wir die Tangenten bearbeiten um jede Art von Kurve zu erstellen, die wir benötigen Wir können die Punkte und Tangenten auch manuell bearbeiten , indem wir den Punktebereich unten erweitern Farbtonvariation kann verwendet werden, um den Farbton Ihrer Partikelfarben nach dem Zufallsprinzip zu ordnen, wodurch sie weniger einheitlich aussehen Die restlichen Eigenschaften sind für unser Tot-Projekt nicht besonders geeignet, aber ich gebe Ihnen eine kurze Zusammenfassung dessen, wofür sie bestimmt sind Turbulenz kann angewendet werden, um zu simulieren, wie sich Luftströmungen auf Ihre Partikel auswirken würden Sie können das Geräuschmuster bearbeiten, das zur Berechnung der Turbulenzen verwendet wird , wenn es aktiviert ist Partikel können durch Kollisionen gestoppt oder abgetötet werden. Kollisionen sind hier nicht dasselbe wie Kollisionen, die wir bisher verwendet haben , da die Partikel von der Grafikkarte verarbeitet werden Sie können nur mit Lichtokkludern kollidieren, nicht mit Lichtokkludern Und wenn Ihre Partikel skalieren, kann ihr Kollisionsradius auch mit ihnen skaliert werden Und ein Subemitter kann verwendet werden , um Effekte wie ein Feuerwerk zu erzeugen, wodurch zusätzliche Partikelauslassungen entstehen. Damit meine Partikel den anderen Bildraten meines Spiels entsprechen, lege ich die Lebensdauer der Partikel auf acht Frames geteilt durch 12 Frames pro Sekunde Nachdem der Partikelemitter eingerichtet ist, sollten wir seine One-Shot-Eigenschaft auf true setzen Jetzt emittiert er nur noch Partikel in einem einzigen Burst , den wir mit unserem Skript auslösen können Ich schalte meinen Charakter Sprite wieder ein und öffne dann mein Charakterskript dem Partikelknoten einen eindeutigen Namen geben, können wir ihn in einer Variablen mit dem Tag on ready speichern Wenn der Charakter dann Schaden erleidet, können wir den Schnee anweisen, Partikel zu emittieren , indem wir seine Emissionseigenschaft auf true setzen. Beachten Sie, dass dies nicht funktioniert, wenn es schnell hintereinander verwendet wird, da der Partikelemitter da der Partikelemitter bereits Partikel emittiert Wenn Sie also nur die Einstellung „Emission“ auf „true“ werden keine weiteren Partikel erzeugt Zeiten wie diesen sollten Sie entweder für jeden Treffer einen neuen GPU-Partikelknoten erzeugen oder stattdessen die Neustart-Funktion aufrufen Beim Neustart wird der Partikelemitter gezwungen, seine aktuelle Emission zu beenden und mit einem neuen Satz von Partikeln von vorne zu beginnen Denkt daran, diesen Knoten nach Bedarf in eure feindlichen Szenen zu kopieren Bedarf in eure feindlichen Szenen zu Lass es uns ausprobieren. Wenn sie den Feind angreifen, stoßen sie jetzt Partikel aus , wenn sie getroffen werden. Und der Spielercharakter emittiert auch Partikel, wenn er Schaden erleidet Wir haben jetzt Partikeleffekte, die durch unsere Angriffe ausgelöst werden, aber wir können noch mehr tun, damit sich Kampf noch knackiger anfühlt Wir sehen uns im nächsten Video. 60. 8-4 Schütteln: Hallo Freunde. In diesem Video fügen wir eine Verwacklung der Kamera hinzu, damit sich der Kampf noch wirkungsvoller anfühlt Ab dem Kameraskript benötigen wir eine Variable, mit der wir es verwackeln können. Dabei handelt es sich um einen zweiten Vektor Es gibt zwar eine Vielzahl verschiedener Möglichkeiten, einen Kamerawake-Effekt zu erzeugen, aber ich denke, es ist sinnvoll, ein Tween zu verwenden, da es sich um eine Eigenschaftsänderung handelt , die über einen bestimmten Zeitraum stattfindet Lassen Sie uns also eine neue Tween-Variable namens Shake Tween deklarieren. Deklarieren Sie dann auch eine neue Funktion, die öffentlich zugänglich sein wird und die Kamera erschüttern kann Prüfen Sie zunächst, ob die Kamera bereits wackelt, indem Sie überprüfen, ob der Shake-Tween bereits existiert, und falls ja, beenden Wir können dann ein neues Tween erstellen. Dafür sind keine speziellen Übergangs - oder Lockerungsarten erforderlich - oder Lockerungsarten erforderlich Wir wollen eine Eigenschaft nicht gleichmäßig von einem Wert zum anderen verknüpfen, sondern eine Methode einfach mehrmals über einen kurzen Zeitraum aufrufen eine Methode einfach mehrmals über einen kurzen Zeitraum Wir müssen die Funktion, die wir aufrufen, deklarieren, aber ich nenne sie set shake als private Funktion Dann müssen wir ein Argument angeben, vom Anfang bis zum Ende des Tweens an die Funktion übergeben wird Dies ist die Intensität des Schütteleffekts, gemessen in Wir können dies als Parameter der Shake-Funktion akzeptieren , sodass jedes Skript, das eine Kamerawackelung auslösen möchte , die Intensität angeben kann Sie dann im Laufe der Dauer des Kamerawakels Reduzieren Sie dann im Laufe der Dauer des Kamerawakels die Intensität schrittweise auf Null. Möglicherweise möchten Sie diesen Parameter stattdessen zu einem anderen Parameter machen, wenn Sie Kamerawacklungen mit gleichbleibender oder steigender Intensität zulassen möchten Kamerawacklungen mit gleichbleibender oder steigender Intensität zulassen gleichbleibender oder steigender Intensität Das letzte Argument ist die Dauer von dazwischen, die wir auch in einen anderen Parameter umwandeln können Als Nächstes schreiben wir die Set-Shake-Funktion, die die Intensität als Parameter akzeptiert. Diese Funktion wird für die Dauer des Shakes bei jedem Frame aufgerufen , wobei die Intensität allmählich von dem Wert, der im ursprünglichen Funktionsaufruf angegeben wurde, auf Null ändert . Wir müssen also nur den Wert von Shake auf einen neuen Vektor zwei setzen. Wenn wir mit dem zweiten Punkt nach rechts beginnen, drehen wir ihn dann in eine zufällige Richtung. Ein zufälliger Drehwinkel kann eine zufällige Gleitkommazahl zwischen Null und Tau sein. Wir können die Ergebnisse dann mit der Intensität multiplizieren. Wenn dein Shake-Tween aus irgendeinem Grund nicht damit endet, dass du den Shake-Wert auf Null setzt, musst du das am Ende des Tweens tun Wir können das fertige Signal des Shake-Tweens mit der Set-Shake-Funktion verbinden und Null als Intensität festlegen Dadurch wird sichergestellt, dass der Shake-Wert jederzeit, nachdem die Kamera mit dem Schütteln fertig ist , wieder auf Null zurückgesetzt wird Damit der Verwacklungsvektor die Kamera tatsächlich bewegt, müssen wir ihn lediglich zur Kameraposition in unserer Prozessfunktion hinzufügen zur Kameraposition in unserer Prozessfunktion Wie in unserer Spieleszene können wir jetzt jedes Signal, das ein Verwacken der Kamera auslösen soll, mit der Verwacklungsfunktion unserer Kamera verbinden . Zum Beispiel, wenn der Spielercharakter einen Feind angreift oder wenn er Schaden erleidet. Im Spielercharakter-Skript können wir Signale für diese Ereignisse hinzufügen. Zurück in der Spielszene können wir diese Signale mit der Shake-Funktion der Kamera verbinden . Um einer Signalverbindung Argumente hinzuzufügen, müssen wir den Abschnitt für Fortgeschrittene erweitern. Wir können dann Float aus der Liste der Argumenttypen auswählen , da der Intensitätsparameter in unserem Skript ein Float ist. Klicken Sie dann auf die Schaltfläche Hinzufügen. Der Shake benötigt auch eine Dauer, was ebenfalls vom Typ Float ist. Wir können also erneut auf die Schaltfläche Hinzufügen klicken , um einen weiteren Float hinzuzufügen. Die Werte, die wir für Argument eins angeben ändern die Intensität der Erschütterung, gemessen in Pixeln, und Argument zwei gibt die Dauer der Erschütterung in Sekunden an. Ich lasse meine Spielercharaktere angreifen und innerhalb einer Viertelsekunde ein Kamerawackeln mit einer Intensität von vier Pixeln verursachen ein Kamerawackeln mit einer Intensität von vier . Aber wenn sie Schaden erleiden, werde ich die Kamera innerhalb einer halben Sekunde mit einer Intensität von acht Pixeln erschüttern . zur Szene mit den Spielercharakteren wechseln, müssen wir diese Signale zu den richtigen Zeiten aussenden, angefangen mit unserem Signal „ Schaden erhalten“ in den Hurt-Boxen, das bereits mit einer Funktion verbunden ist, die im Charakterskript nach erlittenem Schaden benannt ist. Wenn wir diese Funktion im Spielercharakterskript überschreiben , können wir die Superklassenfunktion aufrufen und dann das Signal ausgeben Als Nächstes können wir das Trefferfeld auswählen und dem Signal im eingegebenen Bereich eine weitere Signalverbindung hinzufügen Signal im eingegebenen Bereich eine weitere Signalverbindung und eine neue Funktion aufrufen lassen Nennen wir es bei Angriff gelandet. Das muss sich nicht mit dem anderen Bereichsknoten befassen , also können wir den Abschnitt für Fortgeschrittene verwenden um dieses Argument von der Signalverbindung Da wir das Gebietsargument aufgehoben haben, hat die Funktion keine Diese Funktion muss lediglich das Signal aussenden, das die Kamera verwackelt Nein, lass es uns ausprobieren. Wenn ich den Mausritter angreife, löst das das Signal „ Trefferfelder sind eingegeben“ aus, das durch den Spielercharakter bis zur Spielszene sprudelt und ein Verwacken der Kamera auslöst. Wenn der Mausritter den Spielercharakter trifft wird das beschädigte Empfangssignal der Hurt-Box ausgelöst, was zu einem stärkeren Kamerawackeln führt. Unsere Kamera wackelt jetzt als Reaktion darauf, dass der Spielercharakter Feinde angreift und Schaden erleidet, aber unsere Charaktere sterben nicht, wenn ihnen die Gesundheit ausgeht Wir sehen uns im nächsten Video. 61. 8-5 Todesfälle: Hallo Freunde. In diesem Video werden wir unsere Charaktere sterben lassen, wenn ihnen die Gesundheit ausgeht. beginne in der Nachtszene mit der Maus, wähle den Animation-Player-Knoten aus und erstelle schnell eine neue tote Animation, indem ich die Trefferanimation dupliziere Nachdem Sie das Sprite auf das richtige Bild im Spritesheet gesetzt haben, empfiehlt es sich, die Hurt-Box auszuschalten, damit sie keinen Schaden mehr erleiden können , und sie auch nicht wieder einzuschalten Das Gleiche kann für alle anderen Areal- und Di-Knoten gemacht werden , wobei der Kontaktschaden und die Trefferbox zwei ausgeschaltet werden, sodass der tote Feind dem Spielercharakter keinen Schaden mehr zufügen kann dem Spielercharakter keinen Schaden mehr zufügen den Animationsbaumknoten auswählen, können wir diese tote Animation zur Zustandsmaschine hinzufügen und automatisch zu ihr wechseln, wenn dieser Charakter tot ist. Im Gegensatz zu anderen Animationen ist kein Übergang aus dem toten Zustand erforderlich. Jetzt müssen wir nur noch die Variable Is dead zum Charakterskript hinzufügen . Ich setze es als booleschen Wert an den Anfang des Skripts. Und deklariere auch ein Signal zwei, nur für den Fall, dass wir jemals wollen, dass etwas auf den Tod nur für den Fall, dass wir jemals wollen, dass etwas bestimmter Charaktere reagiert Schreiben Sie dann eine öffentliche Funktion namens Die, die den Wert dieser Variablen auf true setzt und das Signal ausgibt. Überall in diesem Skript , wo ein Charakter jede Aktion ausführen könnte , die nach seinem Tod nicht erlaubt sein sollte, können wir einfach zuerst den Wert der Variablen is dead überprüfen . Wenn dem Charakter also gesagt wird, dass er in eine Richtung schauen soll, er aber tot ist, sollte er diese Aufforderung ignorieren. Genauso ignorieren wir es, wenn sie angreifen. In ähnlicher Weise sollte dieser Charakter nicht springen, wenn ihm gesagt wird, er soll springen, er aber tot ist. Das Gleiche gilt für Angriffe. Und im physikalischen Prozess setze ich ihre Bewegungsrichtung auch auf Null, setze ich ihre Bewegungsrichtung auch wenn sie tot sind, sodass sie sich nie bewegen, solange sie tot sind, sondern von der Physik beeinflusst werden. Im Hurt Box-Skript haben wir bereits das farbige Signal erzeugt und es ausgegeben, wenn der Charakter keine Lebenspunkte mehr hat, als wir das Drehbuch im vorherigen Abschnitt geschrieben haben das Drehbuch im vorherigen Abschnitt geschrieben Aber um eine Todesanimation und keine Trefferanimation abzuspielen , wenn der Charakter Schaden erleidet und dadurch stirbt, müssen wir sicherstellen, dass wir zu diesem Zeitpunkt nur das gefärbte Signal aussenden Also verschieben wir das Signal, das Schaden erlitten hat, in einen SE-Block und geben dem gefärbten Signal Priorität Wir müssen lediglich das gefärbte Signal der Hurt-Box mit der Würfelfunktion des Feindes verbinden gefärbte Signal der Hurt-Box mit der Würfelfunktion des , um die Animation auszulösen Entweder in der feindlichen Szene oder in der Rauminhaltsszene, wo auch immer du die KI-Knoten deines Feindes hast, möchtest du vielleicht auch das DID-Signal des Feindes mit der freien Funktion dieser Knoten verbinden DID-Signal des Feindes mit der freien Funktion dieser Knoten Alternativ können Sie dies in den Skripten selbst tun. Wenn Sie die Ready-Funktion außer Kraft setzen, können feindliche Gegner mit Ure verbunden werden Auf diese Weise müssen Sie das Signal im gesamten Projekt nicht hunderte Male manuell anschließen gesamten Projekt nicht hunderte Male manuell Lass es uns ausprobieren. Wenn ich den Mausritter fünfmal angreife, erreicht seine Gesundheit Null und er stirbt, wodurch die Todesanimation abgespielt wird und alle Aktionen gestoppt werden. Ich kann ihn auch berühren, ohne Schaden zu nehmen. Nun zum Spielercharakter, ich habe eigentlich keine Todesanimations-Sprites für diesen Charakter Stattdessen werde ich die Trefferanimation wiederverwenden und sie duplizieren, um eine Todesanimation zu erstellen, da ich weiß, dass die Spielszene sowieso ausgeblendet und zurückgesetzt wird, wenn dieser Charakter stirbt die Spielszene sowieso ausgeblendet und zurückgesetzt wird Wie beim Feind ist es eine gute Idee, auch alle Verletzungs- und Trefferboxen auszuschalten Die einzige wirkliche Änderung, die ich hier vornehmen werde , ist die Animationsschleife. Im Animationsbaum füge ich die tote Animation wie zuvor hinzu, mit einem automatischen Übergang, wenn der Charakter tot ist. Aber dieses Mal füge ich auch einen Übergang aus dem toten Zustand hinzu, vorausgesetzt , dass sie nicht mehr tot sind, da der Spielercharakter nach seinem Tod wiederbelebt wird Nachdem ich das Signal für den Tod der Hurt Box mit dem Charakterskript verbunden habe, wechsle ich zum Charakterskript des Spielers Wir müssen eine Revive-Funktion schreiben, die verwendet werden kann, um den Spielercharakter wieder zum Leben zu erwecken, indem wir die Variable I dead wieder auf False setzen Wir können der Hurt-Box auch sagen gleichzeitig ihre volle Gesundheit wiedererlangen soll Um der Todesanimation des Spielercharakters mehr hinzuzufügen, überschreibe ich die Würfelfunktion im Spielercharakter-Skript. Ich rufe zunächst die Superklassenfunktion auf und mache dann einige andere Dinge, mache dann einige andere Dinge den Spielercharakter spezifisch den Partikeleffekte-Node wiederverwende, setze ich seine One-Shot-Eigenschaft auf False seine Explosivität Und die Eigenschaft „Emission“ wird auf „Wahr“ gesetzt, wodurch der spontane Ausbruch von Partikeln in einen stetigen Strom umgewandelt wird Darüber hinaus werde ich die Modulationsfarbe des Charakters verändern eine höhere Intensität zu erzielen Nachdem ich ein neues Tween erstellt habe, setze ich die Modulationsfarbe dieses Knotens auf eine neue Farbe mit RGB-Werten von Dann setze ich in der Revive-Funktion all diese Werte wieder auf ihre normalen Werte zurück A In der Spielszene kann die Kamera auch auf den Tod des Spielers mit einem weiteren, noch intensiveren Kamerawackeln reagieren Tod des Spielers mit einem weiteren noch intensiveren Kamerawackeln Der Spielmanager muss auch auf den Tod des Spielercharakters reagieren Tod des Spielercharakters , um alles zurückzusetzen. So können wir das dD-Signal des Spielercharakters mit dem Game Manager-Skript verbinden . Nennen wir diese Funktion auf Player DD. Wenn der Spieler stirbt, können wir zunächst den Eingabe-Handler deaktivieren, können wir zunächst den Eingabe-Handler deaktivieren sodass er den Charakter nicht mehr kontrollieren kann. Ich warte zuerst eine Sekunde , bis die Todesanimation meines Charakters abgespielt wird. Das kann erreicht werden, indem dem Szenenbaum anweise, einen Timer zu erstellen. Wir können den Szenenbaum jederzeit mit der Funktion get tree abrufen und die Funktion create timer aufrufen, die ein Argument für die Länge des Timers akzeptiert. Dies gibt den bereits gestarteten Timer zurück , sodass wir auf sein Timeout-Signal warten können Dadurch wird die Ausführung dieser Funktion in dieser Zeile für genau 1 Sekunde unterbrochen Funktion in dieser Zeile für genau 1 Sekunde Nachdem er zu Schwarz verblasst ist, müssen wir den Spielercharakter neu positionieren , so dass er reagieren soll Da wir noch keine geeigneten Systeme dafür haben , werde ich sie einfach am Ursprung der Spielszene platzieren und einen Kommentar hinterlassen, dass dies später implementiert werden muss Wir können jetzt den Spielercharakter wiederbeleben, wieder einblenden und den Eingabe-Handler wieder aktivieren, und den Eingabe-Handler wieder aktivieren sodass der Spieler weiterspielen kann Wenn Sie Text anzeigen möchten, können Sie der Canvas-Ebene einen Label-Node hinzufügen Ich nenne Mind Game Over und gebe ihm einen eindeutigen Namen. Füllen Sie es dann mit etwas Text und zentrieren Sie es. Geben Sie ihm eine größere Schriftgröße. Und verankern Sie es in der Mitte des Bildschirms. Bevor ich es zu Schwarz verblasse, erstelle ich auch einen Tween, Alphawert des Labels bis zu eins verblassen lässt Ich moduliere den Alphawert auf Null, sodass er standardmäßig unsichtbar ist Ohne zu warten, wird dies zur gleichen Zeit geschehen , in der der Bildschirm schwarz wird Das Etikett muss vor der Blende gezeichnet werden , damit es sichtbar ist Nachdem ich den Spielercharakter neu positioniert habe, warte ich noch eine Sekunde bevor ich zum Text übergehe Aber ich mache es schneller, als es eingeblendet ist. Nachdem ich den Spielercharakter wiederbelebt habe, zeige ich eine andere Meldung an das Spiel wieder eingeblendet Ich dupliziere die bestehende Game-Over-Nachricht, nenne diese Nachricht Revive und ändere Bevor das Einblenden wieder gelöscht wird, verwende ich ein weiteres Tween, damit der Text eingeblendet Warten Sie eine weitere Sekunde und blenden Sie den Text dann wieder aus Lass es uns ausprobieren. Ich lasse die Nacht der Maus meinen Spielercharakter töten. Unsere Charaktere sterben jetzt und der Spielmanager reagiert auf den Tod des Spielercharakters, aber in unserem Spiel ist noch kein Boss drin Wir sehen uns im nächsten Video. 62. 8-6 Chef 1: Hallo Freunde. In diesem Video bauen wir einen Boss für unser Spiel , der komplexer ist als unsere anderen Feinde. Ich beginne damit, einen neuen Asset-Ordner zu erstellen , der die Assets für diesen Boss enthält. Importiere dann die Sprites. Dann erstelle ich in meinem Ordner mit feindlichen Szenen eine neue Szene mit dem Namen Mac Mouse mit dem Stammknotentyp CharacterBody two D. Dieser Boss besteht aus mehreren verschiedenen Sprite-Komponenten , die ich zusammensetzen und übereinander schichten muss Zuerst füge ich ein normales D ohne zwei hinzu, ich alle visuellen Komponenten des Bosses umdrehen kann , wenn sie sich umdrehen, und es Flip nennen umdrehen, und Dann füge mehrere Sprites für die verschiedenen Komponenten hinzu. Ich benötige ein Sprite für die Panzerung, das wird eine Atlas-Textur sein Und nachdem ich die Textur ausgefüllt habe, wähle ich die entsprechende Region aus dem Spritesheet aus Dies wird um 48 Pixel nach oben verschoben. diesen Sprite-Knoten dupliziere, benenne ich ihn in Gears um und ändere seinen Typ in Animated Sprite two D. Wenn ich dem Knoten eine Sprite-Frames-Ressource gebe, füge ich die Zahnrad-Sprites Dann ändere die Animationsgeschwindigkeit auf 12 Bilder pro Sekunde. Das sollte hinter der Panzerung stehen, also ordne ich die Knoten neu an den Sprite-Knoten für die Panzerung erneut dupliziere, erstelle ich ein weiteres Sprite für den Hintergrund hinter den Zahnrädern Nachdem ich die Atlas-Textur für diesen Knoten einzigartig gemacht habe, kann ich eine andere Region zum Zeichnen auswählen und diesen Knoten neu anordnen, sodass er hinter den anderen gezeichnet wird Dieser Hintergrund dient auch dazu, die Zahnräder so zu beschneiden, dass nichts außerhalb des Körpers gezeichnet wird Das können wir tun, indem wir die Zahnräder als untergeordnetes Element des Hintergrundknotens platzieren. Wählen Sie dann im Bereich „Sichtbarkeit“ den Hintergrund aus und ändern Sie die Einstellung „Clip-Kinder“ von „ Deaktiviert“ auf „Ausschneiden und Zeichnen“. Jetzt ziehen sich die Zahnräder nur noch in den Körper hinein. Es gibt auch eine animierte Aufziehtaste. Also werde ich meinen Gears-Knoten duplizieren, um einen weiteren Animated Sprite-Tout-Knoten zu erstellen, und ihn Key nennen Nachdem ich die Sprite-Frames-Ressource für diesen Knoten einzigartig gemacht habe, ersetze ich die Gear-Sprite-Frames durch die wichtigsten Sprite-Frames Sprite-Frames Ich werde dann die Taste neu positionieren, sodass sie sich an der entsprechenden Position auf Rückseite des Körpers der Mc-Maus Ich benötige mehr Animated Sprite Two-D-Knoten für die Räder, also dupliziere ich den Schlüssel, um ein animiertes Rad zu erstellen Nachdem ich die Sprite-Frames-Ressource einzigartig gemacht habe, tausche ich die wichtigsten Sprite-Frames gegen die Rad-Sprite-Frames aus die Rad-Sprite-Frames Stellen Sie das Rad dann an eine gute Position und verschieben Sie es so, dass es auf dem Boden liegt O. Um die Räder hinter dem Körper zu zeichnen , ordne ich sie so an, dass sie sich im Szenenbaum über dem Körper Ich dupliziere das Vorderrad, um ein zweites Rad zu erstellen und es neu zu positionieren Die letzte visuelle Komponente dieses Bosses ist ein Fass, das aus seinem Mund herausragt Es wird nur ein gewöhnlicher Geist sein. Nachdem ich die Sprite-Textur zugewiesen habe, verschiebe ich sie so, dass sie um den Mund der Mc-Maus liegt, und sie hinter die Body-Sprites Wenn dieses Fass Projektile abfeuert, möchte ich, dass es aus dem Mund der Mc-Maus herausragt, sodass es einen Offset von minus 16 Pixeln hat Ich füge an dieser Position einen Flächentutti-Knoten hinzu, der das Projektil sein wird Geben Sie ihm dann einen animierten Sprite Tutti-Knoten mit Sprite-Frames-Ressourcen und fügen Sie die beiden Fireball-Sprite-Frames hinzu Nachdem ich die Bildrate eingestellt habe, habe ich standardmäßig auch diese automatische Wiedergabe Dazu wird eine Kollisionsform benötigt, die nur ein Kreis sein wird. Damit es als Projektil funktioniert, muss das Projektilskript beigefügt sein Das Projektilskript erwartet, dass das Projektil eine Aufprallanimation hat, also füge ich eine hinzu, indem ich dieselben Schlag-Sprites wie mein anderes Projektil verwende dieselben Schlag-Sprites Dabei muss die Hurt-Box-Ebene des Spielers überwacht und maskiert Wir können den eingegebenen Bereich und die vom Körper eingegebenen Signale mit dem Projektilskript verbinden , um Aufprallanimation und den Schaden auszulösen O. Wenn der Feuerball zusammengebaut ist, können wir ihn als eigene Szene im Projektilordner speichern im Projektilordner Ich füge einen Toti-Knoten als untergeordnetes Element des Feuerballs hinzu, der als Ort dient, an dem die Projektile erscheinen, genau wie wir es mit dem Spielercharakter gemacht Ordne dann den Tutti-Markerknoten so an, dass er ein Bruder des Feuerballs ist, wobei seine relative Position beibehalten wird, und lösche den Feuerball beibehalten an, dass er ein Bruder des Feuerballs ist, wobei seine relative Position beibehalten wird, und lösche den Feuerball. Setzen Sie dann den Abstand der Fässer Standardposition zurück nur den Körper nach links und rechts drehen, Ich möchte nicht nur den Körper nach links und rechts drehen, sondern auch, dass der Körper der Mc-Maus rumpelt, aber nicht die Räder Also werde ich alles, was ich will, als Kinder eines anderen Körpers mit dem Namen D zum Rumpeln bringen Kinder eines anderen Körpers mit dem Namen D Jedes Mal, wenn sich die Mc-Maus bewegt, möchte ich, dass Staub und Steine von den Rädern vom Boden aufgewirbelt werden von den Rädern vom Boden aufgewirbelt Also füge ich einen GP-Partikel mit zwei D-Knoten für die Felsen hinzu. Dann weise ich einen Rock Sprite als Textur zu und erstelle ein Prozessmaterial für Partikel Okay. Lass die Steine vom Boden aufsteigen, alles was ich tun muss, ist die Geschwindigkeitsrichtung nach oben zu ändern und jedem Stein eine zufällige Geschwindigkeit von 32-64 Pixeln pro Sekunde zu geben eine zufällige Geschwindigkeit von 32-64 Pixeln pro Sekunde Bei Staub dupliziere ich zunächst den Gesteinspartikel-Emitter und Dann weise ich der Textureigenschaft dasselbe Partikel-Spritesheet zu, das ich für Attack Impacts verwendet habe das ich für Attack Impacts Da es sich um ein Spritesheet handelt, das animiert werden soll, benötigt dieser Knoten ein Canvas-Objektmaterial mit aktivierter Partikelanimationseigenschaft der richtigen Anzahl von Nachdem ich das Material für die Partikelverarbeitung einzigartig gemacht habe, behalte ich die Geschwindigkeit bei, entferne aber die Schwerkraft und füge genügend Dämpfung hinzu, um der ursprünglichen Geschwindigkeit entgegenzuwirken Unter „Anzeige“ füge ich eine Animationsgeschwindigkeit von eins hinzu, um die Partikel zu animieren , und eine Alpha-Kurve , damit sie mit der Zeit verschwinden. Ich möchte, dass das im Vordergrund dargestellt wird, also setze ich die Eigenschaft „Reihenfolge“ auf eins Das sollte ausreichen, also dupliziere ich die beiden Partikelknoten und füge sie dem anderen Rad hinzu. Ich möchte nicht, dass sie standardmäßig emittieren, also wähle ich alle gruppiert aus und schalte ihre Emissionseigenschaften aus. Wie jeder andere Feind benötigt auch dieser eine Kollisionsform, um mit der Umgebung zu kollidieren , sowie Verletzungs- und Trefferboxen Da dieser Feind eine eher einzigartige Form hat, verwende ich eher ein Kollisionspolygon als eine Kollisionsform eher ein Kollisionspolygon als eine Kollisionsform dem Polygon einige Scheitelpunkte hinzufüge , um die allgemeine Form des Körpers des Chefs zu erhalten, muss ich sicherstellen, dass das Kollisionspolygon den Boden berührt Ich möchte mir auch nicht wirklich die Mühe machen, dieses Polygon umzudrehen, also mache ich es symmetrisch. Das reicht für Kollisionen mit der Umgebung aus, ermöglicht es dem Spielercharakter aber auch , auf dem Feind zu stehen Bei der Hurt-Box geht es mir etwas weniger darum, die Form des Feindes so genau abzubilden, also verwende ich eine normale Kapsel Wenn du mehrere Standardformen kombinieren möchtest , um eine komplexere Hurt-Box zu erstellen, kannst du einfach mehr Kollisionsformknoten hinzufügen. Ich füge über der ersten eine zweite Kapsel hinzu, um einen größeren Teil des Körpers abzudecken. Ich möchte mir auch nicht die Mühe machen, diese Hurt-Boxen umzudrehen, daher hilft es, dass sie symmetrisch sind Der D-Node Area Two sendet seine Signale als ob alle Formen zu einer Form zusammengefasst wären Denken Sie jedoch daran, dass, wenn die Formen weit voneinander entfernt sind, etwas möglicherweise in eine Kollisionsform eindringt, diese dann verlässt und dann in eine andere Kollisionsform eintritt, was zu mehreren Kollisionen führt Ich werde auch eine separate Hurt-Box für den Aufziehschlüssel hinzufügen. diesem Schlüssel eine eigene Hurt-Box gibst muss er nicht mit der Gesundheit des Bosses verbunden sein, sondern kann Signale aussenden, wenn der Spieler ihn angreift Dies kann nur eine einfache kreisförmige Kollisionsform haben, muss aber umgedreht werden Ich werde also sicherstellen, dass die Exposition des Formknotens ausschlaggebend dafür ist , auf welcher Seite sich die Hurt-Box befindet Und schließlich braucht dieser Feind eine Hitbox. Dies wird verwendet, wenn die Mc-Maus vorwärts fährt. Ich möchte, dass dies dem Spielercharakter schadet, wenn er vor oder über dem Boss steht. Ich verwende also eine um 90 Grad gedrehte Kapsel, die über das Kollisionspolygon des Körpers davor und darüber hinausragt die über das Kollisionspolygon des Körpers davor und darüber hinausragt , aber nicht dahinter Wählt man den Wurzelknoten des Charakters aus, muss der Feind als Terrain betrachtet werden , damit der Spielercharakter darauf stehen kann, aber auch auf der feindlichen Ebene existiert und nur das Terrain maskiert Keine der Hurt-Boxen oder Trefferboxen muss standardmäßig überwacht oder überwacht werden können Wir schalten sie durch Skripte oder Animationen ein, wenn sie aktiviert werden müssen Aber die Hurt-Boxen können auf die Kollisionsebene der gegnerischen Hurt-Box gesetzt werden, und die Hit-Boxen können so eingestellt werden, dass sie die Kollisionsebene der Verletzungsbox des Spielers maskieren Kollisionsebene der Verletzungsbox , sodass sie funktionieren, wenn sie aktiviert sind. Wir haben jetzt einen Boss für unser Spiel zusammengestellt, aber es gibt noch keine Skripte, die ihn steuern. Wir sehen uns im nächsten Video. 63. 8-7 Chef 2: Hallo Freunde. In diesem Video werden wir unserem Boss komplexere Verhaltensweisen geben als unseren normalen Feinden. Die tatsächliche Mechanik des Fortschritts wird im nächsten Abschnitt behandelt. Aber vorerst wird es helfen, darüber nachzudenken, wie unser Boss im Verhältnis zu seiner Arena existieren sollte. Also lasst uns diesen Boss-Feind in eine einfache Arena mit einer Mauer auf beiden Seiten platzieren . Im Allgemeinen fangen Bosse in Metroidvania den Spieler in einer Arena ein, und sobald der Spieler sie betritt, muss er den Boss besiegen bevor er sie verlassen darf Das ist ein Ereignis, das dadurch ausgelöst werden muss, dass der Spielercharakter den D-Node von Area Two betritt , also fügen wir der Szene einen hinzu und nennen ihn Dann gib ihm eine Kollisionsform. Ich verwende ein Rechteck und lasse es einen sehr großen Bereich abdecken, sodass der Spieler es nicht umgehen kann und lasse es den Körper des Spielercharakters überwachen. Dazu muss ein Skript angehängt werden, aber ich erstelle es im Dateisystem-Tab in einem neuen Ordner mit feindlichen Skripten für Bosse, wir Boss Encounter nennen können, wodurch Area Two D erweitert wird. Dieses Skript wird dafür verantwortlich sein den gesamten Ablauf der Bossbegegnung zu steuern, einschließlich wann sie beginnt, wann sie endet und alle Phasenübergänge, Dinge wie Titelkarten, wechselnde Musik usw. Wir müssen dem einen Klassennamen geben damit wir ihn später erweitern können Um darauf zu reagieren, dass der Spielercharakter an dieser Bossbegegnung teilnimmt, können wir weitermachen und die Funktion on body entered schreiben, die einen Parameter namens body vom Typ D ohne zwei akzeptiert und nichts zurückgibt. Der Spielercharakter nimmt an dieser Boss-Begegnung teil. Zunächst sollten wir alle zukünftigen Kollisionen mit diesem Bereich ausschalten , indem set deferred verwenden, um die Überwachungseigenschaft auf False zu setzen Denken Sie daran, dass wir, wenn eine Funktion durch ein Kollisionsereignis aufgerufen wird, unsere Kollisionsobjekte nicht gleichzeitig ändern sollten . Deshalb verschieben wir dies, bis die Kollisionen behandelt Wir können dann die Arena schließen, den Spieler darin gefangen halten und alle erforderlichen Initialisierungen durchführen Aber darauf kommen wir später zurück. Vorerst deklarieren wir eine exportierte Variable, die den Boss-Feind selbst und eine für den Spielercharakter als Ziel enthält den Boss-Feind selbst . Wenn der Spielercharakter an der Bossbegegnung teilnimmt, können wir den Wert des Ziels auf den Körper sowie als lokale Phasenvariable als Ganzzahl festlegen . Fügen Sie dann eine Startfunktion, eine Endfunktion und auch eine Phasenübergangsfunktion die Phase als Parameter akzeptiert und die Variable auf ihren neuen Wert aktualisiert. In der Startfunktion können wir Phase auf eins setzen und unsere Entscheidungsfunktion aufrufen , um den Kampf zu beginnen. Wir benötigen außerdem eine Funktion , die dem Boss mitteilt, was er als Nächstes tun soll. Vorerst rufe ich die Startfunktion auf, wenn der Spielercharakter die Boss-Arena betritt. Stellen Sie sicher, dass Sie dieses Skript speichern damit der Klassenname registriert ist. wir nun die Grundstruktur festgelegt haben, hängen wir ein neues Skript an unseren Boss-Encounter-Knoten an. Ich benenne es nach meinem Boss, Neck Mouse Encounter, der Boss Encounter erweitert , und speichere es im entsprechenden Ordner. Mit dem angehängten Skript können wir der exportierten Variablen den Endgegner zuweisen, die Kollisionsmaske auf die Ebene des Spielercharakters setzen und das vom Körper eingegebene Signal verbinden. Da die Funktion „Ein Körper eingegeben bereits in der Oberklasse Boss-Begegnung existiert, brauchen wir uns in diesem Skript darüber keine Gedanken zu machen Wir werden jedoch die Entscheidungsfunktion überschreiben und dieser speziellen Boss-Begegnung einen eigenen Algorithmus geben dieser speziellen Boss-Begegnung , der entscheidet, was sie als Nächstes tun wird Die Bossbegegnung auf diese Weise zu strukturieren, macht es einfacher, das Verhalten eines Bosses je nachdem, in welcher Phase er sich gerade befindet, zu ändern oder der Arena als Reaktion auf die Aktionen des Bosses Umweltgefahren hinzuzufügen oder das Verhalten mehrerer Bosse in einer einzigen Begegnung zu synchronisieren das Verhalten mehrerer Bosse in einer Jede neue Bossbegegnung, die wir erstellen möchten , kann auch die Klasse der Bossbegegnungen erweitern und für jeden Endgegner eigene, einzigartige Implementierungen bereitstellen für jeden Endgegner eigene, einzigartige Implementierungen Zunächst ist es eine gute Idee, zu überprüfen, ob der Boss tot ist, bevor wir ihn entscheiden lassen, was als Nächstes zu tun Wenn sie also schon tot sind, können wir einfach zurückkehren. Es ist auch eine gute Idee, die Aktionen eines Bosses mit einer kurzen Pause abzuwarten , bis ein Timeout-Signal des Timers ausgelöst Wir können es weniger vorhersehbar machen indem wir die Dauer des Timers zufällig und sogar die Kadenz des Kampfes mit jeder Phase erhöhen, indem wir durch die Phasenzahl dividieren Und egal, wofür sich der Boss entscheidet, er sollte sich wahrscheinlich dem Ziel zuwenden Wir können also eine Funktion aufrufen, die dem Chef sagt, dass er nach links schauen wenn die globale Exposition des Ziels geringer ist als seine eigene Mithilfe einer Match-Anweisung für die Phasenvariable können wir auf einfache Weise verschiedene Aktionsoptionen für verschiedene Phasen bereitstellen verschiedene Aktionsoptionen für verschiedene Phasen Da mein Chef so einfach ist, werde ich mich dafür entscheiden, die Intensität der Aktionen phasenweise zu erhöhen , anstatt neue einzuführen. Mit einer weiteren Match-Anweisung auf einer zufälligen Ganzzahl von 0-1 schaffe ich eine gleichmäßige Chance, zwischen zwei verschiedenen Aktionen zu entscheiden Entweder bewegt sich der Boss an eine zufällige Position in der Arena, die der globalen Position dieses Boss-Begegnungsknotens plus einer Zufallszahl zwischen minus 300 und positiven 300 entspricht, oder der Boss schießt Feuerbälle auf den Spieler Ich werde die Anzahl der Feuerbälle basierend auf der aktuellen Phase randomisieren Feuerbälle basierend auf der Ich möchte auch, dass der Boss eine dritte Aktion hat, die darin besteht, den Spielercharakter mit höherer Geschwindigkeit anzugreifen, aber nur unter bestimmten Bedingungen Wenn die Mc-Maus also zum Laden bereit ist , wird sie geladen. Wenn nicht geladen wird, wird die Aktion nach dem Zufallsprinzip ausgewählt. Und ich gebe ihm das Vorzeichen der globalen Position des Ziels abzüglich der globalen Position der McMouse als Richtung Wenn Sie planen, welche Aktionen Ihr Chef wann verwenden soll, erhalten Sie genau die öffentlichen Variablen und Funktionen, die Sie in deren Skripten schreiben müssen. Aus diesem Skript können wir also ersehen, dass das Skript unseres Chefs eine „Ist tot“ -Variable, eine einsatzbereite Variable und außerdem Funktionen „Nach links zeigen“, „aufladen “, zur Position bewegen und „Feuerbälle abfeuern Dies ist eine einfache Methode, um beim Schreiben komplexer Skripte an die Kapselung heranzukommen Kapselung Wir können das Skript schreiben, das zuerst eine Schnittstelle herstellen muss , sodass wir bereits genau wissen, was wir Die Kapselung hilft uns auch dabei, Abstraktion zu erreichen. Da wir uns nur auf das konzentrieren, was öffentlich zugänglich sein muss, können wir auch davon ausgehen, dass alles andere privat sein sollte Als Nächstes hängen wir ein Skript an den Root-Node des MCMUS und speichern es im Ordner Enemy Scripts Wir können alle Variablen und Funktionen deklarieren, die die entsprechenden Parameter aus dem Boss-Encounter-Skript akzeptieren aus dem Boss-Encounter-Skript Wenn wir ein Signal deklarieren und es so etwas wie fertig nennen, dann können wir dieses Signal von allen Aktionen ausgeben , die in der Entscheidungsfunktion ausgewählt wurden . Lassen Sie uns vorerst einfach ausdrucken, was wir vom Chef erwartet hatten. Wir können zuerst überprüfen, ob dieser Feind tot ist, und wenn ja, das fertige Signal aussenden sofort das fertige Signal aussenden und zurückkehren, damit nichts passiert. Warten Sie dann 1 Sekunde bevor Sie das fertige Signal aussenden. Wählen Sie dann in der Inhaltsszene den Knoten „ Endgegner“ aus, den wir dem Endgegner selbst zuordnen können , wenn wir möchten , und verbinden Sie das fertige Signal mit der Entscheidungsfunktion. Jedes Mal, wenn dieser Bossgegner eine der Aktionen abschließt, entscheidet er automatisch, was als Nächstes zu tun ist. Das sollte ausreichen , um den Ablauf unseres Bosskampfes zu demonstrieren . Also lass es uns ausprobieren. Wir können anhand der Ausgabe alle ein oder zwei Sekunden sehen, der Feind eine Entscheidung darüber trifft, was als Nächstes zu tun ist. Unser Boss-Feind wird jetzt durch ein Boss-Encounter-Skript gesteuert, aber wir müssen noch implementieren, wie alles intern in der Boss-Szene funktioniert. Wir sehen uns im nächsten Video. 64. 8-8 Chef 3: Hallo Freunde. In diesem Video werde ich durchgehen, wie ich die Funktionen meines Chefs geschrieben habe, damit Sie meine Methoden mit der Art und Weise vergleichen können , wie Sie Ihre implementiert haben. Zuerst habe ich die Hit-Box- und Hurt-Box-Skripte an die Hitbox bzw. die Hurt-Boxen des Chefs angehängt Hurt-Box-Skripte an die Hitbox bzw. die Hurt-Boxen des Chefs Dann habe ich mit den Boss-Enemy-Skripten angefangen. Ich habe Signale für alles deklariert , was verwendet werden sollte, um den Bosskampf zu starten oder zu beenden oder einen Phasenübergang herbeizuführen. Ein anderes, wenn der Boss die Richtung ändert , sodass ich weiß, wann ich die Dinge umdrehen muss, und ein paar mehr, um zu wissen, wann der Boss an seinem geplanten Ziel angekommen ist oder gegen eine Wand gekracht Dann ist da noch das Signal, das weggelassen wird, wenn die aktuell vom Chef beschlossene Aktion abgeschlossen ist und er entscheiden muss, was er als Nächstes tun wird Ich habe das Richtungsänderungssignal an die Hit-Box angeschlossen und die Aufziehtasten Hurt Box, sodass sie umgedreht werden können Das Hurt Box-Skript hatte diese Funktion eigentlich nicht, also habe ich sie aus dem Hit Boox-Skript kopiert Die Aufziehtaste Hurt Box befindet sich jedoch hinter dem Boss, sodass ich eine exportierte Variable hinzufügen musste um die Richtung für diesen speziellen Fall umzukehren Zurück im Drehbuch der Mac-Maus brauchte ich einen Verweis auf Körper des Chefs, um ihn zum rumpeln zu bringen Das wird also in einer Variablen gespeichert, da ich es sehr häufig verwenden werde Und natürlich muss ich wissen, ob der Boss lebt oder tot ist. Ich möchte, dass mein Bosskampf mit ausgeschalteter McMuse beginnt und der Spieler die Aufziehtaste mehrmals angreift , um ihn zu starten Also habe ich eine Variable deklariert, die angibt, ob der Motor gerade gestartet ist oder nicht , sowie eine Geschwindigkeit für die Aufziehtaste, bei einem Achtel der normalen Geschwindigkeit gestartet wird, und einen Tween, mit dem ich die Geschwindigkeit im Laufe der Zeit schrittweise ändern kann die Geschwindigkeit im Laufe der Zeit schrittweise ändern Um diesen Effekt zu erzielen, habe ich die Animation der Aufziehtasten automatisch abspielen lassen, allerdings mit einer Geschwindigkeitsskala von Null und die Hurt-Box ist standardmäßig überwachbar Ich habe dann das beschädigte Signal mit meinem Boss-Skript verbunden und eine Funktion namens On Key Um sicherzustellen, dass die Verletzungsbox des Schlüssels niemals stirbt, nenne ich sie ihre Wiederherstellungsfunktion, da dies nicht die Gesundheit des Bosses widerspiegelt, sondern lediglich ein weiteres Angriffsziel für den Spielercharakter Nachdem ich die Animationsgeschwindigkeitsskala der Aufziehtasten auf das Doppelte eingestellt hatte, habe ich den Tween verwendet, um ihn im Laufe von 1 Sekunde schrittweise auf den erwarteten Wert zu reduzieren Laufe von 1 Sekunde schrittweise auf den erwarteten Wert Wenn die Engine bereits gestartet wurde, Angriff auf die Aufziehtaste dazu, dass die Mac-Maus auf den Spielercharakter zustürmt als nächste Aktion Ansonsten habe ich die Tastengeschwindigkeit verdoppelt und geprüft, ob sie einen Wert von mindestens eins erreicht hat. Bei dem Standardwert von einem Achtel passiert das erst, wenn der Aufziehschlüssel zum dritten Mal angegriffen wird. Wenn das passiert, habe ich eine Funktion aufgerufen , um den Motor der Mc-Maus zu starten. Diese Funktion weist lediglich die Zahnradanimation an, mit der Wiedergabe zu beginnen, einen Rumble-Timer zu starten , der auf eine Zwöltelsekunde eingestellt ist, sodass der Motor variabel auf True gestartet wird und das Signal ausgegeben Jede Zwölfsekunde, wenn der Timer das Timer abläuft, habe ich die Y-Position des Körpers auf eine zufällige Ganzzahl zwischen negativ und positiv verschoben zwischen negativ und positiv sodass der Körper auf und ab rumpelt Das Gesicht des Bosses nach links zu setzen war sehr ähnlich wie beim Spielercharakter, mit der Ausnahme, dass dieser Boss-Feind standardmäßig nach links schaut Damit der Boss herumfährt und auf den Spielercharakter zustürmt, habe ich viele der gleichen Bewegungsvariablen im Charakterskript verwendet , nur mit unterschiedlichen Namen, und auch das Ziel des Bosses und die Entfernung zu seinem Ziel als Floats aufgenommen , sodass ich sie verwenden kann, um zu bestimmen, wohin der Boss im physikalischen Prozess gehen muss. Ich habe auch die Schwerkraft für alle Fälle mit einbezogen und die Bewegungsgeschwindigkeit standardmäßig auf die Fahrgeschwindigkeit eingestellt die Fahrgeschwindigkeit Ich habe die Räder in einem Array gespeichert , damit ich sie einfach synchronisieren kann. Dies mag zwar für nur zwei Räder unnötig erscheinen, aber wenn Sie es auf diese Weise schreiben, funktioniert es für eine beliebige Anzahl von Rädern. Ich habe eine öffentliche Variable verwendet, um zu sagen, ob die Aufziehtaste dieser Mc-Maus angegriffen wurde und sie bereit ist, einen Ladeangriff auszuführen und eine Ganzzahl, um zu zählen , wie oft sie gegen eine Wand gestürzt Als das Boss-Encounter-Skript entscheidet, dass sich die Mc-Maus zu einer Position innerhalb der Boss-Arena bewegen soll , und die Position, zu der man sich bewegen soll, als Parameter angibt schnell zu überprüfen, ob der Boss tot ist , sodass die Anfrage ignoriert werden kann , habe ich das Ziel gespeichert , die Bewegungsrichtung und die Bewegungsgeschwindigkeit festgelegt und bewegt sich auf true. Ich habe eine private Funktion aufgerufen , um alle Räder zu animieren, warte dann auf mein eingehendes Signal, bevor ich das fertige Signal ausgestrahlt Das eingegangene Signal wird später vom physikalischen Prozess ausgegeben Das Argument, das an das Drehen der Räder übergeben wird, steuert, wie schnell sie animiert werden und ob die Animation vorwärts oder rückwärts abgespielt wird Wenn also die Mac-Maus nach links zeigt und sich nach links bewegt oder nach rechts zeigt und sich nach rechts bewegt, spiele ich die Animation mit einer Geschwindigkeit von eins Andernfalls werden bei einer Geschwindigkeit von minus Eins die Animationen rückwärts abgespielt Ein Angriff auf den Spielercharakter bewirkt im Großen und Ganzen das Gleiche Ich möchte jedoch, dass die Mc-Maus immer in die Richtung zeigt, in die sie geladen wird, und die Räder mit doppelter Geschwindigkeit durchdrehen. Mit einer kurzen Pause wird die Ladung an den Spieler telegraphiert , sodass er reagieren und ihm aus dem Weg gehen kann Da es sich bei dem Angriff um einen Angriff handelt, ist die Überwachungseigenschaft der Hitbox auf true gesetzt Nachdem die Einstellung auf true gesetzt ist, warte ich auf das Signal, das ausgegeben wird , nachdem die McMuse gegen eine Wand gekracht ist , und nutze eine weitere kurze Pause, um den Boss für einen kurzen Moment zu betäuben Denken Sie daran, das Signal im eingegebenen Bereich der Trefferboxen zu verbinden , um tatsächlich Schaden zu verursachen drehte die Räder und akzeptierte die Richtung der Drehung als Parameter. Ich wiederholte jedes Rad in meiner Radanordnung und wies jedes einzelne an, Ich wiederholte jedes Rad in meiner Radanordnung und wies jedes einzelne seine Standardanimation abzuspielen , wobei der absolute Wert von Richtung als Animationsgeschwindigkeit verwendet der absolute Wert von Richtung als wurde und ob die Richtung negativ war oder nicht, um zu bestimmen, ob die Animation rückwärts abgespielt werden sollte Ich habe auch die Emitter für Gesteins- und Staubpartikel, die an jedem Rad angebracht waren, gleichzeitig gestartet die Emitter für Gesteins- und Staubpartikel, die an jedem Rad angebracht , wenn der Richtungswert etwas anderes als Null war Andernfalls werden sie ausgeschaltet. Nun zum physikalischen Prozess , der diese beiden Aktionen ermöglicht. Wenn der Boss bereits tot ist, kann er sich nicht freiwillig bewegen, sodass seine Bewegungsrichtung auf Null gesetzt wird Dann habe ich die X-Geschwindigkeit des Bosses beschleunigt oder gebremst und die Schwerkraft auf seine Y-Geschwindigkeit angewendet , bevor ich die Bewegungs - und Gleitfunktion aufgerufen habe, um die Geschwindigkeit - und Gleitfunktion aufgerufen habe, um die des Charakters anzuwenden Wenn der Boss gerade fährt, muss ich überprüfen, ob er sein Ziel erreicht hat oder ob er gerade aufgeladen wird und gerade eine Wand berührt, dann weiß ich, dass er abgestürzt ist dann weiß ich Um zu wissen, ob der Chef sein angestrebtes Ziel erreicht hat , muss ich zunächst die Entfernung zu seinem Ziel ermitteln Das ist der absolute Wert des Ziels abzüglich der aktuellen globalen Exposition des Chefs Formel für die Sprunghöhe umkehren, können wir feststellen, ob der Endgegner nah genug am Ziel ist , um mit dem Abbremsen zu beginnen Wenn die Entfernung kleiner ist als die Geschwindigkeit Quadrat geteilt durch die Verzögerung geteilt durch zwei Wenn das wahr ist, höre ich auf, mich im Kreis zu drehen, setze die Bewegungsrichtung auf Null, ist die Fahrtrichtung falsch und gebe das eingetroffene Signal Wenn der Boss gegen eine Wand prallt, habe ich fast das Gleiche getan, aber ich habe auch die Geschwindigkeit erhöht, damit sie von der Wand weg abprallen Und die Hitbox ausgeschaltet. Ich habe auch gezählt, wie oft das passiert, und beim dritten Absturz wurde die Panzerung der Mc-Maus beschädigt, Panzerung der Mc-Maus beschädigt sodass sie in die zweite Phase übergehen kann. Wenn die Panzerung durch zu viele Stürze beschädigt wurde, habe ich die Geschwindigkeit der Aufziehtaste auf zwei erhöht Um die Panzerung zu beschädigen, musste ich lediglich den Bereich des Spriteblatts ändern, der vom Spriteknoten der Panzerung gezogen wurde der vom Spriteknoten der Panzerung gezogen Außerdem habe ich die Geschwindigkeit der Aufziehtaste und der Ausrüstungsanimationen sowie des Rumble-Timers verdoppelt Ausrüstungsanimationen sowie des , um die Boss-Szene noch instabiler zu machen die Boss-Szene noch Und ich habe die überwachbare Eigenschaft der Hurt-Box auf true gesetzt, sodass der Spielercharakter jetzt den Körper der Mc-Maus angreifen kann , um ihm Schaden zuzufügen Dann habe ich das Signal ausgegeben, um den Phasenübergang auszulösen. Um die Feuerbälle abzuschießen, brauchte ich eine vollgepackte Szene für die Feuerbälle sowie für die neuen Feuerbälle. Ich würde den Marker instanziieren, wo sie instanziiert werden sollten , plus das Fass und einen Tween, um plus das Fass Als der Boss aufgefordert wird, mehrere Feuerbälle abzufeuern, habe ich zuerst darauf gewartet, den Lauf zu verlängern, dann habe ich mehrere Male wiederholt, habe ich zuerst darauf gewartet, den Lauf zu verlängern, dann habe ich mehrere Male wiederholt, vor jedem Schuss eine Viertelsekunde Pause dann einen Feuerball abgefeuert. Nachdem ich alle Feuerbälle abgeschossen hatte, wartete ich darauf, den Lauf zurückzuziehen, bevor ich das fertige Signal aussendete . Aus- oder Einfahren des Fasses war ein einfacher Vorgang, bei dem die Fässer im Abstand von X über eine Viertelsekunde auf die gewünschte Zahl gedreht Abfeuern eines einzelnen Feuerballs ist fast das Gleiche wie mit den Projektilen des Spielercharakters es einfach als Geschwister hinzu bringen Sie es an die richtige Position und feuern Sie in die vorwärts gerichtete Richtung ich in meinem Projektilskript Wenn ich in meinem Projektilskript einer Hurt-Box anweise, Schaden zu nehmen, muss ich auch die Richtung des Schadens angeben Und wenn der Boss keine Lebenspunkte mehr hat, verwende ich Set Deferred, um die Trefferbox und beide Hurt-Boxen auszuschalten und alle Animationen zu beenden , bevor ich das farbige Signal aussende , um die Bossbegegnung zu beenden In der Szene mit dem Rauminhalt habe ich das Signal zum Starten des Motors mit der Startfunktion gegen den Endgegner und mit dem Signal zum Beenden der zweiten Begegnung verbunden Signal zum Starten des Motors mit der Startfunktion gegen den Endgegner und mit dem Signal zum Beenden der zweiten Begegnung Startfunktion gegen den Endgegner und mit dem Signal zum Beenden der Außerdem habe ich das Signal „ Panzerung beschädigt“ mit der Funktion „Phase einstellen“ verknüpft und zwei als Argument verknüpft, zwei als Argument um den Übergang zur zweiten Phase auszulösen. Ich habe den Aufruf der Startfunktion auskommentiert, sodass ich den Beginn des Kampfes nach dem Start des Motors auslösen konnte . Ja. Oh. jetzt Unser Chef führt jetzt eine komplexe Abfolge von Aktionen mit eskalierender Intensität über mehrere Phasen Unserem Spiel fehlt jedoch jegliche sinnvolle Weiterentwicklung. Wir sehen uns im nächsten Abschnitt. 65. 9-1 Punkt speichern: Hallo Freunde. In diesem Abschnitt werden wir diese Zwei-D-Plattform in ein Metroidvania verwandeln , indem wir den Fortschritt des Spielers richtig verfolgen Wir beginnen damit, unserem Spiel einen Speicherpunkt hinzuzufügen. Ich habe meine Begegnung mit dem Boss in eigenen Raum verschoben und sie an die Seite meiner Karte in eine separate Vulkanregion Außerdem habe ich einen neuen Speicherraum für meine Waldregion auf der linken Seite eingerichtet. Ich habe meinen Spielercharakter hier oben gelassen. Ich setze ihre Position einfach wieder auf den Ursprung zurück. Fangen wir mit den Speicherdaten der Spieler an, wo wir den Ort speichern müssen , an dem der Spieler sein Spiel zuletzt gespeichert hat. Wie du diese Informationen speicherst hängt von der Struktur deines Spiels ab. Aber für mein Spiel verwende ich eine Reihe von Zeichenketten. Es mag zwar effizienter sein, Speicherpunkte als Zahlen zu speichern, das ist nur eine einzige Variable, sodass die Auswirkungen vernachlässigbar sein werden Es hilft auch, die Speicherdatei für Debugging-Zwecke lesbar zu halten die Speicherdatei für Debugging-Zwecke lesbar zu Das erste Element des Arrays ist der Name der Region und das zweite ist der Name des Raums Dieses Muster folgt der Struktur meines Szenenbaums. Wenn ich die Speicherdaten der Spieler lade, muss ich nur die Region finden , die mit der ersten Zeichenfolge übereinstimmt, dann den Raum finden, der der zweiten Zeichenfolge entspricht und den Spielercharakter am Speicherpunkt in diesem Raum positionieren . Beachten Sie, dass dieser Speicherpunkt im Spiel zu dem Zeitpunkt existieren sollte im Spiel zu dem Zeitpunkt existieren dem die Speicherdaten geladen werden und noch kein Rauminhalt geladen wurde. Daher sollte sich das Speicherpunktobjekt in der Raumszene und nicht in der Rauminhaltsszene befinden. Ich füge meiner gespeicherten Raumszene einen Knoten zwei D hinzu und nenne ihn Savepoint Einfachheit halber platziere ich diesen Knoten so, dass er sich an der Position befindet, an der ich den Charakter spawnen möchte Da wir mehrere dieser Speicherpunkte in unserem Spiel haben müssen , sollte es als eigene Szene gespeichert werden Wir können es dann isoliert bearbeiten. Wie Sie Ihren Speicherpunkt aktivieren möchten, liegt ganz bei Ihnen. Ich verwende einfach ein einfaches Kollisionsereignis. Jedes Mal, wenn der Spieler einen Speicherpunkt berührt, wird sein Fortschritt gespeichert. Also füge ich der Szene einen D-Node mit zwei Bereichen hinzu und setze ihn um 96 Pixel vom Boden ab , sodass der Spieler springen muss , um ihn zu berühren. Ich habe einige Elemente für meinen Speicherpunkt importiert handelt es sich um ein Buch und auch um ein Effekt-Sprite, das ich hinter das Buch zeichne, damit es leuchtet Ich füge dem Gebietsknoten ein Sprite mit zwei D-Nodes hinzu, um zuerst den Glüheffekt zu zeichnen Dann füge ein animiertes Sprite mit zwei D für das Buch hinzu. Geben Sie ihm eine Sprite-Frames-Ressource und füllen Sie sie mit den Die Animation vorwärts und dann wieder rückwärts abspielen. Der Bereich benötigt eine Kollisionsform, also gebe ich ihm einen Kreis und verwende den Radius des Glühens , der 32 Pixel beträgt Da es sich um die Raumszene nicht um die Rauminhaltsszene handelt, muss sie vor dem Rauminhalt angeordnet werden . Es muss nach dem Körper des Spielercharakters Ausschau halten. Wenn anhängen ein Skript an den Speicherpunkt anhängen, können wir dann das vom Körper des Bereichs eingegebene Signal mit dem Skript verbinden eingegebene Signal mit dem Skript Wenn der Spielercharakter den Speicherpunkt berührt, setzen wir den Wert von last saved at in seinen Speicherdaten auf ein neues Array, wobei das erste Element des Arrays der Name der Region und das zweite Element der Name des Raums Wir können diese Namen mit dem Tag on ready automatisieren, da das übergeordnete Element des Speicherpunkts immer der Raum ist, in dem er sich befindet, und das übergeordnete Element des Raums immer die Region ist. Aufgrund der Art des Szenenbaums , bei dem Geschwister eindeutige Namen haben müssen wird sichergestellt, dass dies ausreicht, um genau zu bestimmen, in welchem Raum sie zuletzt gespeichert haben. Wir können uns auch einen Verweis auf den Animated Sprite Two D-Knoten holen und ihn anweisen, seine Animation abzuspielen , wenn das passiert Vergiss nicht, dem globalen Dateiknoten mitzuteilen, dass er das Spiel speichern soll , wann immer du etwas Dauerhaftes erstellen möchtest Wenn wir zum Game Manager-Skript wechseln, müssen wir die zuletzt gespeicherte Position des Spielers laden. Nachdem die gesamte Initialisierung abgeschlossen ist, rufen wir eine Funktion auf, um den Spielercharakter zu positionieren Wenn die Speicherdaten des Spielers den Wert „Zuletzt gespeichert am“ haben, können wir die Region anhand ihres Namens ermitteln, da wir wissen, dass sie ein untergeordnetes Element des Weltknotens ist Und dann machen Sie dasselbe, um den Raum abzurufen, in dem Wissen, dass der Raum ein untergeordnetes Element der Region ist. Wir können den Spielercharakter dann an der globalen Position des Speicherpunkts in diesem Raum positionieren. Dadurch wird der Spieler den Raum betreten, seinen Inhalt laden und erwartungsgemäß wieder einblenden. Wenn der Spieler noch keinen sicheren Punkt erreicht hat, setze ich ihn zum Ausgangspunkt, um das Spiel zu starten. Ein Problem tritt jedoch auf, wenn der Spieler stirbt, da wir den Spielercharakter auch an die Position bringen wollen, die zu diesem Zeitpunkt zuletzt gespeichert wurde . Sowohl die Death-Event-Sequenz als auch der Spieler, der einen Raum betritt , manipulieren gleichzeitig den Fade Es gibt mehrere Möglichkeiten, dieses Problem zu lösen, aber der Einfachheit halber werde ich überprüfen, ob der Spielercharakter seinem Tod den Raum wechselt Wenn sie sterben und im selben Raum wieder erscheinen, wird der Spieler, der den Raum betreten hat, nicht ausgelöst, sodass die Todessequenz das Ausblenden bewältigen kann Andernfalls ersetze ich es durch eine einfache Pause für 1 Sekunde Um zu wissen, ob die Neupositionierung des Spielercharakters den Raum verändert hat, lasse ich die Funktion einen booleschen Wert zurückgeben Und kehre zurück, ob der neue Raum mit dem aktuellen Raum identisch ist oder ob er standardmäßig falsch Lass es uns ausprobieren. Wenn ich mein Spiel zum ersten Mal lade, startet mein Charakter an der Standardposition in meinem Startraum. Wenn ich nach links gehe, finde ich den Speicherpunkt. Wenn ich zum Speicherpunkt springe, wird mein Spiel gespeichert. Wenn ich das Spiel schließe und erneut spiele, startet mein Spielercharakter jetzt am Speicherpunkt. Um meinen Speicherpunkt etwas magischer zu machen, lasse ich ihn auf und ab schweben. Ich exportiere ein paar Variablen für den Oszillationsbereich und Geschwindigkeit mit einer Standardeinstellung von 16 Pixeln und einer Schwingung pro Sekunde Das Objekt, das sich bewegen wird, ist der Area-Node, auch die Sprites als seine untergeordneten Objekte bewegt Ich muss seine anfängliche Y-Position kennen und wissen, wie viel Zeit vergangen ist die Prozessfunktion außer Kraft zu setzen, setze ich T auf sich selbst plus Delta multipliziert mit der Schwingungsgeschwindigkeit zwischen Null und Dadurch kann sich die Schwingung unendlich wiederholen , ohne jemals das Maximum einer Fließkommazahl zu ohne jemals das Maximum einer Fließkommazahl zu erreichen. Die Y-Position des Bereichs kann dann auf die Ausgangsposition plus den Sinus von T multipliziert mit dem Schwingungsbereich gesetzt Ausgangsposition plus den Sinus von T multipliziert mit dem Um den Speicherpunkt auf der Karte zu zeichnen, können wir der Speicherpunktszene einfach ein Sprite mit zwei D hinzufügen und ihr die Textur geben, die wir zeichnen möchten Skalieren Sie es sehr groß, sodass es für die Kartenkamera sichtbar ist, verstecken Sie es dann, damit es nicht im Weg ist, und fügen Sie das Kartensymbol-Skript Es muss sich auf Sichtbarkeitsebene zwei befinden, nicht auf Ebene eins, und alle seine Vorfahren im Szenenbaum müssen sowohl auf Ebene eins als auch auf Ebene zwei sichtbar sein. Ich möchte auch das Todesproblem testen, also füge ich meinem Spielercharakterskript eine einfache Eingabefunktion hinzu. Wenn ich also die Leertaste drücke, stirbt der Charakter. Wenn ich das Spiel jetzt starte, schwebt der Speicherpunkt auf und ab, und ich kann ihn auf der Karte sehen. Wenn ich die Leertaste drücke, stirbt der Charakter und reagiert am Speicherpunkt. Wenn ich in einen anderen Raum wechsle, kann ich es erneut tun und am Speicherpunkt erneut antworten. Wir haben jetzt einen Speicherpunkt , der sich die zuletzt gespeicherte Position des Spielers merkt und sie an der richtigen Position lädt. Im nächsten Video werden wir die Fähigkeit hinzufügen, Gegenstände freizuschalten , die ein Metroidvania ausmachen Wir sehen uns im nächsten Video. 66. 9-2 Metroidvania: Hallo Freunde. In diesem Video fügen wir Gegenstände hinzu, die der Spieler sammeln kann , um seine Metroidvania-Fähigkeiten freizuschalten Ich beginne damit, einen neuen Szenenordner mit dem Namen Upgrades zu erstellen einen neuen Szenenordner mit dem Namen Dann dupliziere meine gespeicherte Point-Szene, nenne sie Gem und lege sie in den neuen Upgrade-Ordner. Dann öffne es, um es zu bearbeiten. Im Gegensatz zum Speicherpunkt möchte ich nicht, dass dies auf meiner Karte dargestellt wird Deshalb lösche ich das Kartensymbol. Es ist nicht erforderlich, dass das Objekt vom Ursprung aus verschoben Deshalb setze ich die Position der Gebietsknoten zurück. Machen Sie dann den Bereich zwei zu einem D-Knoten, dem Wurzelknoten, benennen Sie ihn in GEM um und löschen Sie den alten Save-Point-Knoten zwei D. Ich ersetze die Sprite-Frames des Buchs durch neue, zeichne einen rotierenden Edelstein. Lassen Sie dann diese Animation automatisch abspielen und mit Lassen Sie dann diese Animation automatisch 12 Bildern pro Sekunde wiederholen Wir können dann ein neues Skript für unsere Upgrades anhängen. die vom Körper eingegebenen Area-2-D-Nodes wieder verbinden , können wir die neuen Fähigkeiten der Spielercharaktere freischalten , wenn sie dieses Upgrade berühren Dazu exportieren wir eine Variable vom Typ Enums-Punkt-Fähigkeiten, das zuvor erstellte Enums-Skript verweist Dadurch entsteht ein praktisches Drop-down-Menü im Inspektor, in dem wir eine unserer Fähigkeiten auswählen können, die wir für diesen Upgrade-Gegenstand Denken Sie jedoch daran, dass eine Aufzählung nur eine Ganzzahl mit einem Namen ist In meinem Spiel wird der Edelstein die Fähigkeit des Spielercharakters freischalten Fähigkeit des Spielercharakters Projektile abzuschießen Zurück im Skript können wir, wenn der Körper des Spielercharakters diesen Bereich betritt, den Wert von Datei, der Körper des Spielercharakters diesen Bereich betritt, den Wert von Datei, Punkt, Punkt „Fähigkeiten freigeschaltet“ mit dem Index „ Fähigkeit“ auf „Wahr“ setzen Punkt, Punkt „Fähigkeiten freigeschaltet“ mit dem Index „ Fähigkeit“ auf „Wahr Speichere dann das Spiel, um dieses Upgrade dauerhaft zu machen. Damit sich das wirkungsvoller anfühlt, werden wir wahrscheinlich davor und danach eine Menge ausgefallener Sachen machen wollen und diesen Knoten dann irgendwann entfernen wollen, wenn wir fertig sind Wir können sicherstellen, dass bei diesem Knoten immer nur ein einziges Kollisionsereignis eintritt indem wir set deferred verwenden, um seine Überwachungseigenschaft nach der ersten Kollision auszuschalten seine Überwachungseigenschaft nach In meiner Szene mit dem Inhalt von Speicherräumen lege ich das irgendwo hin, damit ich es testen kann A Ich wollte jedoch auf und ab schweben, wie es der Speicherpunkt tut. Anstatt den Code von einem Skript in ein anderes zu kopieren und einzufügen , sollten wir ihn zu einer Komponente machen, die jeden Node Two D angehängt werden kann, ähnlich wie die Enemy Behavior-Skripte. Zurück in der Edelstein-Szene füge ich einfach einen normalen Node hinzu und nenne ihn Float. Kopieren Sie dann den Code aus dem Save Point-Skript und fügen Sie ihn in dieses Skript ein. Anstatt eines Area-Tote-Knotens wird dies lediglich der übergeordnete Knoten des Float-Knotens sein, allerdings muss es sich um einen No-Tutti-Node oder einen Vorfahren eines No-Tutti-Nodes handeln, um eine Position zu haben Wir können diesen Knoten dann in die Save Point-Szene kopieren und den Code aus dem Save Point-Skript entfernen Diese drei Skripte sind viel besser wiederverwendbar, wenn sie nur für einen einzigen Zweck geschrieben wurden. Außerdem sind nur für einen einzigen Zweck sie leichter zu verstehen und zu debuggen Eine weitere Sache, die wir tun sollten, ist, diesen Upgrade-Gegenstand B nicht hier zu haben , wenn der Spieler diese Fähigkeit bereits freigeschaltet hat Indem wir die Bereitschaftsfunktion außer Kraft setzen, überprüfen wir den Wert der freigeschalteten Fähigkeiten in den Speicherdaten des Spielers, um zu sehen ob diese Fähigkeit bereits freigeschaltet ist , und stellen diesen Knoten in die Warteschlange, um freigegeben zu werden, falls dies der Fall ist. Lass es uns jetzt ausprobieren. Wenn ich das Spiel starte, sehe ich meinen Upgrade-Gegenstand dort schweben. Das Drücken der Taste zum Abfeuern von Projektilen funktioniert nicht, da ich diese Fähigkeit noch nicht freigeschaltet habe hochspringe, um den Upgrade-Gegenstand zu holen , verschwindet er und ich kann jetzt Projektile abschießen das Spiel schließe und erneut spiele, ist der Upgrade-Gegenstand nicht da, da ich ihn bereits gesammelt habe, und ich kann immer noch Projektile abfeuern da die Fähigkeit dauerhaft freigeschaltet war Jetzt wollen wir dafür sorgen, dass sich das Sammeln dieses Gegenstands Spieler viel wirkungsvoller anfühlt Um das zu testen, müssen wir unsere Speicherdaten löschen im Projektmenü Benutzerdatenordner öffnen aus, Wählen Sie im Projektmenü Benutzerdatenordner öffnen aus, um diesen Ordner in Ihrem Dateimanager zu öffnen, wo wir Speicherpunkte sehen und ihn löschen können. Wenn wir das Spiel jetzt starten, hat der Spieler keine zuletzt gespeicherte Position und es sind keine Fähigkeiten freigeschaltet. Ich gehe einfach zurück in den Speicherraum und klicke auf meinen Speicherpunkt. Dann schließe ich das Spiel. Wenn Sie versuchen möchten, die Ereignissequenz für das Sammeln des Objekts selbst zu erstellen , werden Sie wahrscheinlich Partikeleffekte oder andere Knoten hinzufügen wollen , um Ihr Ergebnis zu erzielen. Halte das Video hier an und dann gehen wir nochmal durch, was ich gemacht habe. Nach der Implementierung meiner Event-Sequenz sehen meine Ergebnisse wie folgt aus. Zuerst habe ich eine konstante Farbe für hellweiß erklärt. Das ist nicht nur weiß, sondern hat auch eine maximale Intensität, was bedeutet, dass auch andere Farben fast weiß erscheinen. Wenn der Spielercharakter den Gegenstand berührt, stoppe ich sofort das Auf- und Abschweben und friere den Spielercharakter indem ich die Verarbeitung deaktiviere Dann habe ich einen Partikelemitter gestartet, der die Partikel aus der Umgebung des Gegenstands emittiert und sich nach innen bewegt Dann führe den Gegenstand zur Position des Spielercharakters zur Hälfte nach oben, bis er sich in der Nähe seiner Körpermitte befindet. Gleichzeitig werden seiner Körpermitte befindet. Gleichzeitig die Farben des Gegenstands und des Charakters hellweiß getwebt Gegenstands und des Charakters hellweiß Das Hinzufügen von Parallelen zu einer Tween-Funktion bedeutet, dass diese alle gleichzeitig ablaufen , anstatt zu warten , bis eine fertig ist, bevor mit der nächsten begonnen Dann schalte ich die Fähigkeit und speichere das Spiel wie zuvor Und wenn die Fähigkeit freigeschaltet ist, blende alle visuellen Elemente aus, stoppe die nach innen gerichteten Partikel, eine nach außen gerichtete Partikelexplosion aus und aktualisiere das Sprite des Charakters, und aktualisiere das Sprite des Charakters den neuen Gegenstand enthält Nachdem ich die Farbe des Spielercharakters wieder auf normales Weiß gebracht habe, schalte ich die Verarbeitung des Spielercharakters wieder ein und entferne dieses Objekt aus dem Die nach innen gerichteten Partikel verwenden dieselben Sprites wie die Staubpartikel des Chefs Sie werden von einer Kugel mit einem Radius von 32 Pixeln emittiert . Die Partikel haben eine negative Radialgeschwindigkeit, um sie zum Mittelpunkt zu ziehen, keine Schwerkraft. Alpha krümmt sich um 1-0 und ist animiert. Nach außen gerichtete Partikel sind im Großen und Ganzen dieselben , außer dass es sich um eine Explosion mit Explosivität Emittiert von einem Punkt mit maximaler Streuung und ausreichender Dämpfung, um die ursprüngliche Geschwindigkeit aufzuheben Wir haben jetzt Sammelgegenstände in unserem Spiel, die dem Spieler neue Möglichkeiten bieten, die Welt zu erkunden Aber es würde viel mehr Spaß machen, unser Spiel zu erkunden, wenn es Abkürzungen gäbe Wir sehen uns im nächsten Video. Und 67. 9-3 Abkürzung: Freunde. In diesem Video fügen wir eine Verknüpfung hinzu, die der Spieler freischalten kann, um das Erkunden unseres Spiels reibungsloser und lohnender zu gestalten Erkunden unseres Spiels reibungsloser und lohnender Ich werde den zweiten Raum rechts neben meinem Startraum verwenden , um meine Abkürzung in der Inhaltsszene des zweiten Raums zu erstellen Ich habe den Raum in zwei separate Hälften aufgeteilt und platziere meine Abkürzung in der Mitte, sodass der Spieler diesen Raum nicht durchqueren kann, wenn er ihn von links betritt Ich beginne mit einem statischen Körper zur Kennzeichnung, um Kollisionen zu erkennen, und einem Sprite Toti-Knoten Ich verwende eine Atlas-Textur und bevölkere mein Waldgelände als Atlas Dann zeichne ich mit den drei vertikalen Kacheln eine Kollisionsform als Box hinzufüge und die Mauer mit einer Geländekollision überdecke, kann der Spieler nicht durchkommen Wir können dann mithilfe einer Atlas-Textur einen weiteren Sprite-Tutti-Knoten hinzufügen , und ich habe bereits ein neues Spritesheet für eine Holzspange importiert ein neues Spritesheet für eine Ich verwende das erste unbeschädigte Sprite und positioniere es auf Wenn der Spieler diesen Raum also von der rechten Seite betritt, kann er diese Stütze angreifen, sie beschädigen und die Mauer zerstören, um die Abkürzung zu öffnen Die Zahnspange benötigt einen Hurt Box-Bereich zwei D-Knoten und ein untergeordnetes Objekt mit Kollisionsform zwei D-Knoten Ich nehme eine andere Kastenform und lasse sie das Sprite abdecken. O. Es wäre eine gute Idee, das auf eine andere Kollisionsebene zu legen , damit wir genau kontrollieren können, was es beschädigen kann Ich verwende Ebene zwei für meine Abkürzungen. Vergessen Sie nicht, Ihre Physik-Ebenen in den Projekteinstellungen zu benennen , damit Sie sich merken können, wofür sie gedacht sind. Wir müssen dafür sorgen, dass die männliche Attack-Hitbox unserer Charaktere diese Ebene maskiert , damit sie die Klammer beschädigen können Sowie alle Projektile, die sie abschießen können. Zurück in der Rauminhaltsszene sollten wir diese Abkürzung zu einer eigenen Szene machen, da wir wahrscheinlich mehrere davon in unserem Spiel haben Diese Abkürzung wird speziell nur für die Waldregion erstellt. Also speichere ich es in diesem Ordner und muss weitere Shortcut-Szenen für meine anderen Regionen erstellen . diese Szene öffnen, können wir das Hurt-Box-Skript an den Hurt-Box-Knoten den Hurt-Box-Knoten anhängen und auch ein neues Skript für das Shortcut-Verhalten an den Stammknoten anhängen. Der Hauptzweck dieses Skripts , zu speichern, wenn diese Verknüpfung gelöscht wird , und sie beim Laden des Rauminhalts gelöscht zu lassen . Dazu verwenden wir etwas, das allgemein als Flagge bezeichnet wird , indem wir eine Zeichenkettenvariable für den Namen der Flagge exportieren . In der Rauminhaltsszene müssen wir einen Flaggennamen für diese Tastenkombination angeben. Wir können dieser Flagge einen beliebigen Namen geben, aber sie muss für jede Tastenkombination in unserem Spiel eindeutig sein. Ich nenne meine Abkürzung Forest Second Room. Wenn wir zum Datenskript wechseln, benötigen wir eine neue exportierte Variable um unsere Flaggen in einem Wörterbuch zu speichern. Wenn Sie die Zeichenfolge als Schlüssel verwenden , wird der Wert ein boolescher Wert sein Zurück im Shortcut-Skript, wenn diese Verknüpfung gelöscht ist, können wir den Wert der Punktmarkierungen für Dateidaten so setzen , dass der Schlüssel unser Flagname ist, und den Wert auf true setzen Speichere dann das Spiel, um es dauerhaft zu machen , und nachdem du einige visuelle Dinge getan hast, entferne die Verknüpfung aus dem Szenenbaum. die Ready-Funktion außer Kraft setzen, können wir den Wert unserer Flagge überprüfen um zu sehen, ob die Verknüpfung bereits zerstört wurde , und sie aus dem Szenenbaum entfernen, falls dies der Fall war Wenn die Verknüpfung jedoch noch nicht gelöscht wurde, enthält das Wörterbuch noch keinen Wert für diesen Flaggennamen Wir müssen also zuerst überprüfen, ob der Wert existiert, bevor wir versuchen, darauf zuzugreifen. Lassen Sie uns das Signal, das die Hurt-Box erhalten hat, mit der Funktion zum Zerstören von Shortcuts verbinden und das Argument entbinden Ich verlege den zweiten Raum auf die linke Seite des Speicherraums, damit ich ihn testen kann Wenn ich diesen Raum von rechts betrete, verhindert die Wand, dass mein Charakter hindurchkommt. Ich kann die Klammer angreifen, um sie zu zerstören, wodurch die Mauer zerstört wird, und ich kann sie durchqueren Wenn ich das Spiel schließe und es erneut starte, bleibt der Shortcut geöffnet Es gibt jedoch ein kleines Problem. Ich ordne meine Räume neu sodass sich der zweite Raum wieder auf der rechten Seite befindet, und lösche dann meine sichere Datei, um die Verknüpfung wiederherzustellen Ich führe das Spiel erneut aus. Die Mauer verhindert, dass mein Charakter weitermachen kann. Ich kann die Abkürzung jedoch immer noch von dieser Seite aus öffnen. Wir müssen also verhindern, dass unser Charakter durch Wände angreifen kann. die Charakterszene öffnen, können wir der Trefferbox einen Cast Two D-Node hinzufügen. Wir werden dieselbe Strategie anwenden, die wir bei feindlicher Aggression angewendet haben, um zu überprüfen, ob es eine klare Linie zwischen der Trefferbox und der Verletztenbox gibt. Dazu muss der Strahl von der Mitte des Charakters ausgehen und wir müssen alles maskieren, was diese Trefferbox treffen kann , sowie alles , was ihn behindern kann, wie Gelände, also sowohl Körper als auch Bereiche Der Strahl kann auch innerhalb einiger dieser Collider entstehen , also muss er in der Lage sein, auch Bereiche und Körper innerhalb ihrer Formen zu treffen und Körper innerhalb ihrer Formen Im Hit-Box-Skript können wir einen Verweis auf diesen gecasteten Knoten mit dem Tag on ready abrufen , aber ich ändere den Knotenpfad so, dass ich get node oder null verwende Auf diese Weise muss nicht an jede Hitbox in unserem Spiel ein Raycast angehängt Wenn es zu einer Kollision kommt, überprüfen wir zuerst, ob der Strahl existiert, weisen den Strahl dann an, auf die Verletzungsbox zu zeigen , die von der Trefferbox getroffen wurde, und erzwingen, dass sie sofort aktualisiert Wenn der Strahl auf etwas trifft und es sich dabei um etwas anderes als den Bereich handelt, bedeutet das, dass etwas anderes im Weg ist. Durch die Rücksendung wird verhindert, dass der Schaden entsteht. Wenn wir das Spiel jetzt starten, Angriff auf die Abkürzung von wird ein Angriff auf die Abkürzung von der falschen Seite durch den Walls Collider blockiert Wenn ich diesen Raum nach links bewege und ihn von rechts betrete, kann ich die Stütze angreifen und die Mauer zerstören, da der Strahl, der aus der Trefferbox des Charakters abgefeuert wird, nicht blockiert wird Wenn du willst, kannst du hier eine Pause machen und Partikeleffekte hinzufügen, schütteln und sogar mehrere Angriffe benötigen , um die Stütze zu durchbrechen, bevor du die Wand zerstörst Jetzt, wo ich meine Effekte hinzugefügt habe, sehen meine Ergebnisse wie folgt aus Nach einem Angriff gibt die Wand Staubpartikel ab, wackelt und die Stütze ist Nach einem zweiten Angriff zerfällt die Zahnspange in mehrere Teile, die Wand wird entfernt und die Partikel Um diesen Effekt zu erzielen, habe ich dem Knoten GPU-Partikel hinzugefügt die dieselben Staubpartikel emittieren wie zuvor, diesmal jedoch in Form einer Box Ich habe einen Trümmerknoten als Ordner hinzugefügt drei verschiedene Teile als starre Körper enthält. Und ein Shake-Timer, 12 Mal pro Sekunde ein Signal aussendet. das beschädigte Empfangssignal der Hurt-Box mit einer beschädigten Empfangsfunktion verbunden , Ich habe das beschädigte Empfangssignal der Hurt-Box mit einer beschädigten Empfangsfunktion verbunden, den Partikelemitter neu gestartet und dann überprüft, ob zum ersten Mal beschädigt ist Wenn die Hurt Box bereits beschädigt ist, schalte ich die Kollisionserkennung die Kollisionserkennung aus und zerstörte die Wand Andernfalls setze Damage auf true, aktualisiere die Klammer, sprite, um die beschädigte Version zu zeichnen, starte dann den Shake-Timer und stoppe ihn 1 Sekunde Das Timeout-Signal des Shake-Timers ruft diese Shake-Funktion auf, die die Wand lediglich um ein Pixel in einer zufälligen Richtung versetzt ein Pixel in einer zufälligen Als die Mauer zerstört wurde, habe ich die Speicherdaten wie zuvor aktualisiert, aber auch einige Trümmer verstreut, sowohl die Wand als auch die Stütze versteckt Warten Sie dann, bis die Partikel fertig sind, bevor Sie die gesamte Szene entfernen Um die Trümmer zu zerstreuen, habe ich sie sichtbar gemacht, dann alle Teile wieder aufgetaut und ihnen Impulskräfte hinzugefügt , ihrer Position im Verhältnis zum Elternteil entsprechen Wir haben jetzt eine Abkürzung, die der Spieler öffnen kann, was das Zurückverfolgen bei der Erkundung unserer Welt erheblich erleichtert Erkundung unserer Welt Aber die gesamte Karte ist für sie von Beginn des Spiels an deutlich sichtbar Wir sehen uns im nächsten Video. 68. 9-4 Karte: Hallo, Freunde. In diesem Video verstecken wir unsere Karte vor dem Spieler und enthüllen Räume erst, wenn der Spieler sie betritt. Ausgehend von unserem Speicherdaten-Skript können wir dieselbe Strategie wie beim Speicherpunkt anwenden , um zu verfolgen , welche Räume der Spieler betreten hat. Wir exportieren eine neue Variable mit dem Namen Map vom Typ Wörterbuch. Die Schlüssel dieses Wörterbuchs werden die Namen von Regionen sein, und die Werte werden ein anderes Wörterbuch sein. Die Schlüssel des zweiten Wörterbuchs werden die Namen der Räume in dieser Region sein, und die Werte werden boolesche Werte sein, die angeben , ob der Spieler diesen Raum betreten hat oder nicht Wenn wir in einer unserer Raumszenen nachschauen, wird die Karte von einer Art Tu-Di-Knoten gezeichnet In meinem Spiel werden sie von einem Knoten auf der Ebene „Tile Map“ gezeichnet. Was auch immer der Knoten ist, es ist ziemlich trivial, seine Sichtbarkeit umzuschalten ist ziemlich trivial, seine Sichtbarkeit Wir werden einen Verweis auf diesen Knoten in unserem Raumskript beschreiben auf diesen Knoten in unserem Raumskript Sie können das Ready-Tag verwenden, wenn der Kartenknoten für alle Räume in Ihrem gesamten Projekt einheitlich ist , oder ein Export-Tag, wenn Sie mehr Flexibilität wünschen, aber Sie müssen es jedem Raum manuell zuweisen. Außerdem muss jeder Raum den Namen der Region kennen, in der er sich befindet. Das können wir mit einem Ready-Tag automatisieren, sodass der Name des übergeordneten Knotens des Raums in der Szenenstruktur abgerufen wird. Wir können dann eine Funktion schreiben , um die Sichtbarkeit der Karte zu aktualisieren , je nachdem, ob der Spieler diesen Raum schon einmal betreten hat oder nicht. Punktdaten der Datei überprüfen, die nach dem Namen der Region indexiert dem Namen der Region erhalten wir ein weiteres Wörterbuch für die Region, das wir nach dem Namen des Raums indexieren können Dies ist ein boolescher Wert, der angibt , ob der Spieler diesen Raum schon einmal betreten hat oder nicht Und wenn es wahr ist, werden wir die Sichtbarkeit der Karte auf true setzen Sichtbarkeit der Karte auf Aber genau wie beim Flaggenwörterbuch müssen wir aufpassen, dass wir nicht versuchen, auf Wörterbucheinträge zuzugreifen , die nicht existieren. Dies bietet in diesem Fall jedoch eine zusätzliche Möglichkeit, da wir das Fehlen des Wörterbucheintrags als zusätzliche Information nutzen können . Zum Beispiel können wir überprüfen, ob das Kartenwörterbuch einen Eintrag für diese Region enthält. Wenn nicht, bedeutet das, dass der Spieler diese Region noch nie betreten hat. Wenn der Raumeingang nicht existiert, weiß der Spieler ebenfalls nicht , dass dieser Raum überhaupt existiert. Wir müssen zuerst überprüfen, ob der Regionseintrag im Kartenwörterbuch existiert. Ist dies nicht der Fall, sollte der Spieler diese Karte nicht sehen können , und wir können diese Funktion einfach verlassen. Machen Sie dann dasselbe mit dem Raumeintrag im Regionalwörterbuch. Wenn der Eintrag nicht existiert, blende ich die Karte aus. Wenn er jedoch existiert, können wir die Sichtbarkeit auf true setzen und den Wert des booleschen Werts überprüfen Wenn der boolesche Wert wahr ist, stelle ich die Map-Modulation Alpha auf volle Opazität Aber wenn es falsch ist, stelle ich es auf halbtransparent ein. Das heißt, ich kann Räume auf der Karte, von denen der Spieler weiß, von denen unterscheiden der Spieler weiß, von , die er zuvor betreten hat. Alternativ können Sie einen anderen Knoten verwenden, um diese verschiedenen Zustände zu zeichnen und die Sichtbarkeit jedes einzelnen Knotens umzuschalten Wir können die Sichtbarkeit der Karte während der Bereitschaftsfunktion initialisieren Karte während der Bereitschaftsfunktion Wir können eine weitere Funktion schreiben, um einen Raum zu entdecken und seine Karte anzuzeigen Um unsere beiden unterschiedlichen Kartenstatus zu erstellen, können wir einen booleschen Parameter akzeptieren, der angibt ob dieser Raum entdeckt wird, indem wir ihn betreten Diese Funktion muss lediglich den Wert der Datei mit den Punktdaten Punkt Map, indexiert nach dem Namen der Region, indexiert nach dem Namen des Raums, auf den Wert Entered Wenn dieser Wert jedoch bereits existiert und auf true gesetzt wurde, möchten wir ihn nicht wieder auf false setzen Wir können die logische Operation verwenden oder sie nur dann auf False setzen, wenn sie nicht bereits wahr ist. Rufen Sie dann die Funktion Sichtbarkeit der Karte aktualisieren auf, um mit dem entsprechenden Zeichnen zu beginnen. Wenn die Region noch nicht im Kartenwörterbuch existiert, ist dies der erste Raum den der Spieler in dieser Region entdeckt hat. Das wäre eine gute Gelegenheit etwas Interessantes zu tun, wie zum Beispiel eine Titelkarte vorzuzeigen oder eine kurze Szene abzuspielen , um den Spieler mit der neuen Region vertraut zu machen. Ich rufe eine Funktion namens Discover auf, die noch nicht für die Region geschrieben wurde. Dies wird für die Initialisierung des Kartenwörterbucheintrags für die Region verantwortlich sein Initialisierung des Kartenwörterbucheintrags für die Region zum Game Manager-Skript wechseln, können wir, wenn der Spielercharakter einen neuen Raum betritt, wenn der Spielercharakter einen neuen Raum betritt, diesen Raum mit einem Argument von true entdecken , um ihn undurchsichtig auf der Karte zu zeichnen In der Hauptspielszene können wir den Regionen unseres Spiels ein Skript hinzufügen Beim Schreiben der Entdeckungsfunktion wird diese aufgerufen, wenn ein Spieler zum ersten Mal einen Raum in dieser Region betritt. Wir können also damit beginnen, den Kartenwörterbucheintrag für diese Region in den Speicherdaten des Spielers zu erstellen den Kartenwörterbucheintrag für . Ich werde diese Gelegenheit auch nutzen, um die Region zur Karte des Spielers hinzuzufügen , indem ich eine Funktion zum Einblenden von Karten aufrufe. Dadurch wird einfach durch jeden Raum in dieser Region iteriert und es entdeckt, allerdings mit dem Argument falsch, sodass es halbtransparent dargestellt wird Dieses Skript muss an alle Regionen angehängt werden. In jeder meiner Regionsszenen füge ich außerdem einen Labelknoten , um den Namen dieser Region auf der Karte anzuzeigen. Damit dieser Text auf der Kartenkamera lesbar ist, muss er eine sehr große Schriftgröße haben. Ich setze die Schriftgröße auf 256. Stellen Sie dann die Schriftfarbe so ein, dass sie der Farbe der Räume entspricht. Damit es besser zur Geltung kommt, füge ich auch einen Schatten und eine Kontur hinzu. Es muss sich auf der zweiten Sichtbarkeitsebene befinden, damit die Kartenkamera es sehen kann. Ich kopiere diese Beschriftungsnotiz in meine Vulkanregion und ändere ihre Textfarbe so, dass sie dieser Region entspricht. zweiten Szene der Region eine Leinwandebene hinzufügen, können wir eine einfache Titelkarte erstellen, die angezeigt wird, wenn der Spieler die einzelnen Regionen zum ersten Mal betritt. Mit einem weiteren Label-Node werde ich den Namen dieser Region in großer Schriftgröße in der Mitte des Bildschirms anzeigen. Ich mache das standardmäßig unsichtbar und zeige es nur an, wenn der Spieler diese Region zum ersten Mal betritt. Im Regions-Skript animiere ich diese Anzeige mit einem Tween, Alphawert des Label-Nodes auf eins hochsetze, eine Sekunde warte und ihn dann wieder auf Null heruntertweene Es muss einen Alphawert von Null haben , um zu starten und sichtbar zu machen Dies kann in meine anderen Regionen kopiert und mit ihren Namen aktualisiert werden. Wenn die Region entdeckt wurde, speichere ich das Spiel und mache die Kartenbeschriftung sichtbar. Dies muss auch in der Ready-Funktion initialisiert werden , je nachdem , ob der Regionseintrag im Kartenwörterbuch existiert oder nicht im Kartenwörterbuch existiert Jetzt, wo Regionen untergeordnete Objekte haben, bei denen es sich nicht um Räume handelt, muss ich zunächst überprüfen, ob es sich bei den Kindern tatsächlich um Räume handelt, bevor ich deren Erkennungsfunktionen aufrufe . Lass es uns ausprobieren. Wenn das Spiel beginnt, betritt der Spieler automatisch die Waldregion. Also wird die Titelkarte für die Waldregion angezeigt. Die Kartendaten werden aufgedeckt, aber nur der Startraum ist undurchsichtig , da das der einzige Raum ist, den ich betreten habe Wenn ich jeden Raum betrete, wechseln die Räume von transparent zu undurchsichtig Ich habe die Abkürzung aus dem anderen Raum entfernt , um die Dinge einfacher zu machen Die Vulkanregion wurde noch nicht betreten und ist daher nicht auf der Karte sichtbar. Und wenn ich die Vulkanregion betrete, wird ihre Titelkarte angezeigt und ihre Räume werden der Karte hinzugefügt. Obwohl ich noch nichts Passendes für diese Region gebaut habe. Zurück zur Waldregion Die Region wurde bereits entdeckt, weshalb ihre Titelkarte nicht angezeigt wird. Wir verfügen jetzt über ein System , mit dem Karte unseres Spiels schrittweise angezeigt wird während der Spieler unsere Welt erkundet. Aber die Regionen unseres Spiels würden sich mit etwas Hintergrundmusik viel ausgeprägter anfühlen . Wir sehen uns im nächsten Video. 69. 9-5 Musik: Hallo Freunde. In diesem Video fügen wir Hintergrundmusik , die sich mit jeder Region in unserem Spiel ändert. Dies wird nicht nur dazu beitragen, das einzigartige Erscheinungsbild jeder Region hervorzuheben , sondern auch ein zusätzliches Gefühl des Fortschritts vermitteln. Wenn du Hintergrundmusik in dein Spielprojekt importierst, wähle die Dateien auf der Registerkarte „Dateisystem“ aus, öffne dann die Registerkarte „ Importieren“ und ändere den Loop-Modus auf „Vorwärts“. Andernfalls wird deine Musik nur einmal abgespielt und dann gestoppt. Dies erfordert einen Reimport der Assets. In jeder unserer Regionsszenen könnten wir einen Audio-Stream-Player-Knoten einrichten , um diese Musiktitel abzuspielen Aber dafür müssten wir verwalten, welcher zu einem bestimmten Zeitpunkt abgespielt wird, was ziemlich umständlich ist. Normalerweise möchten wir sowieso nicht, dass mehr als ein Hintergrundmusiktitel mehr als ein Hintergrundmusiktitel gleichzeitig abgespielt Es wäre also einfacher, nur einen Audio-Stream-Player-Knoten für das Abspielen von Hintergrundmusik zu haben , wir von überall in unserem Spiel zugreifen können. Aber jede Region muss trotzdem wissen , welche Hintergrundmusik für sie abgespielt werden soll. In unserem Regions-Skript können wir eine Variable exportieren, um die Hintergrundmusik für diese Region als Audiostream zu speichern . Füllen Sie dann die exportierte Variable für jede Region in ihren einzelnen Szenen mit unterschiedlichen Musikdateien Wir können dann ein globales Skript zur Verwaltung unserer Hintergrundmusik erstellen , vom Audio Stream Player übernommen Öffnen Sie dann die Projekteinstellungen, die Registerkarte Globals, und fügen Sie dieses Skript der Liste der globalen Knoten hinzu Um zum Skript zurückzukehren, benötigen wir eigentlich nur zwei öffentliche Funktionen, eine, die das Skript anweist, einen Musiktitel abzuspielen und den Audiostream als Parameter zu akzeptieren, und eine andere, die Musikwiedergabe zu beenden Aber plötzlich die Musik zu beenden, wäre ziemlich erschütternd. Es ist ziemlich üblich , Musik auszublenden, indem man die Lautstärke schrittweise reduziert, bevor man sie stoppt Beginnend mit der Play-Track-Funktion können wir den Stream, der gerade abgespielt wird, auf den Track-Parameter einstellen und die Wiedergabefunktion des Audio-Stream-Players aufrufen die Wiedergabefunktion des Audio-Stream-Players , um die Wiedergabe zu starten. Aber wenn bereits etwas abgespielt wird , müssen wir es zuerst beenden. Wenn dieses Skript also bereits etwas abspielt und das, was es spielt, das ist, was wir spielen möchten, können wir einfach zurückkehren. Wenn es nicht dasselbe ist, können wir warten, bis die Lautstärke wieder eingestellt ist Danach können wir zum neuen Titel wechseln und ihn wieder einblenden Um die Lautstärke schrittweise zu verringern, benötigen wir ein Tween und eine Funktion zum Tweenern der Lautstärke, endgültige Wert für die Lautstärke als Parameter akzeptiert Nachdem wir überprüft haben, ob das Tween bereits existiert, und es gelöscht haben, erstellen wir ein neues Tween und schalten die Lautstärke über einen gewissen Zeitraum auf ihren Endwert Ich brauche nur 1 Sekunde. Die Lautstärke wird normalerweise in Dezibel gemessen, was keine lineare Maßeinheit ist Es wird daher nicht empfohlen, die Lautstärke in Dezibel zu erhöhen. Stattdessen verwenden wir den linearen Lautstärkewert, bei dem es einen einfachen Gleitkommawert handelt, der zwischen Null für Stummschaltung und Eins für normale Lautstärke reicht für Stummschaltung und Eins für normale Wir können das fertige Tween-Signal zurückgeben , sodass wir darauf warten können Um die Musikwiedergabe zu beenden, müssen wir nur warten, bis die Lautstärke Null erreicht hat, dann Stop aufrufen und das fertige Signal zurückgeben Und nachdem wir zwischen den Titeln gewechselt haben, sollten wir die Lautstärke wieder auf eins reduzieren, damit wir die neue Musik hören können. Jetzt müssen wir diesem Knoten nur noch mitteilen , welcher Musiktitel wann abgespielt werden soll. Der Einfachheit halber gehe ich davon aus , dass ich beim Laden der Inhalte eines Raums die Musik abspielen möchte , die zu dieser Region gehört. also Music Play Track nenne, übergebe ich die Region, die dem Raumpunkt Music übergeordnet ist. Wenn ich aufgefordert werde, dieselbe Musik abzuspielen, die bereits abgespielt wird, ignoriert der globale Musikknoten die Anfrage einfach. Sie müssen also nicht überprüfen, was bereits abgespielt wird. Lass es uns ausprobieren. Wenn ich das Spiel starte, fange ich in der Waldregion an, und so wird das Thema Waldmusik abgespielt. Wenn ich die Räume wechsle, ändert sich die Musik nicht, solange ich noch in der Waldregion bin. Aber wenn ich zur Vulkanregion übergehe, das Thema Waldregion ausgeblendet und stattdessen wird das Thema Vulkanregion abgespielt Es wird wahrscheinlich Zeiten geben, in denen Sie einen bestimmten Musiktitel vorübergehend abspielen möchten , z. B. während einer Zwischensequenz oder eines Bosskampfs Lassen Sie uns also unserem Musikskript zwei weitere Funktionen hinzufügen. Eine, um den aktuellen Musiktitel zu überschreiben , und eine andere , um zum vorherigen Musiktitel zurückzukehren Wir benötigen eine Variable für die Hintergrundmusik der aktuellen Region Wenn wir aufgefordert werden, die Hintergrundmusik durch einen neuen Musiktitel zu überschreiben , speichern wir zunächst die Hintergrundmusik der Region in unserer Variablen. Warten Sie dann auf das Ausblenden und spielen Sie unseren neuen Titel ab. Nach Abschluss der Veranstaltung können wir zur Hintergrundmusik unserer Region zurückkehren , indem wir den alten Musiktitel ausblenden und dann abspielen In unserem Boss-Encounter-Skript können wir eine Variable exportieren, die einen speziellen Musiktitel für unsere Boss-Musik In der Boss-Begegnung mit Mc-Mouse können wir diesem Bosskampf dann einen eigenen speziellen Musiktitel geben. Der globale Musikknoten kann angewiesen werden, diese Musik abzuspielen, wenn die Bossbegegnung beginnt. Und kehrt zur Hintergrundmusik der Region zurück , wenn der Kampf vorbei ist Und schließlich sollte diesem Musikknoten mitgeteilt werden, zu welchem Bus er am Audiobus gehört , damit wir seine Lautstärke in anderen Einstellungen einfacher regeln können seine Lautstärke in anderen Einstellungen einfacher regeln also die Bereitschaftsfunktion außer Kraft setzen, können wir den Wert des Busses manuell auf Musik Wir haben jetzt ein globales Musiksystem, mit dem wir jede Musik abspielen können, die wir für unser Spiel benötigen, aber an unserer Begegnung mit dem Boss muss noch etwas gearbeitet Wir sehen uns im nächsten Video. 70. 9-6 Endlicher Boss: Hallo Freunde. In diesem Video werden wir die Boss-Begegnung mit einer Arena abschließen und verhindern, dass der Boss wieder erscheint, sobald er besiegt ist Ich habe meine Räume neu angeordnet, sodass der Spieler im Speicherraum direkt neben dem Boss-Raum beginnt den Inhalt des Boss-Raums geöffnet Ich habe den Inhalt des Boss-Raums geöffnet und die Inhaltsszene des Boss-Raums mit mehreren Parallax-Layern aufgebaut Inhaltsszene des Boss-Raums mit mehreren Parallax-Layern Damit der D-Knoten der Tile Map-Ebene zwei Parallax-Scrolling ausführen konnte , musste ich ein neues Skript erstellen, das von der Ebene „ Tile Map“ ohne Auto-Scroll übernommen Ebene „ Tile Map“ ohne Da der D-Knoten der zweiten Ebene von Tile Map nicht über die Eigenschaft „Region verwüstet“ verfügt, kann er nicht dieselbe Methode verwenden wenn wir wollten, dass er Jeder Knoten zwischen den Ebenen „Tile Map“ und „Di“ hat eine andere Bildlaufskala und moduliert mehr zur Hintergrundfarbe hin Um zu verfolgen, welche Bosse der Spieler besiegt hat, öffnen wir das Datenskript und fügen eine neue Variable mit dem Namen Boss ist Eine Alternative zur Verwendung eines Wörterbuchs ist ein Array. Jedes Mal, wenn ein Boss besiegt wird, können wir einfach seinen Namen an dieses Array anhängen Im Boss-Encounter-Skript können wir die Bereitschaftsfunktion überschreiben, um zu überprüfen, ob dieser Boss bereits besiegt wurde Wenn die Datei Punktdaten Punkt Boss ist besiegt einen Eintrag hat, der dem Namen des Bosses entspricht, dann hat der Spieler diesen Boss bereits besiegt und wir können diese Bossbegegnung entfernen. Wenn der Boss besiegt ist, können wir den Namen des Bosses an die Liste der besiegten Bosse anhängen Bosse Speichere dann das Spiel, um es dauerhaft zu machen . Im Gegensatz zu Wörterbüchern können Arrays Duplikate enthalten. Wenn Sie also Informationen auf diese Weise speichern, sollten Sie überprüfen, ob der Eintrag bereits existiert Wenn Sie zu diesem Zeitpunkt den Boss-Encounter-Knoten aus dem Szenenbaum entfernen, wird auch der Boss selbst entfernt, was ich nicht tun möchte. Aber wenn der Spieler den Raum verlässt und wieder hineinkommt, wird der Boss durch die Bereitschaftsfunktion entfernt. Das wird ausreichen, um den Endgegner zu besiegen, aber die Begegnung selbst könnte einige Verbesserungen gebrauchen. Das Erste, was ich tun möchte, wenn der Bosskampf beginnt ist, eine Tür zu schließen, die den Spieler in die Arena einsperrt. Genau wie bei der Abkürzung habe ich einen statischen Körper verwendet, um den Knoten zu entfernen denselben Wall-Sprite als Terrain wiederverwendet Und eine rechteckige Kollisionsform. Das Sprite und die Kollisionsform befinden sich jedoch weit über dem Ursprung der Tür, sodass die Tür standardmäßig geöffnet ist Wenn sie aufgefordert wird, sich zu schließen, positioniert die Tür die Kollisionsform neu zwickt dann die Position der Sprites entsprechend, und das Öffnen der Tür bringt die Kollisionsform und das Sprite wieder an ihre ursprünglichen Positionen zurück dieser Tür einen eindeutigen Namen geben, können wir sie im Encounter-Skript des Bosses schließen , wenn der Kampf beginnt, und sie öffnen, wenn der Kampf beginnt, und sie öffnen Denken Sie daran, die Funktionen der Superklasse aufzurufen, um auch alles andere in den Start- und Endfunktionen zu erledigen Ich möchte auch, dass der Boss härter kämpft , indem ich brennende Felsbrocken von der Decke fallen Also habe ich eine weitere Szene für die brennenden Felsbrocken gemacht, denen es sich um einen starren Körper mit zwei D-Knoten handelt Dadurch wird die Schwerkraft für mich automatisch geregelt. Sie werden von einem Animated Sprite Two-D-Knoten gezeichnet und animiert, der die importierten Sprites automatisch mit 12 Bildern pro Sekunde durchläuft 12 Bildern pro Sekunde Der starre Körper befindet sich auf einer neuen Kollisionsebene, die speziell für Gefahren vorgesehen ist und nichts Sie werden also mit nichts kollidieren , auch nicht mit dem Gelände Sie fallen einfach von über der Arena nach unter die Arena und es ist eine Trefferbox angebracht, die nach der Hurt-Box des Spielercharakters Ausschau hält Vergiss nicht, dich mit dem Signal des betretenen Bereichs zu verbinden , um Schaden zu verursachen. In meinem Mc-Maus-Encounter-Skript habe ich eine Variable exportiert, um diesen brennenden Felsbrocken als vollgepackte Szene zu speichern , die ich als neuen starren Körper mit brennendem Felsbrocken instanziieren kann neuen starren Körper mit brennendem Als ich aufgefordert wurde, flammende Felsbrocken zu spawnen, habe ich mehrmals zufällig eine Schleife zwischen der Phasenzahl und der Phasenzahl mal zufällig eine Schleife zwischen der Phasenzahl und der Phasenzahl zwei gemacht, sodass die Anzahl der Felsbrocken in der zweiten Phase der instanziiere einen neuen Felsbrocken, habe ihn der Szene hinzugefügt und ihn über der Arena an einer zufälligen Position zwischen der linken und rechten Wand positioniert Arena an einer zufälligen Position zwischen der linken Ich instanziiere einen neuen Felsbrocken, habe ihn der Szene hinzugefügt und ihn über der Arena an einer zufälligen Position zwischen der linken und rechten Wand positioniert. Um das Absturzereignis noch eindrucksvoller zu machen, füge ich auch Godot macht es ziemlich einfach, von überall auf die aktuelle Kamera zuzugreifen Zuerst müssen wir nur die Funktion Get Viewport aufrufen und dann die Viewports Get Camera Two D-Funktion aufrufen Wir können dann unsere Shake-Funktion aufrufen, um die Kamera zu schütteln. Ich gebe ihr für eine Viertelsekunde eine Intensität von zwei Pixeln. Ich kann dann das abgestürzte Signal der Mc-Maus mit dem Encounter-Skript verbinden , um als Reaktion darauf das Spawnen der brennenden Felsbrocken auszulösen Reaktion darauf das Spawnen der brennenden Felsbrocken Da es sich bei den Felsbrocken um starre Körper handelt, fallen sie aufgrund der Schwerkraft auf natürliche Weise herunter Dann kann ich sie, nachdem sie unter den Boden der Arena gefallen sind, mit einem Bereich von zwei D aufräumen unter den Boden der Arena gefallen sind, mit einem Bereich von . Dieser Müllsammelbereich ist nur ein rechteckiger Bereich , der den Boden der Arena abdeckt, weit genug darunter, dass alles, was in diesen Bereich gelangt , für die Kamera nicht sichtbar Der Bereichsknoten überwacht und maskiert die Gefahrenebene Sein vom Körper eingegebenes Signal stellt eine Verbindung zum MC-Mauszählerskript her zum MC-Mauszählerskript , um sie aus dem Szenenbaum zu entfernen Aufgrund der Änderungen, die an der Trefferbox unseres Charakters vorgenommen wurden die Übertragung von der Hit-Box zur Hurt-Box ungebremst sein musste, musste ich den Schlüssel Hurt Box meiner Mac-Maus neu organisieren Jetzt bestimmt die Hurt-Box die Position und die Kollisionsform befindet sich an ihrer lokalen Da der D-Node Area Two die Position selbst bestimmt, muss das Script nicht mehr auf die Kollisionsform verweisen, sondern wechselt stattdessen seine eigene Position wenn der Charakter die Richtung ändert Lass es uns ausprobieren. Ich gehe in mein Boss-Zimmer und finde meinen Boss-Feind dort sitzen. Ich kann den Schlüssel angreifen, um ihn aufzuziehen und die Boss-Begegnung zu starten. Das löst den Beginn meines Bosskampfes aus, der die Musik verändert und die Tür zur Arena zumacht, sodass ich darin gefangen bleibe Wenn ich gegen den Boss kämpfe, löst er jedes Mal, wenn er gegen eine Wand prallt, ein Wackeln der Kamera aus und es fallen brennende Felsbrocken Wir können zwar nicht sehen, was mit den brennenden Felsbrocken passiert , wenn sie unter die Kamera fallen, aber sie werden gerade von der Müllsammelstelle gereinigt Wenn der Boss in die zweite Phase eintritt , erhöht sich die Anzahl der gespawnten brennenden Felsbrocken, und wenn der Boss besiegt wird, endet die Begegnung, wodurch die Musik wieder zur Musik der Vulkanregion zurückkehrt und die Tür geöffnet Wenn Sie den Raum verlassen und zurückkommen, ist die Begegnung mit dem Boss Wir haben jetzt alles, was wir brauchen, um ein ganzes Metroidvania-Spiel zu entwickeln Im nächsten Video gehen wir auf unsere nächsten Schritte ein. Wir sehen uns im nächsten Video. 71. 9:7 Finale: Hallo Freunde. Herzlichen Glückwunsch zum Abschluss des Kurses. Du verfügst jetzt über alle Werkzeuge und Fähigkeiten, die Erstellung eines Metroidvania-Grundspiels erforderlich sind, komplett mit freischaltbaren Fähigkeiten, die dem Spieler nach und nach Zugang zu weiteren Teilen der Welt ermöglichen, um eine Karte zu erkunden, auf der der aktuelle Standort des Spielers angezeigt wird Welt ermöglichen, um eine Karte zu erkunden, auf der der aktuelle Standort des Spielers angezeigt aktuelle Standort des Spielers und Punkte zu speichern, um seinen Fortschritt zu verfolgen Jetzt müssen Sie nur noch viele der Lektionen wiederholen, die Sie im Laufe des Kurses gelernt haben , um mehr davon zu erstellen Mehr Räume, mehr Regionen mit mehr Feinden zum Bekämpfen und mehr Abkürzungen zum Freischalten. Folgen Sie diesen Schritten, um mehr aus diesem Kurs herauszuholen und weitere Fähigkeiten zu erlernen, mit denen Sie Ihr eigenes Metroidvania-Spiel erstellen können Ihr eigenes Metroidvania-Spiel erstellen Schritt eins. Wenn dies dein erstes großes Spielprojekt ist, solltest du in der Lage sein, ein Spiel nach dieser Vorlage mit mindestens drei verschiedenen Regionen zu erstellen , jede mehrere Räume mit denen jede mehrere Räume mit unterschiedlichen Gegnertypen Plattform-Herausforderungen hat, und diese Regionen sollten sich voneinander unterscheiden Gemäß den Prinzipien des Metroidvania-Spieldesigns sollte dein Spiel den Spielern Hindernisse vor Augen führen , die sie nicht überwinden können, bevor du die Fähigkeit dazu freischaltest Der kritische Weg durch das Spiel sollte eine Rückreise durch frühere Bereiche erfordern und dem Spieler mehrere neue Möglichkeiten bieten , ihn mit seinen neuen Fähigkeiten zu erkunden Versuche, ein Spiel zu entwickeln, das von Anfang bis Ende mindestens 10 Minuten dauert , ohne sich zu sehr zu wiederholen Schritt zwei: Wenn Sie mit Ihrem Spiel fertig sind und eine größere Herausforderung suchen, möchten Sie sich vielleicht etwas einfallen lassen , das Sie ändern möchten Vielleicht gefällt dir die Art und Weise nicht, wie das Wandspringen funktioniert, oder du möchtest dem Angriff des Spielercharakters Rückstoßkraft verleihen dem Angriff des Spielercharakters Versuche, eine Möglichkeit zu finden die Mechanik so anzupassen, dass sie so funktioniert , wie du es bevorzugst, und ändere die Art und Weise, wie sie im Spiel implementiert ist Versuche noch zu vermeiden, etwas völlig Neues zu machen. Konzentrieren Sie sich einfach darauf, Anpassungen an dem vorzunehmen, was bereits da ist. Schritt drei. Sobald Sie Änderungen an den bereits vorhandenen Mechaniken vornehmen können , sollten Sie im nächsten Schritt eine neue Mechanik hinzufügen , die die bereits bereitgestellten Tools verwendet Einige Dinge, die du dem Spiel vielleicht hinzufügen möchtest, könnten ein Sammelobjekt sein, das die maximale Gesundheit des Spielers erhöht, oder ein neuer Zauber, der den Spielercharakter heilt Das Hinzufügen dieser Mechaniken zum Spiel erfordert keine neuen Fähigkeiten, sondern erfordert, dass du lernst, mehrere bestehende Systeme auf neue Weise miteinander zu integrieren mehrere bestehende Systeme auf neue Weise miteinander Möglicherweise möchten Sie auch nach neuen Ressourcen suchen, die Sie für Ihre neuen Mechaniken verwenden können, oder versuchen, Ihre eigenen zu entwickeln. Schritt vier. Jetzt, da Sie bestehende Mechaniken nach Ihren Wünschen zum Laufen bringen und sie in neue Systeme integrieren können , ist es an der Zeit, eine neue Mechanik von Grund auf neu zu entwerfen und zu bauen Dies könnte eine völlig neue Metroidvania-Fähigkeit sein , die es dem Spieler ermöglicht, auf mehr Teile der Welt zuzugreifen, indem sie NPCs hinzufügt, mit denen der Spieler über ein Dialogsystem sprechen kann, Feinde dazu bringt, Geld fallen zu lassen, das der Spieler sammeln und es ihnen ermöglicht, dieses Geld in einem Geschäft auszugeben, um ihre dieses Geld in einem Geschäft auszugeben, Bevor du anfängst, solltest du dir etwas Zeit nehmen, um über all die vorhandenen Systeme nachzudenken , die mit der neuen Mechanik kommunizieren müssen mit der neuen Mechanik kommunizieren müssen Überlegen Sie, welche Teile Ihres Entwurfs abstrahiert werden sollten oder welche von vorhandenen Skripten übernommen werden können von vorhandenen Skripten übernommen Fünfter Schritt. Wenn Sie ein völlig neues System erstellen und es erfolgreich in dieses Spiel integrieren können , sollten Sie bereit sein, ein neues Spiel von Grund auf neu zu erstellen. Suchen Sie entweder online nach einem anderen Asset-Paket oder erstellen Sie Ihre eigenen Assets, denen Sie ein völlig neues Metroidvania-Spiel von Grund auf nach Ihrem eigenen Design Du kannst deine Arbeit gerne auf unserem Discord-Server teilen während du mit diesem Projekt weiter lernst und deine Fähigkeiten ausbaust Schritt sechs. Sobald dein Spiel fertig ist, kannst du es auf Plattformen wie Ich teilen, um Feedback von Spielern zu erhalten und das Spiel sogar zu verkaufen, wenn es fertig ist. Du wirst wahrscheinlich nicht viel Geld mit dem Verkauf von Spielen auf IH verdienen , aber das Feedback wird für die Verbesserung deiner Fähigkeiten in der Spieleentwicklung von unschätzbarem Wert sein für die Verbesserung deiner Fähigkeiten in der Spieleentwicklung von unschätzbarem Wert Wenn du ein Spiel hast, das auf Ich gut abgeschnitten hat, dann könntest du versuchen, es auf Steam zu verkaufen , um ein viel größeres Publikum zu erreichen Die Messlatte für die Qualität eines Spiels , das auf Steam erfolgreich ist, ist jedoch viel höher. Und Sie benötigen eine Marktstrategie, wenn Sie möchten, dass Ihr Spiel von den Spielern wahrgenommen wird. Viel Glück beim Abschluss Ihres Projekts. Ich freue mich auf Ihre Arbeit.