# Unreal Engine: Visual and Audio Effects

*2025-08-20*

> Notes taken from the eleventh week of Game Programming Foundations


While last week covered [animation and animation montages]({{< relref "/posts/2025/unreal-engine-10-animation-and-montages" >}}), this week was **juice**: the legacy [Cascade particle system](https://dev.epicgames.com/documentation/unreal-engine/cascade-particle-systems?application_version=4.27) and its successor [Niagara](https://dev.epicgames.com/documentation/unreal-engine/overview-of-niagara-effects-for-unreal-engine), sounds, sound cues and [MetaSounds](https://dev.epicgames.com/documentation/unreal-engine/metasounds-in-unreal-engine), camera shake, post-process effects, and force feedback.

Updates were committed to [sawnoff-studios/niagara-system-demo](https://github.com/sawnoff-studios/niagara-system-demo) as I followed along – notes below.

---

## Cascade (Legacy Particle System)

- Add via the Add button → Add Feature or Content Pack → Miscellaneous → **Cascade Particle System (Legacy)**
- Open a particle effect and enable/disable modules via checkboxes
- Worth learning a little anyway: concepts carry across to Niagara

## Cascade to Niagara Converter

- The plugin can convert Cascade systems, but results are generally error-prone
- Warnings on opening (e.g. scale being off); it can attempt to automatically fix issues

## Niagara Emitters

- Emitters are like blueprint nodes – **modular, reusable components** – and unlike Cascade, you can access them individually
- Create an Emitter and pick a template to start from

**Selecting and configuring properties:**
- Click a property → Details panel on the right
- **Sprite Attributes → Sprite-based renderer → Sprite Material**: sprite particles face toward the camera by default
- Add new properties/modules via the plus icon
- Delete with the **DEL** key

**Useful modules:**
- **Add Velocity** → Velocity Mode → Linear: sets velocity in X/Y/Z; the small dropdown changes the velocity type
- **Particle State** is on by default – drag the lifetime minimum/maximum to change when effects kick in
- **Scale Color** transitions from one color to another – the dropdown can make a vector from a Linear Color RGB
- **Color from Curve**: double-click the top pin for the color picker, double-click the curve to add pins – top is color, bottom is alpha

## Niagara Systems

- Niagara Emitters **can't be placed in the world directly** – they must live inside a Niagara System
- Right-click an Emitter → **Create Niagara System**
- Systems can expose **user parameters**
- **Ctrl+D** duplicates without affecting the original Emitter
- Emitters can be exported as assets via right-click

## Spawning Effects

**Blueprint:**
- **Spawn System at Location / Attached** for Niagara
- **Spawn Emitter at Location** only offers Cascade particles – a legacy relic

**C++:**
- Add `"Niagara"` to `Build.cs`, then `UNiagaraFunctionLibrary::SpawnSystemAtLocation()`
- Gotcha: spawning at an actor's location fires from the **base of the mesh**, because that's where the pivot is – get the object's size, halve it, and offset the spawn position

## Audio

- Import as usual, but effectively only **.wav/.ogg** are supported (no .mp3)
- Basic playback and property editing available on import

**Sound Classes:**
- Configure in Project Settings → Engine → Audio → Default Classes
- Group sounds into classes → per-class volume sliders (e.g. a Master group)
- Make sure effects get added to the right class – you rarely play a raw sound wave directly

**Sound Cues (UE4):**
- Right-click a wave file → Create Cue, then add effects on the right
- Select multiple waves → **Create Multiple Cues** – the cue randomizes between them
- Being slowly phased out (see MetaSounds)

**MetaSounds:**
- For fully randomized sound effects and music generation
- Right-click → **MetaSound Source**
- Gotcha: wiring `On Play → Output` results in the audio cutting off instantly - hook up **On Finished → Output** to make it play out
- **Pitch shift via semitones**, driven by a `Random (Float)` node; hooking it via the Next pin randomizes pitch on every play
- **Ctrl+D** a MetaSound and swap the effect to create variants
- **Generators** (e.g. Square wave) can synthesize tones directly – Change Type → Trivial

**Playing sounds in Blueprint:**
- **Play Sound 2D** – constant volume regardless of listener position (UI, ambient)
- **Play Sound at Location** - attenuates from a world position
- Sound dragging on too long? **Spawn Sound at Location** instead, promote the return value to a variable (an Audio Component reference like `FuseRef`), and call **Stop** on it when needed

**C++:**
- A `USoundBase*` reference in the header, then:
```cpp
UGameplayStatics::PlaySoundAtLocation(this, ExplosionSound, GetActorLocation());
```

**Sound Attenuation:**
- Create a **Sound Attenuation** asset (right side of the sound's Details panel)
- Override attenuation → set **Inner Radius** and **Falloff Distance**
- One attenuation asset can serve multiple sound effects

## Camera Shake

- Create `CS_Explosion` as a Blueprint with parent **DefaultCameraShakeBase** – a data-only Blueprint using the Root Shake Pattern
- In the bomb Blueprint, call **Play World Camera Shake** with `CS_Explosion`

## Particle Effects

- E.g. `NE_Explosion` with a Mesh Renderer emitting dust particles (rather than sprites)

## Post Process

- Add a **PostProcessVolume** via the Outliner's Add button → Visual Effects
- Set properties (bloom, exposure, etc.) in the Details panel
- **Infinite Extent (Unbound)** makes it override the global post process
- Multiple volumes are ordered by **Priority**

## Force Feedback

- Add **gamepad support early** if you plan to use it – input actions and mappings for the pad first
- Create the effect: Input → **Force Feedback Effect** (or Miscellaneous → Haptic Feedback for VR) → `FF_Explosion`
- Build curves and offsets the same way as timelines
- Trigger via **Client Play Force Feedback**, with Get Player Controller as the target

---

## Notes on things that stood out

The week's running theme was **old and new living side by side**: Cascade→Niagara, Sound Cues→MetaSounds, each pair with a converter that half-works and a lesson in why the old system's concepts still matter.

The most practical takeaway was the **pivot-point spawn gotcha** - effects appearing at an actor's feet is a classic "works on my machine" bug - and the **On Finished → Output** trap in MetaSounds, which produces a silently truncated sound with no error.
