Die Entwurfsphilosophie von Niagara
Warum visuelle Effekte für Unreal Engine neu erfinden?
Unreal Engine erweitert seinen Nutzerkreis und wird inzwischen in vielen Branchen außerhalb der Spieleentwicklung eingesetzt. Beispiele sind:
- Architektonische Visualisierung
- Industrielles Design, wie z. B. Fahrzeugdesigns
- Virtuelle TV- und Filmproduktion
Unsere Nutzer sind so vielfältig wie nie zuvor – von Designstudenten über kleine Indie-Entwickler bis hin zu großen professionellen Studioteams sowie Einzelpersonen und Unternehmen außerhalb der Spielebranche. In Zukunft werden die Epic-Entwickler nicht mehr alles über jede Branche wissen, die Unreal Engine verwendet. Wir wollten ein System für visuelle Effekte (VFX) schaffen, das für alle unsere Nutzer in allen Branchen geeignet ist.
Unsere Ziele für ein neues VFX-System
Wir wollten ein neues System schaffen, das allen Nutzern die Flexibilität gibt, die Effekte zu erschaffen, die sie benötigen. ###Unsere Ziele für unser neues VFX-System waren:
- Es legt die volle Kontrolle in de Hände der Künstler.
- Es ist in jeder Achse programmierbar und anpassbar.
- Es bietet bessere Werkzeuge für das Debugging, die Visualisierung und die Performance.
- Es unterstützt Daten aus anderen Teilen der Unreal Engine oder aus externen Quellen.
- Es ist dem Nutzer nicht im Weg.
So erreicht Niagara unsere Ziele
Datenfreigabe
Vollständige Nutzerkontrolle beginnt mit dem Zugang zu Daten. Wir möchten, dass der Nutzer in der Lage ist, alle Daten aus jedem Teil von Unreal Engine sowie Daten aus anderen Anwendungen zu verwenden. Deshalb haben wir uns entschlossen, alles für den Nutzer offenzulegen.
Partikel-Nutzlast
Um all diese Daten dem Nutzer zugänglich zu machen, müssen wir festlegen, wie jemand diese Daten nutzen kann. Namespaces bieten Container für hierarchische Daten. Beispielsweise, enthält „Emitter.Age" Daten für einen Emitter; „Particle.Position" enthält Daten für ein Partikel. Unsere Parameter-Map ist die Nutzlast des Partikels, die alle Attribute des Partikels enthält. Dadurch wird alles optional.
Es können viele Typen von Daten hinzugefügt werden
Jeder Datentyp kann als Partikelparameter hinzugefügt werden. Du kannst komplexe Strukturen, Transformationsmatrizen oder boolesche Flags hinzufügen Du kannst diese oder jeden anderen Datentyp hinzufügen und in deiner Effektsimulation verwenden.
Kombinieren des Diagramm-Paradigmas und des Stapel-Paradigmas
Sowohl das Stapel-Paradigma (wie es in Cascade verwendet wird) als auch das Diagramm-Paradigma (wie es in Blueprints verwendet wird) haben ihre Vorteile. Stapel bieten Nutzern modulares Verhalten und Lesbarkeit. Diagramme geben den Nutzern mehr Kontrolle über das Verhalten. Unser neues Effekte-System kombiniert die Vorteile beider Paradigmen.
Hierarchie für die Hybridstruktur von Niagara
Module
Module funktionieren in einem Diagramm-Paradigma – du kannst mithilfe eines visuellen Knotendiagramms Module mit HLSL im Script-Editor erstellen. Module sprechen mit allgemeinen Daten, kapseln Verhaltensweisen und können gestapelt werden.
Emitter
Emitter arbeiten in einem Stapel-Paradigma – sie dienen als Container für Module und können zusammen gestapelt werden, um verschiedene Effekte zu erzeugen. Ein Emitter dient nur zu einem Zweck, kann aber wiederverwendet werden. Die Parameter werden von den Modulen auf die Emitterebene übertragen, aber Sie können Module und Parameter im Emitter ändern.
Systeme
Wie Emitter arbeiten Systeme in einem Stapel-Paradigma und arbeiten außerdem mit einer Sequencer-Zeitleiste – diese kannst du verwenden, um zu steuern, wie Emitter sich im System verhalten. Ein System ist Container für Emitter. Das System kombiniert diese Emitter zu einem Effekt. Wenn du ein System im Niagara-Editor bearbeitest, kannst du jeden Parameter, jedes Modul oder jeden Emitter im System modifizieren und überschreiben.
Auswahlstapel und Stapelgruppen in Niagara
Die Partikelsimulation in Niagara funktioniert konzeptionell wie ein Stapel – die Simulation fließt im Stapel von oben nach unten und führt die Module der Reihe nach aus. Wichtig dabei ist, dass jedes Modul einer Gruppe zugewiesen ist, die beschreibt, wann das Modul ausgeführt wird. Beispielsweise befinden sich Module, die Partikel initialisieren oder die agieren, wenn ein Partikel spawnt, in der Gruppe Partikel-Spawn.
Innerhalb jeder Gruppe können mehrere Bühnen vorhanden sein, die zu verschiedenen Zeitpunkten im Lebenszyklus eines Systems aufgerufen werden. Emitter, Systeme und Partikel besitzen standardmäßig die Bühnen Spawnen und Aktualisieren. Spawn-Bühnen werden im ersten Frame aufgerufen, in dem die Gruppe existiert. Beispielsweise rufen Systeme ihre Spawn-Bühne auf, wenn das System zum ersten Mal in dem Level instanziert und aktiviert wird. Partikel rufen ihre Spawn-Bühne auf, wann immer der Emitter ein Partikel emittiert und die Spawn-Anweisungen werden für jedes Partikel, das neu erstellt wird, ausgeführt. Aktualisierungs-Bühnen werden in jedem Frame aufgerufen, in dem das System, der Emitter oder das Partikel aktiv ist.
Außerdem gibt es erweiterte Bühnen wie Events und Simulations-Bühnen, die dem Spawn- und Aktualisierungsfluss hinzugefügt werden können. Events werden immer dann aufgerufen, wenn ein Partikel ein neues Event generiert und ein Emitter eingerichtet ist, der dieses Event bearbeitet. Wo es möglich ist, treten die Event-Handler-Bühnen im selben Frame auf, aber nach dem ursprünglichen Event. Simulations-Bühnen sind eine erweiterte GPU-Funktion. Diese Funktion ermöglicht es, dass mehrere Spawn- und Aktualisierungs-Bühnen nacheinander ablaufen können und ist zur Konstruktion von komplexen Strukturen wie Flüssigkeitssimulationen hilfreich.
Ein Modul ist ein Element, aber ein Element ist kein Modul. Module sind editierbare Assets, die ein Nutzer erstellen kann. Elemente beziehen sich auf Teile eines Systems oder Emitters, die der Nutzer nicht erstellen kann. Beispiele für Elemente sind Systemeigenschaften, Emittereigenschaften und Renderer.
Bühnen, Gruppen, Namespaces und Datenkapselung
Durch das Hinzufügen jedes Moduls zu einer Bühne (Aktualisierung, Spawn, Event oder Simulation) in einer Gruppe (System, Emitter oder Partikel) kannst du steuern, wann ein Modul ausgeführt wird und mit welchen Daten ein Modul arbeitet. Stapelgruppen sind Namespaces zugeordnet, die definieren, welche Daten die Module in dieser Gruppe lesen oder schreiben können.
Beispielsweise können Module, die in der Gruppe System ausgeführt werden, Parameter im Namespace „System" lesen und schreiben, können aber Parameter, die zu den Namespaces „Engine" oder „Nutzer" gehören, nur lesen. Wenn die Ausführung den Stapel von der Gruppe „System" zur Gruppe „Emitter" hinuntergeht, können die in der Gruppe Emitter ausgeführten Module die Parameter im Namespace „Emitter" lesen und schreiben, aber die Parameter in den Namespaces „System", „Engine" und „Nutzer" nur lesen. Module in der Gruppe Partikel können die Parameter in den Namespaces „System" und „Emitter" nur lesen.
Da Module in den Emitter-Gruppen Parameter aus dem Namensraum „System" lesen können, kann eine Simulation, die für alle Emitter relevant ist, einmal von Modulen in der Gruppe „System" durchgeführt werden, und die Ergebnisse davon (gespeichert im Namensraum „System") können von den Modulen der Gruppe „Emitter" in jedem einzelnen Emitter ausgelesen werden. Dies wird mit den Modulen der Gruppe „Partikel" fortgesetzt, die die Parameter in den Namespaces „System" und „Emitter" lesen können. In der nachfolgenden Tabelle findest du eine kurzgefasste Darstellung dieser Beziehungen.
| Modulgruppe | Liest vom Namespace | Schreibt in den Namespace |
|---|---|---|
| System | System, Engine, Nutzer | System |
| Emitter | System, Emitter, Engine, Nutzer | Emitter |
| Partikel | System, Emitter, Partikel, Engine, Nutzer | Partikel |