Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Game Art Effects

Wie generiert man schockierend gute 2D-Blitz-Effekte in Unity? (JavaScript)

by
Read Time:35 minsLanguages:

German (Deutsch) translation by Władysław Łucyszyn (you can also view the original English article)

Es gibt viele Einsatzmöglichkeiten für Blitzeffekte in Spielen, von der Hintergrundatmosphäre während eines Sturms bis hin zu den verheerenden Blitzangriffen eines Zauberers. In diesem Tutorial erkläre ich, wie Sie programmgesteuert fantastische 2D-Blitzeffekte erzeugen: Schrauben, Zweige und sogar Text.

Dieses Tutorial wurde speziell für Unity geschrieben, mit allen Code-Snippets in JavaScript. Das gleiche Tutorial ist auch mit C#-Code verfügbar. Wenn Sie Unity nicht verwenden, sehen Sie sich diese plattformunabhängige Version desselben Tutorials an. Es wurde für XNA geschrieben, aber Sie sollten in der Lage sein, dieselben Techniken und Konzepte in jeder Gamedev-Engine und -Plattform zu verwenden.

Demo

Sehen Sie sich die Demo unten an:

Klicken Sie auf das Unity-Objekt und verwenden Sie dann die Zifferntasten, um zwischen den Demos zu wechseln. Bei einigen Demos müssen Sie auf eine oder zwei Stellen klicken, um sie zu aktivieren.

Grundeinstellung

Um zu beginnen, müssen Sie ein neues 2D-Projekt in Unity erstellen. Benennen Sie es, wie Sie möchten. Erstellen Sie in Unity vier Ordner: Materials, Prefabs, Scripts und Sprites.

Klicken Sie als Nächstes auf die Hauptkamera und stellen Sie sicher, dass ihre Projektion auf Orthographic eingestellt ist. Stellen Sie die Größe der Kamera auf 10 ein.

Klicken Sie mit der rechten Maustaste auf den Ordner Materialien und wählen Sie Erstellen > Material. Benennen Sie es in Additive um. Wählen Sie dieses Material aus und ändern Sie seinen Shader in Partikel > Additiv. Dies wird Ihrem Blitz helfen, später zu "knallen".

Schritt 1: Zeichnen Sie eine leuchtende Linie

Der Grundbaustein, aus dem wir Blitze machen müssen, ist ein Liniensegment. Öffnen Sie zunächst Ihre bevorzugte Bildbearbeitungssoftware und zeichnen Sie eine gerade Blitzlinie mit einem Leuchteffekt. So sieht meiner aus:

Wir möchten Linien unterschiedlicher Länge zeichnen, also schneiden wir das Liniensegment wie unten gezeigt in drei Teile (schneiden Sie Ihr Bild nach Bedarf zu). Dies ermöglicht es uns, das mittlere Segment auf jede gewünschte Länge zu dehnen. Da wir das mittlere Segment strecken werden, können wir es als nur ein einzelnes Pixel dick speichern. Da das linke und das rechte Stück Spiegelbilder voneinander sind, müssen wir nur eines davon speichern; Wir können es im Code umdrehen.

Ziehen Sie Ihre Bilddateien in den Sprites-Ordner im Projekt-Fenster. Dadurch werden die Bilddateien in das Unity-Projekt importiert. Klicken Sie auf die Sprites, um sie im Inspektorfenster anzuzeigen. Stellen Sie sicher, dass der Texturtyp auf Sprite(2D \ uGUI) eingestellt ist, und stellen Sie das Pack-Tag auf Line ein.

Das Packing Tag hilft Unity, beim Zeichnen unseres Lightnings bei Draw-Aufrufen zu sparen, also stellen Sie sicher, dass Sie beiden Sprites das gleiche Packing Tag geben, sonst wird die Leistung nicht verbessert.

Lassen Sie uns nun eine neue Klasse für das Zeichnen von Liniensegmenten deklarieren:

A und B sind die Endpunkte der Linie. Durch Skalieren und Drehen der Teile der Linie können wir eine Linie beliebiger Dicke, Länge und Ausrichtung zeichnen.

Fügen Sie die folgende Draw()-Methode am Ende der LineJS-Klasse hinzu:

Die Art und Weise, wie wir das mittlere Segment und die Kappen positionieren, werden sie beim Zeichnen nahtlos verbinden. Die Startkappe wird an Punkt A positioniert, das mittlere Segment wird auf die gewünschte Breite gestreckt und die Endkappe wird um 180° gedreht und an Punkt B gezeichnet.

Jetzt müssen wir ein Prefab erstellen, mit dem unsere LineJS-Klasse arbeiten kann. Wählen Sie in Unity im Menü GameObject > Leer erstellen. Das Objekt wird in Ihrem Hierarchie-Bereich angezeigt. Benennen Sie es in LineJS um und ziehen Sie Ihr LineJS-Skript darauf. Es sollte in etwa wie das Bild unten aussehen.

Wir verwenden dieses Objekt als Container für die Teile unseres Liniensegments.

Jetzt müssen wir Objekte für die Teile unseres Liniensegments erstellen. Erstellen Sie drei Sprites, indem Sie GameObject > Create Other > Sprite aus dem Menü auswählen. Benennen Sie sie in StartCap, MiddleSegment und EndCap um. Ziehen Sie sie auf unser LineJS-Objekt, sodass sie zu seinen Kindern werden – dies sollte ungefähr wie in der Abbildung unten aussehen.

Gehen Sie jedes Kind durch und stellen Sie sein Material im Sprite-Renderer auf das zuvor erstellte Additiv-Material ein. Weisen Sie jedem Kind das entsprechende Sprite zu. (Die beiden Caps sollten das Cap-Sprite erhalten und das mittlere Segment sollte das Line-Sprite erhalten.)

Klicken Sie auf das LineJS-Objekt, damit Sie das Skript im Inspektor-Fenster sehen können. Weisen Sie die Kinder den entsprechenden Slots zu und ziehen Sie dann das LineJS-Objekt in den Prefabs-Ordner, um ein Prefab dafür zu erstellen. Sie können das LineJS-Objekt jetzt aus dem Hierarchiebereich löschen.

Schritt 2: Erstellen Sie gezackte Linien

Blitze neigen dazu, gezackte Linien zu bilden, daher benötigen wir einen Algorithmus, um diese zu generieren. Wir werden dies tun, indem wir zufällig Punkte entlang einer Linie auswählen und sie um einen zufälligen Abstand von der Linie verschieben.

Die Verwendung einer völlig zufälligen Verschiebung führt dazu, dass die Linie zu gezackt wird. Daher glätten wir die Ergebnisse, indem wir begrenzen, wie weit benachbarte Punkte voneinander verschoben werden können – siehe den Unterschied zwischen der zweiten und dritten Linie in der Abbildung unten.

Wir glätten die Linie, indem wir Punkte mit einem ähnlichen Versatz zum vorherigen Punkt platzieren; Dadurch kann die Linie als Ganzes auf und ab wandern, während verhindert wird, dass irgendein Teil davon zu gezackt wird.

Lassen Sie uns eine LightningBoltJS-Klasse erstellen, um das Erstellen unserer gezackten Linien zu verarbeiten.

Der Code sieht vielleicht etwas einschüchternd aus, ist aber nicht so schlimm, wenn Sie die Logik verstanden haben. Bevor wir fortfahren, sollten Sie verstehen, dass wir uns entschieden haben, unsere Liniensegmente in den Bolzen zu bündeln (da das ständige Instanziieren und Zerstören von Objekten in Unity kostspielig sein kann).

  • Die Funktion Initialize() wird für jeden Blitz einmal aufgerufen und bestimmt, wie viele Liniensegmente jeder Blitz verwenden darf.
  • Die Funktion activateLine() aktiviert ein Liniensegment mit den gegebenen Positionsdaten.
  • Die Funktion DeactivateSegments() deaktiviert alle aktiven Liniensegmente in unserer Schraube.
  • Die Funktion ActivateBolt() übernimmt die Erstellung unserer gezackten Linien und ruft die Funktion activateLine() auf, um unsere Liniensegmente an den entsprechenden Positionen zu aktivieren.

Um unsere gezackten Linien zu erstellen, berechnen wir zunächst die Steigung zwischen unseren beiden Punkten sowie den Normalenvektor zu dieser Steigung. Wir wählen dann eine Reihe von zufälligen Positionen entlang der Linie und speichern sie in unserer Positionsliste. Wir skalieren diese Positionen zwischen 0 und 1, sodass 0 den Anfang der Linie und 1 den Endpunkt darstellt. Dann sortieren wir diese Positionen, damit wir einfach Liniensegmente dazwischen einfügen können.

Die Schleife durchläuft die zufällig ausgewählten Punkte und verschiebt sie um einen zufälligen Betrag entlang der Normalen. Der scale-Faktor dient dazu, zu scharfe Winkel zu vermeiden, und die envelope stellt sicher, dass der Blitz tatsächlich zum Zielpunkt geht, indem sie die Verschiebung begrenzt, wenn wir uns dem Ende nähern. Die spread soll dabei helfen, zu kontrollieren, wie weit die Segmente von der Steigung unserer Linie abweichen; ein spread von 0 ergibt im Wesentlichen eine gerade Linie.

Also, wie wir es mit unserer LineJS-Klasse gemacht haben, machen wir daraus ein Prefab. Wählen Sie im Menü GameObject > Leer erstellen. Das Objekt wird in Ihrem Hierarchiebereich angezeigt. Benennen Sie es in BoltJS um und ziehen Sie eine Kopie des LightningBoltJS-Skripts darauf. Klicken Sie abschließend auf das BoltJS-Objekt und weisen Sie das LineJS-Prefab aus dem Prefabs-Ordner dem entsprechenden Slot im LightningBoltJS-Skript zu. Wenn Sie damit fertig sind, ziehen Sie einfach das BoltJS-Objekt in den Prefabs-Ordner, um ein Prefab zu erstellen.

Schritt 3: Animation hinzufügen

Blitze sollten hell aufblitzen und dann ausblenden. Dafür sind unsere Funktionen Update() und Draw() in LightningBoltJS da. Durch Aufrufen von Update() wird die Schraube ausgeblendet. Der Aufruf von Draw() aktualisiert die Farbe der Schraube auf dem Bildschirm. IsComplete() teilt Ihnen mit, wenn der Bolzen vollständig ausgeblendet ist.

Schritt 4: Erstellen Sie eine Schraube

Nun, da wir unsere LightningBoltJS-Klasse haben, wollen wir sie tatsächlich sinnvoll nutzen und eine schnelle Demo-Szene einrichten.

Wir werden für diese Demo einen Objektpool verwenden, also möchten wir ein leeres Objekt erstellen, um unsere aktiven und inaktiven Schrauben aufzunehmen (einfach aus organisatorischen Gründen). Wählen Sie in Unity im Menü GameObject > Leer erstellen. Das Objekt wird in Ihrem Hierarchie-Bereich angezeigt. Benennen Sie es in LightningPoolHolder um.

Klicken Sie mit der rechten Maustaste auf den Ordner Scripts und wählen Sie Erstellen > Javascript. Benennen Sie Ihr Skript DemoScriptJS und öffnen Sie es. Hier ist ein kurzer Code, um Ihnen den Einstieg zu erleichtern:

Dieser Code bietet uns lediglich die Möglichkeit, Schrauben mithilfe von Objektpooling zu erstellen. Es gibt andere Möglichkeiten, dies einzurichten, aber hiermit gehen wir vor! Sobald wir es eingerichtet haben, müssen Sie nur noch zweimal klicken, um eine Schraube auf dem Bildschirm zu erstellen: einmal für die Startposition und einmal für die Endposition.

Wir benötigen ein Objekt, um unser DemoScriptJS anzulegen. Wählen Sie im Menü GameObject > Leer erstellen. Das Objekt wird in Ihrem Hierarchiebereich angezeigt. Benennen Sie es in DemoScript um und ziehen Sie Ihr DemoScriptJS-Skript darauf. Klicken Sie auf das DemoScript-Objekt, damit wir es im Inspektorfenster anzeigen können. Weisen Sie das BoltJS-Prefab aus dem Prefabs-Ordner dem passenden Slot in DemoScriptJS zu.

Das sollte reichen, um dich in Schwung zu bringen! Führen Sie die Szene in Unity aus und probieren Sie es aus!

Schritt 5: Branch Lightning erstellen

Sie können die LightningBoltJS-Klasse als Baustein verwenden, um interessantere Blitzeffekte zu erstellen. Sie können die Schrauben beispielsweise wie unten gezeigt verzweigen:

Um den Blitz zu verzweigen, wählen wir zufällige Punkte entlang des Blitzes und fügen neue Bolzen hinzu, die von diesen Punkten abzweigen. Im folgenden Code erstellen wir zwischen drei und sechs Zweige, die sich in einem Winkel von 30° vom Hauptbolzen trennen.

Dieser Code funktioniert sehr ähnlich wie unsere LightningBoltJS-Klasse, mit der Ausnahme, dass er kein Objektpooling verwendet. Der Aufruf von Initialize() ist alles, was Sie tun müssen, um einen Verzweigungsbolzen zu erstellen; Danach müssen Sie nur noch Update() und Draw() aufrufen. Wie das genau geht, zeige ich Ihnen später in unserem DemoScriptJS im Tutorial.

Möglicherweise haben Sie den Verweis auf eine GetPoint()-Funktion in der LightningBoltJS-Klasse bemerkt. Wir haben diese Funktion noch nicht wirklich implementiert, also kümmern wir uns jetzt darum.

Fügen Sie unten in der LightningBoltJS-Klasse die folgende Funktion hinzu:

Schritt 6: Blitztext erstellen

Unten ist ein Video eines anderen Effekts, den Sie aus den Blitzen machen können:

Dafür müssen wir noch etwas mehr einrichten. Wählen Sie zunächst im Projektfenster Erstellen > RenderTexture aus. Benennen Sie es in RenderText um und setzen Sie seine Größe auf 256x256px. (Es muss nicht unbedingt die genaue Größe haben, aber je kleiner es ist, desto schneller wird das Programm ausgeführt.)

Wählen Sie im Menü Bearbeiten > Projekteinstellungen > Tags und Ebenen. Erweitern Sie dann im Inspektor-Bedienfeld das Dropdown-Menü Ebenen und fügen Sie Text zur Benutzerebene 8 hinzu.

Wir müssen dann eine zweite Kamera erstellen. Wählen Sie im Menü GameObject > Andere erstellen > Kamera. Benennen Sie es in TextCamera um und setzen Sie seine Projektion auf Orthographic und seine Clear Flags auf Solid Color. Stellen Sie die Hintergrundfarbe auf (R: 0, G: 0, B: 0, A: 0) und die Culling-Maske auf nur Text (die Ebene, die wir gerade erstellt haben). Setzen Sie schließlich die Zieltextur auf RenderText (die zuvor erstellte RenderTexture). Wahrscheinlich müssen Sie später mit der Größe der Kamera herumspielen, damit alles auf den Bildschirm passt.

Jetzt müssen wir den eigentlichen Text erstellen, den wir mit unserem Blitz zeichnen werden. Wählen Sie im Menü GameObject > Andere erstellen > GUI-Text. Wählen Sie das GUI-Textobjekt aus dem Hierarchie-Bedienfeld aus und stellen Sie seinen Text auf LIGHTNING, seinen Anker auf die middle center und seine Ausrichtung auf die center ein. Setzen Sie dann seine Ebene auf die Text-Ebene, die wir zuvor erstellt haben. Sie müssen wahrscheinlich mit der Schriftgröße herumspielen, damit der Text auf den Bildschirm passt.

Wählen Sie nun die Hauptkamera aus und stellen Sie ihre Culling-Maske so ein, dass sie alles außer unserer Textebene ist. Dies führt dazu, dass unser GUI-Text scheinbar vom Bildschirm verschwindet, aber er sollte auf der zuvor erstellten RenderTexture gezeichnet werden: Wählen Sie RenderText aus dem Projekt-Fenster und Sie sollten das Wort LIGHTNING in der Vorschau am unteren Rand des Bedienfelds sehen können .

Wenn Sie das Wort LIGHTNING nicht sehen können, müssen Sie mit Ihrer Positionierung, Schriftgröße und (Text-)Kameragröße herumspielen. Um Ihnen bei der Positionierung Ihres Textes zu helfen, klicken Sie im Hierarchie-Bedienfeld auf TextCamera und setzen Sie die Zieltextur auf None. Sie können jetzt Ihren GUI-Text sehen, wenn Sie ihn auf der TextCamera zentrieren. Sobald Sie alles positioniert haben, setzen Sie die Zieltextur der TextCamera wieder auf RenderText.

Nun zum Code! Wir müssen die Pixel aus dem Text abrufen, den wir zeichnen. Wir können dies tun, indem wir unseren Text auf ein RenderTarget zeichnen und die Pixeldaten mit Texture2D.ReadPixels() in Texture2D zurücklesen. Dann können wir die Koordinaten der Pixel aus dem Text als List.<Vector2> speichern.

Hier ist der Code, um das zu tun:

Hinweis: Wir müssen diese Funktion beim Start unseres Programms als Coroutine ausführen, damit sie korrekt ausgeführt wird.

Danach können wir in jedem Frame zufällig Paare dieser Punkte auswählen und einen Blitz zwischen ihnen erstellen. Wir wollen es so gestalten, dass je näher zwei Punkte beieinander liegen, desto größer ist die Chance, dass wir einen Bolzen zwischen ihnen erzeugen.

Es gibt eine einfache Technik, die wir verwenden können, um dies zu erreichen: Wir wählen den ersten Punkt nach dem Zufallsprinzip aus, und dann wählen wir eine feste Anzahl anderer Punkte nach dem Zufallsprinzip und wählen den nächsten.

Hier ist der Code dafür (wir werden ihn später zu unserem DemoScriptJS hinzufügen):

Die Anzahl der getesteten Kandidatenpunkte beeinflusst das Aussehen des Blitztextes. Wenn wir eine größere Anzahl von Punkten überprüfen, können wir sehr nahe Punkte finden, zwischen denen Bolzen gezogen werden können, wodurch der Text sehr sauber und lesbar wird, jedoch mit weniger langen Blitzen zwischen den Buchstaben. Kleinere Zahlen lassen den Blitztext wilder aussehen, aber weniger lesbar.

Schritt 7: Probieren Sie andere Variationen aus

Wir haben die Erstellung von Branch Lightning und Lightning Text besprochen, aber das sind sicherlich nicht die einzigen Effekte, die Sie erzielen können. Schauen wir uns ein paar andere Variationen von Blitzen an, die Sie möglicherweise verwenden möchten.

Beweglicher Blitz

Vielleicht möchten Sie oft einen beweglichen Blitz machen. Sie können dies tun, indem Sie jedem Rahmen eine neue kurze Schraube am Endpunkt der Schraube des vorherigen Rahmens hinzufügen.

Blitzschlag

Diese Variante bietet einen dramatischen Effekt, der Blitze in einem Kreis aus dem Mittelpunkt schießt:

Schritt 8: Fügen Sie alles in DemoScriptJS zusammen

Sie möchten all diese ausgefallenen Effekte, die wir bisher erstellt haben, ausprobieren können, also fügen wir sie alle in das DemoScriptJS ein, das wir zuvor erstellt haben. Sie können zwischen den Effekten wechseln, indem Sie die Zifferntasten auf Ihrer Tastatur drücken, um den Effekt auszuwählen, und dann einfach zweimal klicken, wie wir es mit unseren Schrauben zuvor getan haben.

Hier ist der vollständige Code:

Abschluss

Blitz ist ein großartiger Spezialeffekt, um Ihre Spiele aufzupeppen. Die in diesem Tutorial beschriebenen Effekte sind ein guter Ausgangspunkt, aber es ist sicherlich nicht alles, was Sie mit Blitz machen können. Mit etwas Fantasie können Sie alle Arten von beeindruckenden Blitzeffekten erstellen! Laden Sie den Quellcode herunter und experimentieren Sie selbst.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.