Niagara is Unreal Engine's next-generation VFX system. With Niagara, the technical artist has the ability to create additional functionality on their own, without the assistance of a programmer. The system is adaptable and flexible. Beginners can start out by modifying templates or behavior examples, and advanced users can create their own custom modules.
Core Niagara Components
In the Niagara VFX system, there are four core components:
- Systems
- Emitters
- Modules
- Parameters
Systems
A Niagara system is a container for everything you will need to build that effect. Inside that system, you may have different building blocks that stack up to help you produce the overall effect.
You can modify some system-level behaviors that will then apply to everything in that effect.
The Timeline panel in the System Editor shows which emitters are contained in the system, and can be used to manage those emitters.
Emitters
Emitters are where particles are generated in a Niagara system. An emitter controls how particles are born, what happens to that particles as they age, and how the particles look and behave.
The emitter is organized in a stack. Inside that stack is several groups, inside which you can put modules that accomplish individual tasks. The groups are as follows.
-
Emitter Spawn
This group defines what happns when an emitter is first created on the CPU. Use this group to define initial setups and defaults.
-
Emitter Update
This group defines emitter-level modules that occur every frame on the CPU. Use this group to define spawning of particles when you want them to continue spawning on every frame.
-
Particle Spawn
This group is called once per particle, when that particle is first born. This is where you will want to define the initialization details of the particles, such as the location where they are born, what color they are, their size, and more.
-
Particle Update
This group is called per particle on each frame. You will want to define here anything that needs to change frame-by-frame as the particles age. For example, if the color of the particles is changing over time. Or, if the particles are affected by forces like gravity, curl noise, or point attraction. You may even want the particles to change size over time.
-
Event Handler
In the Event Handler group, you can create Generate events in one or more emitters that define certain data. Then you can create Listening events in other emitters which trigger a behavior in reaction to that generated event.
-
Render
The last group is the Render group. This is where you define the display of the particle and set up one or more renderers for your particles. You may want to use a Mesh renderer if you want to define a 3D model as the basis of your particles, upon which you could apply a material. Or, you may want to use a sprite renderer and define your particles as 2D sprites. There are many different renderers to choose from and experiment with.
Modules
Modules are the basic building blocks of effects in Niagara. You add modules to groups to make a stack. Modules are processed sequentially from top to bottom.
You can think of a module as a container for doing some math. You pass some data into the module, then inside the module you do some math on that data, and then you write that data back out at the end of the module.
Modules are built using High-Level Shading Language (HLSL), but can be built visually in a Graph using nodes. You can create functions, include inputs, or write to a value or parameter map. You can even write HLSL code inline, using the CustomHLSL node in the Graph.
You can double-click any module from an emitter in Niagara to take a look at the math that's happening inside. You can even copy and create your own modules. For example, if you double-click on the Add Velocity module to take a look inside, you can inspect the data flow.
The script starts by retrieving inputs - the velocity input and the coordinate space. It then gets the current velocity of the particles, as well as an inputted scaling factor. Then, the input velocity is scaled, transformed in the correct coordinate space, and added to the current velocity of the particles. Once that work is complete, the new particle velocity is written back out so that any modules that need velocity information further on down the stack can retrieve it.
All modules are built with that basic methodology, though for some the internal math may be more complex.
Parameters and Parameter Types
Parameters are an abstraction of data in a Niagara simulation. Parameter types are assigned to a parameter to define the data that parameter represents. There are four types of parameters:
- Primitive: This type of parameter defines numeric data of varying precision and channel widths.
- Enum: This type of parameter defines a fixed set of named values, and assumes one of the named values.
- Struct: This type of parameter defines a combined set of Primitive and Enum types.
- Data Interfaces: This type of parameter defines functions that provide data from external data sources. This can be data from other parts of UE4, or data from an outside application.
You can add a custom parameter module to an emitter by clicking the Plus sign icon (+) and selecting Set new or existing parameter directly. This adds a Set Parameter module to the stack. Click the Plus sign icon (+) on the Set Parameter module and select Add Parameter to set an existing parameter, or Create New Parameter to set a new parameter.
Templates, Wizards, and Behavior Examples
When you first create a Niagara emitter or Niagara system, a dialog displays offering several options for what kind of emitter or system you want to create.
You can change any of the parameters in the template. You can add, modify or delete any of the modules. In a system template, you can also add, modify or delete any of the emitters. Templates are just there to jumpstart your creativity and give you something that you can work with immediately.
System Wizard
To create a new Niagara system, right-click in the Content Browser and locate FX > Niagara System.
The System Wizard offers the following options for creating a new system:
- New system from selected emitters: If you select this option and click Next, a list of available emitters displays. This list includes both existing emitters in your project and template emitters. Select the emitters you want to include in the new system, and click the green Plus sign icon (+) to add them. Then click Finish to create the system. If you choose an existing emitter, the system will inherit from those emitters. If you choose a template emitter, the system will have no inheritances. Also, the template emitter is an instance that can either be strictly local to that system, or you can save it as a separate emitter asset.
- New system from a template or behavior example: If you select this option and click Next, you can choose from a list of templates or behavior examples that represent several commonly used effect systems. As with emitter templates, this list can be curated by art leads or creative directors. If you are new to UE, this option will give you an example of how FX systems are built in Niagara. Behavior Examples are simple examples designed to feature one, isolated aspect of the Niagara system you can examine to help demystify that behavior.
- Copy existing system: If you select this option and click Next, a list of existing systems displays. Choose one of them to copy, then click Finish.
- Create empty system: If you select this option, your system contains no emitters or emitter templates. This option is useful if you want to create a system that is totally different from your other systems.
Emitter Wizard
To create a new emitter, right-click in the Content Browser and select FX > Niagara Emitter.
The Emitter Wizard offers the following options for creating a new emitter:
- New emitter from a template: If you select this option, you can choose from a list of templates that present several types of commonly used effects. In a large development studio, art leads or creative directors can curate the list of templates, ensuring that the company's best practices are baked into the templates. These templates also offer a great starting place if you are new to UE.
- Inherit from an existing emitter: If you select this option, you can create a new emitter that inherits properties from an existing emitter. This option makes the new emitter a child of the existing emitter you selected. If you need many emitters that all have certain properties in common, this is a good option to choose. You can make changes to the parent emitter, and all child emitters will reflect those changes. Select from a parent emitter to use this option.
- Copy existing emitter: If you select this option, you can create a new emitter that is a copy of an emitter you already created. This can be useful if you need to create several similar emitters. Click Next after selecting this option, and a list of available emitters displays. You can then choose which one you want to copy.
Niagara VFX Workflow
Create Systems
First create a Niagara System in which you can add one or more emitters. You can then set up the properties of each emitter.
Create or Add Emitters
In the Niagara Editor, you can adjust your emitter by changing the properties of the modules already in it, or add new modules for the desired effect. You can also copy emitters and add multiple emitters into a single Niagara system. For an example of this, see the Sparks tutorial.
Create or Add Modules
In your emitter, you can add existing modules from Niagara by clicking on the Plus (+) of the group where you want to add the module. Niagara comes with a lot of pre-existing modules, and for the majority of circumstances you will be able to create your effects without needing to do any custom module design.
However, if you want to create your own modules, it can be helpful to understand how the data flows through a module.
- Modules accumulate to a temporary namespace, then you can stack more modules together. As long as they contribute to the same attribute, the modules will stack and accumulate properly.
- When writing a module, there are many functions available for you to use:
- Boolean operators
- Math expressions
- Trigonometry expressions
- Customized functions
- Nodes that make boilerplate functions easier
- Once you create a module, anyone else can use it.
- Modules all use HLSL. The logic flow is as follows:
Remember that each module, emitter and system you create uses resources. To conserve resources and improve performance, look through the modules already included in Niagara to see if you can accomplish your goal without creating a new module. Dynamic Inputs can be used to great effect here.
Niagara Paradigms
Inheritance
- With a flat hierarchy, you cannot effectively locate and use the assets you already have in your library, which leads to people recreating those assets. Duplication of effort lowers efficiency and increases costs.
- Hierarchical inheritance increases discoverability and enables effective reuse of existing assets.
- Anything inherited can be overridden for a child emitter in a system.
- Modules can be added, or can be reverted back to the parent value.
- This is also true with emitter-level behaviors such as spawning, lifetime, looping, bursts, and so on.
Dynamic Inputs
- Dynamic inputs are built the same way modules are built.
- Dynamic inputs give users infinite extensibility for inheritance.
- Instead of acting on a parameter map, dynamic inputs act on a value type.
- Any value can be driven by Graph logic and user-facing values.
- Dynamic inputs have almost the same power as creating modules, but can be selected and dropped into the stack without actually creating new modules.
- Existing modules can be modified and customized in many ways by using and chaining Dynamic Inputs; this can reduce module bloat and improve performance.
Micro Expressions
- Any inline value can be converted into an HLSL expression snippet.
- Users can access any variable in the particle, emitter, or system, as well as any HLSL or VM function.
- This works well for small, one-off features that do not need a new module.
Events
- Events are a way to communicate between elements (such as particles, emitters, and systems).
- Events can be any kind of data, packed into a payload (such as a struct) and sent. Then anything else can listen for that event and take action.
- Options you can use:
- Run the event directly on a particle by using Particle.ID.
- Run the event on every particle in a System.
- Set particles to spawn in response to the event, then take some action on those particles.
- Events are a special node in the graph (structs). How to use the Event node:
- Name the event.
- Add whatever data you want to it.
- Add an Event Handler into the Emitter stack.
- Set the options for the Event Handler.
- There is a separate execution stack for events.
- You can put elaborate graph logic into Event Handlers.
- You can have a whole particle system set up, with complex logic, and then have a whole separate set of behaviors that occur when the event triggers.
Data Interfaces
- There is an extensible system to allow access to arbitrary data.
- Arbitrary data includes mesh data, audio, external DDC information, code objects, and text containers.
- Data interfaces can be written as plugins for greater extensibility moving forward.
- Users can get any data associated with a skeletal mesh by using a skeletal mesh data interface.
Houdini
- Using Houdini, you can calculate split points, spawn locations, impact positions, impact velocity, normals and so on.
- You can then export that data from Houdini to a common container format (CSV).
- You can import that CSV into Niagara in your UE4 project.