game-audio
Use this skill when designing or implementing audio systems for games - sound effects, adaptive music, spatial/3D audio, and middleware integration with FMOD or Wwise. Triggers on sound design, audio implementation, adaptive music systems, spatial audio, HRTF, audio middleware setup, sound event architecture, audio mixing, dynamic soundscapes, and game audio optimization. Covers FMOD Studio, Audiokinetic Wwise, and engine-native audio APIs.
game-development game-audiosound-designfmodwwisespatial-audioadaptive-music3d-audioWhat is game-audio?
Use this skill when designing or implementing audio systems for games - sound effects, adaptive music, spatial/3D audio, and middleware integration with FMOD or Wwise. Triggers on sound design, audio implementation, adaptive music systems, spatial audio, HRTF, audio middleware setup, sound event architecture, audio mixing, dynamic soundscapes, and game audio optimization. Covers FMOD Studio, Audiokinetic Wwise, and engine-native audio APIs.
game-audio
game-audio is a production-ready AI agent skill for claude-code, gemini-cli, openai-codex, and 1 more. Designing or implementing audio systems for games - sound effects, adaptive music, spatial/3D audio, and middleware integration with FMOD or Wwise.
Quick Facts
| Field | Value |
|---|---|
| Category | game-development |
| Version | 0.1.0 |
| Platforms | claude-code, gemini-cli, openai-codex, mcp |
| License | MIT |
How to Install
- Make sure you have Node.js installed on your machine.
- Run the following command in your terminal:
npx skills add AbsolutelySkilled/AbsolutelySkilled --skill game-audio- The game-audio skill is now available in your AI coding agent (Claude Code, Gemini CLI, OpenAI Codex, etc.).
Overview
Game audio encompasses every sound a player hears - from UI clicks to orchestral scores that shift with gameplay. Unlike film audio, game audio is non-linear and reactive: sounds must respond to player actions, environmental state, and game events in real time. This skill covers sound design fundamentals, adaptive music composition and implementation, spatial (3D) audio systems, and professional middleware tools (FMOD Studio and Audiokinetic Wwise) that power audio in most shipped titles.
Tags
game-audio sound-design fmod wwise spatial-audio adaptive-music 3d-audio
Platforms
- claude-code
- gemini-cli
- openai-codex
- mcp
Related Skills
Pair game-audio with these complementary skills:
Frequently Asked Questions
What is game-audio?
Use this skill when designing or implementing audio systems for games - sound effects, adaptive music, spatial/3D audio, and middleware integration with FMOD or Wwise. Triggers on sound design, audio implementation, adaptive music systems, spatial audio, HRTF, audio middleware setup, sound event architecture, audio mixing, dynamic soundscapes, and game audio optimization. Covers FMOD Studio, Audiokinetic Wwise, and engine-native audio APIs.
How do I install game-audio?
Run npx skills add AbsolutelySkilled/AbsolutelySkilled --skill game-audio in your terminal. The skill will be immediately available in your AI coding agent.
What AI agents support game-audio?
This skill works with claude-code, gemini-cli, openai-codex, mcp. Install it once and use it across any supported AI coding agent.
Maintainers
Generated from AbsolutelySkilled
SKILL.md
Game Audio
Game audio encompasses every sound a player hears - from UI clicks to orchestral scores that shift with gameplay. Unlike film audio, game audio is non-linear and reactive: sounds must respond to player actions, environmental state, and game events in real time. This skill covers sound design fundamentals, adaptive music composition and implementation, spatial (3D) audio systems, and professional middleware tools (FMOD Studio and Audiokinetic Wwise) that power audio in most shipped titles.
When to use this skill
Trigger this skill when the user:
- Needs to design or implement a sound effects system for a game
- Wants to create adaptive or dynamic music that responds to gameplay
- Is setting up spatial/3D audio with HRTF or attenuation curves
- Needs to integrate FMOD Studio or Wwise into a game engine
- Wants to architect a sound event system or audio manager
- Asks about audio mixing, buses, ducking, or signal routing
- Needs to optimize audio for memory, CPU, or streaming performance
- Wants to build dynamic soundscapes or ambient audio layers
Do NOT trigger this skill for:
- Music composition theory or notation (use a music theory skill)
- Non-game audio production like podcast editing or mastering (use audio-production)
Key principles
Audio is reactive, not scripted - Game audio cannot be authored linearly like film. Every sound must be designed as a response to an event. Think in terms of event-to-sound mappings, not timelines.
Less is more in the mix - Players process audio subconsciously. A clean mix with 4-6 prominent sounds is more impactful than 20 competing layers. Use priority systems, ducking, and voice limits to keep the mix focused.
Variation prevents fatigue - Any sound heard more than twice needs randomization. Use round-robin containers, pitch/volume randomization, and multiple samples to prevent repetition fatigue.
Spatial audio sells immersion - Proper 3D spatialization, distance attenuation, and environmental effects (reverb zones, occlusion) make players feel present in the world without them consciously noticing.
Middleware is your friend - FMOD and Wwise exist so audio designers and programmers can work in parallel. Sound designers author in the middleware tool; programmers fire events from code. This separation is non-negotiable on any team larger than one person.
Core concepts
The event-driven audio model
Game audio is built on an event system. Game code fires named events (e.g.,
Player/Footstep, Weapon/Fire, Music/EnterCombat), and the audio middleware
resolves those events into actual sounds. This decoupling means:
- Sound designers can swap, layer, or randomize sounds without code changes
- Programmers don't need to know which .wav file plays for a footstep
- Events can carry parameters (surface type, velocity, health percentage) that the middleware uses to select or modulate sounds
Adaptive music architecture
Adaptive music uses one or more of these techniques to respond to gameplay:
| Technique | Description | Best for |
|---|---|---|
| Horizontal re-sequencing | Rearranges musical sections in real time | Exploration, open-world |
| Vertical layering | Adds/removes instrument layers based on intensity | Combat escalation |
| Stinger/transition | Plays a short musical phrase to bridge states | State changes (win, lose, discovery) |
| Branching | Pre-authored alternate paths at decision points | Story-driven moments |
Most shipped games combine 2-3 of these. Vertical layering + stingers is the most common pattern for action games.
Spatial audio pipeline
The spatial audio pipeline processes each sound source through:
- Distance attenuation - Volume decreases with distance (linear, logarithmic, or custom curve)
- Spatialization - Panning across speakers/headphones using HRTF (head-related transfer function) or simple panning
- Occlusion/obstruction - Raycast from listener to source; muffle if geometry blocks the path
- Environmental effects - Apply reverb, echo, or filtering based on the room/space the sound is in (reverb zones)
FMOD vs Wwise at a glance
| Aspect | FMOD Studio | Wwise |
|---|---|---|
| Pricing | Free under $200K revenue | Free under 1000 sound assets |
| Learning curve | Lower - familiar DAW-like UI | Steeper - more powerful, more complex |
| Strength | Rapid prototyping, indie-friendly | Large-scale projects, AAA pipelines |
| Unity integration | First-class plugin | First-class plugin |
| Unreal integration | Community plugin | Built-in integration |
| Scripting | C/C++ API, C# wrapper | C/C++ API, Wwise Authoring API |
See references/fmod-guide.md and references/wwise-guide.md for setup and API
details.
Common tasks
Set up an audio event system
Create a centralized audio manager that maps game events to middleware calls.
// Unity + FMOD example
public class AudioManager : MonoBehaviour
{
public static AudioManager Instance { get; private set; }
private void Awake()
{
if (Instance != null) { Destroy(gameObject); return; }
Instance = this;
DontDestroyOnLoad(gameObject);
}
public void PlayOneShot(string eventPath, Vector3 position)
{
FMODUnity.RuntimeManager.PlayOneShot(eventPath, position);
}
public FMOD.Studio.EventInstance CreateInstance(string eventPath)
{
return FMODUnity.RuntimeManager.CreateInstance(eventPath);
}
public void SetGlobalParameter(string name, float value)
{
FMODUnity.RuntimeManager.StudioSystem.setParameterByName(name, value);
}
}
// Usage from game code:
AudioManager.Instance.PlayOneShot("event:/SFX/Explosion", transform.position);Implement adaptive music with vertical layering
Layer instrument stems that activate based on a game parameter (e.g., threat level).
FMOD Studio setup:
1. Create a Music Event with multiple audio tracks (stems):
- Track 1: Ambient pad (always playing)
- Track 2: Percussion (activates at threat > 0.3)
- Track 3: Brass/strings (activates at threat > 0.6)
- Track 4: Full orchestra (activates at threat > 0.9)
2. Create a parameter "ThreatLevel" (0.0 to 1.0) on the event
3. Add volume automation on each track tied to ThreatLevel:
- Track 1: Volume 1.0 across full range
- Track 2: Fade in from 0.0 to 1.0 between threat 0.3-0.4
- Track 3: Fade in between 0.6-0.7
- Track 4: Fade in between 0.9-1.0// Code side - update the parameter from game state
private FMOD.Studio.EventInstance musicInstance;
void StartMusic()
{
musicInstance = AudioManager.Instance.CreateInstance("event:/Music/Exploration");
musicInstance.start();
}
void Update()
{
float threat = CalculateThreatLevel();
musicInstance.setParameterByName("ThreatLevel", threat);
}Configure spatial audio with attenuation and occlusion
// FMOD: Set 3D attributes on a looping sound source
public class AudioEmitter : MonoBehaviour
{
[SerializeField] private string eventPath = "event:/SFX/Generator_Hum";
private FMOD.Studio.EventInstance instance;
void Start()
{
instance = FMODUnity.RuntimeManager.CreateInstance(eventPath);
instance.set3DAttributes(FMODUnity.RuntimeUtils.To3DAttributes(transform));
instance.start();
}
void Update()
{
instance.set3DAttributes(FMODUnity.RuntimeUtils.To3DAttributes(transform));
}
void OnDestroy()
{
instance.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT);
instance.release();
}
}For occlusion, raycast from the listener to the source and set a low-pass filter parameter based on hit count:
void UpdateOcclusion()
{
Vector3 listenerPos = Camera.main.transform.position;
Vector3 direction = transform.position - listenerPos;
float distance = direction.magnitude;
int hits = Physics.RaycastNonAlloc(listenerPos, direction.normalized,
raycastHits, distance, occlusionMask);
float occlusion = Mathf.Clamp01(hits * 0.3f);
instance.setParameterByName("Occlusion", occlusion);
}Design sound variation for repeated events
Prevent repetition fatigue by using containers and randomization:
FMOD Studio:
1. Create a Multi Instrument inside your event
2. Add 3-5 sound variants (e.g., footstep_01.wav through footstep_05.wav)
3. Set playlist mode to "Shuffle" (avoids consecutive repeats)
4. Add pitch randomization: -2 to +2 semitones
5. Add volume randomization: -1 to +1 dB
Wwise equivalent:
1. Create a Random Container
2. Add sound variants as children
3. Enable "Avoid Repeating Last" with a value of 2-3
4. Add Randomizer on Pitch (-200 to +200 cents) and Volume (-1 to +1 dB)Set up audio buses and mixing
Organize all game audio into a bus hierarchy for clean mixing:
Master Bus
|- Music Bus (baseline: -6 dB)
| |- Combat Music
| |- Ambient Music
|- SFX Bus (baseline: 0 dB)
| |- Player SFX
| |- Enemy SFX
| |- Environment SFX
|- UI Bus (baseline: -3 dB)
|- Voice Bus (baseline: +2 dB, duck Music by -12 dB when active)Key mixing practices:
- Duck music when dialogue plays (sidechain the Voice bus to Music bus)
- Set voice limits per event (e.g., max 8 simultaneous footsteps)
- Use snapshot/state systems for context switches (underwater, pause menu)
- Keep headroom: master should peak at -3 to -6 dBFS
Optimize audio for performance
| Technique | Memory savings | CPU savings | When to use |
|---|---|---|---|
| Compressed formats (Vorbis/Opus) | 80-90% | Slight CPU cost | All SFX except very short sounds |
| Streaming from disk | ~100% per sound | Disk I/O cost | Music, long ambiences (>5 seconds) |
| Voice limiting | Proportional | Proportional | Any sound that can overlap heavily |
| Sample rate reduction (22kHz) | 50% | Minor | Ambient, background, low-frequency |
| Sound pooling | Avoids alloc spikes | Avoids alloc spikes | Rapid-fire sounds (bullets, particles) |
Rules of thumb:
- Stream music and long ambiences; load short SFX into memory
- Set voice limits: 4-8 for common SFX, 1-2 for music events
- Use compressed in-memory format for SFX banks
- Budget: aim for under 50 MB total audio memory on console, 100 MB on PC
Anti-patterns / common mistakes
| Mistake | Why it's wrong | What to do instead |
|---|---|---|
| Hardcoding audio file paths in game code | Tightly couples code to specific assets; impossible to iterate on sounds without recompiling | Use event-based middleware; reference events by name, never by file |
| No sound variation | Players notice repeated identical sounds within 3 occurrences; breaks immersion | Use random containers with 3-5 variants plus pitch/volume randomization |
| Music cuts abruptly on state change | Jarring transitions destroy mood; players notice bad music transitions immediately | Use transition timelines, crossfades, or stinger/bridge segments |
| Ignoring voice limits | 100 simultaneous explosion sounds will clip, distort, and destroy CPU budgets | Set per-event voice limits with steal behavior (oldest, quietest, or farthest) |
| Flat 3D audio (no occlusion) | Sound passing through walls breaks spatial awareness and immersion | Implement raycast-based occlusion with low-pass filtering |
| Mixing everything at 0 dB | No headroom causes clipping; no hierarchy means players can't prioritize important sounds | Structure buses with headroom; duck less important buses when critical sounds play |
| Loading all audio into memory | Game runs out of memory or has huge load times | Stream long audio; compress short SFX; only load banks needed for current level |
Gotchas
FMOD/Wwise events not releasing cause memory leaks - Creating an
EventInstanceand callingstart()without callingstop()andrelease()onOnDestroyleaks audio resources permanently. Looping sounds in particular will play forever even after the game object is destroyed. Always pairCreateInstance()with arelease()in the cleanup path.Voice stealing can silence the most important sound - If your voice limit steal mode is set to "oldest" or "lowest priority" and you don't assign proper priority weights, the enemy warning sound or boss music can get stolen by ambient birds. Set explicit priority values for every event category and use "lowest priority" steal on non-critical sounds only.
Streaming audio from disk introduces frame spikes on seek - Streaming is memory-efficient but seeks cause disk I/O spikes. Enabling streaming on short SFX (under 5 seconds) trades memory savings for CPU/IO cost with no benefit. Stream only music and long ambiences; load short SFX into memory compressed.
Occlusion raycasts every frame on all emitters tanks CPU - Running
Physics.Raycastper emitter per frame for 50+ active audio sources will consume significant CPU time. Stagger occlusion updates (every 3-5 frames per emitter, not every frame) and use a maximum occlusion check distance to skip distant emitters.Parameter automation curves that are too fast cause audible clicks - Changing a parameter value instantly (e.g., switching ThreatLevel from 0 to 1 in one frame) causes a discontinuity in the audio signal that produces an audible click. Always use smoothed parameter changes with a minimum ramp time of 50-100ms for volume/frequency parameters.
References
For detailed content on specific topics, read the relevant file from references/:
references/fmod-guide.md- FMOD Studio setup, C# API, event authoring, parameter automationreferences/wwise-guide.md- Wwise project setup, SoundBank workflow, RTPC, state/switch groupsreferences/spatial-audio.md- HRTF, ambisonics, reverb zones, occlusion algorithms, platform differencesreferences/adaptive-music.md- Horizontal re-sequencing, vertical layering, transition matrices, implementation patterns
Only load a references file if the current task requires deep detail on that topic.
References
adaptive-music.md
Adaptive Music
Deep reference for designing and implementing music systems that respond to gameplay in real time - covering horizontal re-sequencing, vertical layering, transition design, and implementation in FMOD Studio and Wwise.
Adaptive music techniques
Vertical layering (additive)
All layers play simultaneously, synchronized to the same tempo. Individual layers fade in/out based on game parameters.
Layer structure example (combat music):
Layer 1: Ambient pad [always on, volume 0.7]
Layer 2: Rhythmic pulse [on when tension > 0.2]
Layer 3: Percussion [on when tension > 0.4]
Layer 4: Bass + drums [on when tension > 0.6]
Layer 5: Full brass/strings [on when tension > 0.8]
Layer 6: Choir + cymbals [on at tension = 1.0]Implementation rules:
- All layers must share the same BPM, key, and time signature
- Compose so any combination of active layers sounds good
- Fade transitions: 0.5-2.0 seconds depending on tempo
- Use RTPC or parameter to drive layer volumes (not on/off switching)
Horizontal re-sequencing
Music is divided into segments (bars or phrases) that can be rearranged in real time. The system picks the next segment based on game state.
Segment pool:
[Intro] -> [Explore_A] -> [Explore_B] -> [Explore_C]
|
[Transition_ToCombat]
|
[Combat_A] -> [Combat_B] -> [Combat_Loop]
|
[Transition_ToExplore]
|
[Explore_A] (loop back)Rules:
- Segments must start and end on musically compatible boundaries (bar lines)
- Transitions between segments happen at defined sync points (next bar, next beat)
- Each segment should be self-contained enough to loop if the state doesn't change
Stingers and transition segments
Short musical phrases (1-4 bars) that play during state changes to smooth transitions:
| Stinger type | Duration | Trigger |
|---|---|---|
| Discovery | 2-4 bars | Finding an item, entering new area |
| Danger | 1-2 bars | Enemy spotted, trap triggered |
| Victory | 4-8 bars | Boss defeated, level complete |
| Death | 2-4 bars | Player dies |
| Transition bridge | 2-4 bars | Between musical states (explore -> combat) |
Stingers typically override or layer on top of the current music, then fade back to the new state's music.
Branching
Pre-authored alternate paths at decision points. Most common in narrative games:
[Verse 1]
/ \
[Happy Chorus] [Dark Chorus]
\ /
[Verse 2]The branch is selected by a game parameter or state at the decision point. Less flexible than layering but allows for more compositionally complex transitions.
Music state machine design
Most games use a state machine to drive adaptive music:
Example: action-adventure game
States:
MENU -> ambient pad, no gameplay music
EXPLORE -> exploration theme, low intensity
ALERT -> tense variation, percussion enters
COMBAT -> full combat music, all layers
BOSS -> unique boss theme
VICTORY -> victory stinger, fade to explore
DEATH -> death stinger, silence, respawn into explore
CUTSCENE -> scripted music, external control
Transitions:
EXPLORE -> ALERT: Fade over 2 bars, add percussion layer
ALERT -> COMBAT: Stinger + cut to combat at next bar
COMBAT -> EXPLORE: Combat winds down over 4 bars, stinger, crossfade
COMBAT -> BOSS: Immediate transition with boss intro stinger
BOSS -> VICTORY: Victory stinger overlays, fade boss music
* -> CUTSCENE: Duck gameplay music, crossfade to cutscene track
CUTSCENE -> *: Crossfade back to appropriate state musicCooldown and hysteresis
Prevent rapid music flickering when game state oscillates:
- Cooldown timer: After entering a state, stay for minimum 4-8 seconds before allowing transition to a lower-intensity state
- Hysteresis: Use different thresholds for entering vs leaving a state. Example: enter COMBAT at threat > 0.7, leave COMBAT at threat < 0.3
- Transition queue: If a transition is requested while another is in progress, queue it. Don't interrupt transitions.
Implementation in FMOD Studio
Vertical layering setup
- Create a Music Event
- Add multiple Audio Tracks (one per layer)
- Place audio on each track, all synchronized to the same timeline
- Create a local parameter (e.g., "Intensity", 0.0 to 1.0)
- Add volume automation on each track driven by the parameter:
- Track 1 (pad): constant volume
- Track 2 (perc): automate from silent to full between 0.2-0.3
- Track 3 (bass): automate between 0.4-0.5
- (continue for each layer)
- Set the event to loop (add a loop region on the timeline)
Horizontal re-sequencing setup
- Create a Music Event
- Add a Logic Track with transition markers
- Use Transition Regions and Destinations:
- Add named destination markers at each segment start
- Create transition conditions tied to parameters
- Alternative: use the Multi Instrument + parameter-driven playlist
Stinger implementation
- Create a separate one-shot event for each stinger
- Use FMOD's callback system to time the stinger to the next beat/bar:
// Quantize stinger to next beat
musicInstance.getTimelinePosition(out int position);
int beatLength = 60000 / bpm; // ms per beat
int nextBeat = ((position / beatLength) + 1) * beatLength;
int delay = nextBeat - position;
// Schedule stinger
StartCoroutine(PlayStingerAfterDelay("event:/Music/Stinger_Combat", delay));Implementation in Wwise
Music Switch Container
- Create a Music Switch Container
- Associate it with a State Group (e.g., MusicState: Explore, Combat, Boss)
- Add child Music Playlist Containers - one per state
- Each playlist contains Music Segments and defines playback order
- Open the Transition Editor to define rules between states
Transition rules in Wwise
In the Music Switch Container's Transition Editor:
| From | To | Rule |
|---|---|---|
| Explore | Combat | Exit at next bar, play transition segment, enter at start |
| Combat | Explore | Exit at next bar, 2-bar fade out, enter at start |
| Any | Boss | Exit immediate, play boss intro stinger, enter at start |
| Boss | Victory | Exit at next bar, play victory stinger |
Vertical layering in Wwise
- Create a Music Segment with multiple tracks
- Each track represents a layer
- Use RTPC to control each track's volume
- Or use States with volume overrides per track:
- Low intensity state: tracks 1-2 at 0 dB, tracks 3-5 at -96 dB
- High intensity state: all tracks at 0 dB
- Define transition time between states (1-2 seconds)
Composition guidelines for adaptive music
General rules
- Compose in layers from the start - Don't write a finished piece and try to split it later. Each layer must function independently.
- Avoid strong melodic hooks in optional layers - If a melody might not play, don't make it the centerpiece. Put catchy melodies in the always-on base layer.
- Match energy levels to game states - Map your musical intensity scale (1-10) to your game's intensity scale.
- Key and tempo consistency - All layers and segments in a music system should share the same key (or compatible keys) and tempo.
Tempo and sync
- Lock all layers to the same BPM grid
- Typical tempos: exploration 80-100 BPM, combat 120-160 BPM
- If switching between tempos, use transition segments that ritardando/accelerando
- Quantize all transitions to bar boundaries (not beat) for smoother results
Loop points
- Music segments should loop seamlessly - match the waveform at loop boundaries
- Place loop points at bar lines, never mid-beat
- Test loops by listening for 5+ repetitions - subtle clicks or rhythmic bumps become obvious after several repeats
- Export loops with a brief tail (100-200ms) for crossfade if needed
Testing adaptive music
Manual testing checklist
- Each music state sounds good on its own (no missing layers)
- Transitions between adjacent states are smooth
- Transitions between non-adjacent states work (e.g., straight from EXPLORE to BOSS)
- Rapid state changes don't cause audio glitches or overlapping music
- Hysteresis/cooldown prevents flickering at state boundaries
- Stingers align to the beat grid
- Music loops are seamless after 5+ repetitions
- Volume levels are consistent across all states (no sudden jumps)
Profiler monitoring
In FMOD Studio or Wwise Profiler:
- Monitor voice count during music playback (should stay under budget)
- Check CPU usage of music events (streaming vs memory)
- Verify transitions fire at expected sync points
- Inspect parameter values match expected game state
Common pitfalls
| Mistake | Impact | Fix |
|---|---|---|
| Layers not synchronized | Music sounds out of time | Ensure all layers share the same BPM and start point |
| No transition segments | Jarring cuts between states | Compose 2-4 bar bridge segments for major transitions |
| Music reacts too fast | Flickering between states feels chaotic | Add hysteresis and cooldown timers |
| All layers always audible | No dynamic range; combat doesn't feel different from exploration | Reserve 40-60% of layers for high-intensity states only |
| Hard volume cuts | Audible pops and clicks | Always fade over 0.5-2 seconds; never set volume to 0 instantly |
| Ignoring memory for music | Music streams compete with SFX for bandwidth | Stream music from disk; limit to 2-3 simultaneous music streams |
fmod-guide.md
FMOD Studio Guide
Comprehensive reference for FMOD Studio integration in game projects, covering project setup, event authoring, parameter automation, and runtime C# API usage.
Installation and setup
Unity integration
- Download the FMOD for Unity plugin from fmod.com/unity
- Import the
.unitypackageinto your Unity project - Go to FMOD > Edit Settings and set the Studio Project Path to your
.fsprojfile - Set the Build path to
Assets/StreamingAssets(default) - Build banks in FMOD Studio (File > Build) before running in Unity
Unreal Engine integration
- Download the FMOD for Unreal plugin
- Extract to
<Project>/Plugins/FMODStudio/ - In Project Settings > FMOD Studio, set the Studio Project Directory
- Banks are built and loaded automatically with the plugin
Bank management
Banks are the compiled audio containers that ship with your game:
- Master Bank - Always loaded; contains buses, VCAs, and global events
- Master Bank.strings - Contains event name-to-GUID mappings; required for path lookups
- Level/scene banks - Load per scene to manage memory
- Dialogue banks - Separate for localization
// Loading a bank at runtime
FMODUnity.RuntimeManager.LoadBank("Level_Forest", true);
// Unloading when leaving the scene
FMODUnity.RuntimeManager.UnloadBank("Level_Forest");Event authoring in FMOD Studio
Event types
| Type | Use case |
|---|---|
| 2D Event | UI sounds, music, narrator voice |
| 3D Event | In-world sounds that need spatialization |
| Spatializer (panner) | Controls how 3D events are placed in the stereo/surround field |
| Timeline | Sound placed on a timeline with automation lanes |
| Action Sheet | Logic-based sound design using parameters and conditions |
Creating a basic SFX event
- Right-click Events folder > New Event
- Drag audio files onto the timeline
- Set the event to 3D if it needs spatialization (Properties > Spatializer)
- Configure attenuation: set min/max distance in the 3D panner
- Assign to a bus (e.g., SFX/Player)
Parameter types
| Parameter | Scope | Example |
|---|---|---|
| Event parameter (local) | Per-instance | "Speed" on a car engine event |
| Global parameter | Shared across all events | "TimeOfDay", "ThreatLevel" |
| Built-in: Distance | Automatic | Based on listener-to-source distance |
| Built-in: Direction | Automatic | Angle to source relative to listener |
Multi Instrument (randomization)
For sound variation:
- Add a Multi Instrument to the event timeline
- Drag 3-5 variants into the playlist
- Set Playlist Mode: Shuffle (avoids repeats)
- Set Trigger Behavior: Sequential or Steal Oldest
- Add pitch randomization: right-click timeline > Add Modulation > Pitch (-200 to +200 cents)
- Add volume randomization: similar, -1 to +1 dB
C# Runtime API
Core patterns
// One-shot: fire and forget (short SFX)
FMODUnity.RuntimeManager.PlayOneShot("event:/SFX/Explosion", transform.position);
// Persistent instance: looping sounds, music, or anything needing control
FMOD.Studio.EventInstance engineSound;
void Start()
{
engineSound = FMODUnity.RuntimeManager.CreateInstance("event:/SFX/Engine");
engineSound.start();
}
void Update()
{
// Update 3D position
engineSound.set3DAttributes(FMODUnity.RuntimeUtils.To3DAttributes(transform));
// Update parameter
engineSound.setParameterByName("RPM", currentRPM);
}
void OnDestroy()
{
engineSound.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT);
engineSound.release();
}Parameter control
// Local parameter (on a specific event instance)
instance.setParameterByName("Health", playerHealth);
// Global parameter (affects all events listening to it)
FMODUnity.RuntimeManager.StudioSystem.setParameterByName("TimeOfDay", 0.75f);
// Get current value
instance.getParameterByName("Speed", out float value);Bus and VCA control
// Get a bus reference
FMOD.Studio.Bus musicBus = FMODUnity.RuntimeManager.GetBus("bus:/Music");
// Set volume (0.0 to 1.0, linear scale)
musicBus.setVolume(0.5f);
// Mute/unmute
musicBus.setMute(true);
// Pause all sounds on a bus
musicBus.setPaused(true);
// VCA (Volume Control Automation) for player-facing sliders
FMOD.Studio.VCA masterVCA = FMODUnity.RuntimeManager.GetVCA("vca:/Master");
masterVCA.setVolume(settingsSliderValue);Snapshots
Snapshots are mix presets that blend in/out at runtime:
// Activate a snapshot (e.g., underwater muffling)
FMOD.Studio.EventInstance underwaterSnapshot;
void EnterWater()
{
underwaterSnapshot = FMODUnity.RuntimeManager.CreateInstance("snapshot:/Underwater");
underwaterSnapshot.start();
}
void ExitWater()
{
underwaterSnapshot.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT);
underwaterSnapshot.release();
}Callback system
// Listen for timeline markers (e.g., beat markers in music)
instance.setCallback(MusicCallback,
FMOD.Studio.EVENT_CALLBACK_TYPE.TIMELINE_MARKER |
FMOD.Studio.EVENT_CALLBACK_TYPE.TIMELINE_BEAT);
[AOT.MonoPInvokeCallback(typeof(FMOD.Studio.EVENT_CALLBACK))]
static FMOD.RESULT MusicCallback(
FMOD.Studio.EVENT_CALLBACK_TYPE type,
IntPtr instancePtr,
IntPtr parameterPtr)
{
if (type == FMOD.Studio.EVENT_CALLBACK_TYPE.TIMELINE_MARKER)
{
var marker = (FMOD.Studio.TIMELINE_MARKER_PROPERTIES)
Marshal.PtrToStructure(parameterPtr,
typeof(FMOD.Studio.TIMELINE_MARKER_PROPERTIES));
Debug.Log($"Marker: {marker.name} at {marker.position}ms");
}
return FMOD.RESULT.OK;
}Common pitfalls
| Issue | Cause | Fix |
|---|---|---|
| No sound plays | Bank not loaded or event path typo | Check bank loading; verify path matches FMOD Studio |
| Sound plays but no 3D | Event not set to 3D, or 3D attributes not updated | Enable spatializer on event; call set3DAttributes every frame |
| Memory spike on scene load | Loading all banks at once | Use per-scene banks; load async |
| Sound continues after scene change | Instance not stopped/released | Always stop + release in OnDestroy |
| Clicking/popping on stop | Abrupt stop without fade | Use STOP_MODE.ALLOWFADEOUT; add AHDSR on event |
| GC allocation every frame | Creating strings for parameter names | Cache event paths and parameter IDs; use setParameterByID |
Project organization best practices
FMOD Studio Project/
Events/
Music/
Combat.fspro
Exploration.fspro
SFX/
Player/
Footstep.fspro
Jump.fspro
Weapons/
Pistol_Fire.fspro
Environment/
Wind.fspro
UI/
Button_Click.fspro
Voice/
Narrator/
Snapshots/
Underwater
PauseMenu
Buses/
Music
SFX
UI
VoiceName events with a clear hierarchy: event:/SFX/Player/Footstep. This maps
directly to the folder structure and makes code references self-documenting.
spatial-audio.md
Spatial Audio
Deep reference for 3D audio systems in games - covering spatialization techniques, HRTF rendering, distance attenuation, occlusion/obstruction, reverb zones, and platform-specific considerations.
Spatialization techniques
Channel-based panning
The simplest approach: pan a mono source across a speaker layout (stereo, 5.1, 7.1).
- Stereo: left-right panning based on source angle relative to listener
- Surround (5.1/7.1): VBAP (Vector Base Amplitude Panning) distributes sound across the nearest speaker pair
- Pros: Low CPU cost, compatible with all hardware
- Cons: Limited elevation perception, sweet-spot dependent
HRTF (Head-Related Transfer Function)
HRTF simulates how sounds reach each ear differently based on direction, using impulse responses measured from human heads:
- Provides full 3D perception including elevation (above/below)
- Essential for headphone users and VR/AR
- CPU cost per source: moderate (convolution with HRTF filters)
How HRTF works:
- Determine azimuth and elevation angle from listener to source
- Look up the corresponding HRTF pair (left ear, right ear) from a database
- Convolve the mono source with each ear's impulse response
- Output binaural stereo signal
HRTF databases:
- SOFA format - Standard for HRTF data interchange
- Resonance Audio (Google) - Built-in HRTF, free, Ambisonics-based
- Steam Audio (Valve) - Physics-based propagation + HRTF
- Oculus Audio SDK - Optimized for Meta Quest, personalized HRTF
Ambisonics
Ambisonics encodes a full spherical sound field independently of speaker layout:
- First-order (4 channels): Adequate for ambient beds, skyboxes
- Third-order (16 channels): Better localization, good for spatial music
- Decoded to any output format (stereo, surround, binaural) at the listener
Use case: encode complex ambient environments (forest, city) as an Ambisonic bed, then decode to the player's output format. Individual point sources (gunshots, footsteps) should use direct HRTF or panning, not Ambisonics.
Distance attenuation
Distance attenuation controls how volume decreases as the listener moves away from a source. Common curves:
| Curve | Formula | Use case |
|---|---|---|
| Linear | 1 - (d / maxDist) |
Simple, predictable, good for small scenes |
| Logarithmic (inverse) | 1 / (1 + k * d) |
Realistic for outdoor environments |
| Inverse square | 1 / (1 + k * d^2) |
Physically accurate (real-world sound) |
| Custom (spline) | Artist-defined curve | Most control, used in AAA productions |
Attenuation parameters
- Min distance: Below this distance, volume is at maximum (no attenuation)
- Max distance: Beyond this, volume is zero (or at the curve's minimum)
- Rolloff factor: Steepness of the curve between min and max
Typical values:
- Footsteps: min 1m, max 15m
- Gunshots: min 3m, max 100m
- Ambient loops: min 5m, max 50m
- Music: no attenuation (2D)
Occlusion and obstruction
Definitions
- Occlusion: Source is fully behind geometry (no direct or reflected path). Apply both low-pass filter AND volume reduction.
- Obstruction: Geometry blocks direct path but reflected paths exist (e.g., sound goes around a corner). Apply low-pass filter only; volume stays similar.
Implementation approaches
Raycast-based (common, CPU-friendly):
- Cast a ray from listener to source each frame
- Count geometry hits along the path
- Map hit count to an occlusion value (0.0 = clear, 1.0 = fully occluded)
- Send occlusion value to audio middleware as a parameter
- Middleware applies low-pass filter + volume curve based on value
// Unity example
void UpdateOcclusion(Transform source, Transform listener)
{
Vector3 direction = source.position - listener.position;
float distance = direction.magnitude;
int hits = Physics.RaycastNonAlloc(
listener.position, direction.normalized,
raycastBuffer, distance, occlusionLayerMask);
float occlusion = Mathf.Clamp01(hits * 0.25f);
// Send to FMOD
eventInstance.setParameterByName("Occlusion", occlusion);
// OR send to Wwise
AkSoundEngine.SetObjectObstructionAndOcclusion(
gameObject, AkSoundEngine.AK_INVALID_GAME_OBJECT,
occlusion, 0f);
}Multi-ray (more accurate):
- Cast 5-7 rays in a cone pattern from listener toward source
- Average the results for smoother occlusion transitions
- More CPU expensive but avoids binary pop between occluded/unoccluded
Physics-based propagation (Steam Audio, Wwise Spatial Audio):
- Full sound propagation simulation through geometry
- Handles diffraction (sound bending around edges), transmission through walls, and multi-path reflections
- Most realistic but highest CPU cost
- Best for VR or premium AAA titles
Reverb zones
Reverb simulates how sound bounces within an enclosed space. In games, reverb is applied per-zone:
Zone setup pattern
- Define zones as trigger volumes (box, sphere, or mesh collider)
- Each zone has a reverb preset: room size, decay time, wet/dry mix
- When the listener enters a zone, blend to that zone's reverb
- Use auxiliary sends in FMOD/Wwise to route audio through reverb buses
Common reverb presets
| Environment | Decay time | Pre-delay | Wet level | Character |
|---|---|---|---|---|
| Small room | 0.4-0.8s | 5ms | -10 dB | Tight, intimate |
| Large hall | 1.5-3.0s | 20ms | -6 dB | Spacious, cathedral |
| Cave | 2.0-4.0s | 30ms | -3 dB | Dark, echoing |
| Outdoor open | 0.1-0.3s | 0ms | -20 dB | Dry, minimal |
| Bathroom/tile | 0.8-1.5s | 5ms | -4 dB | Bright, reflective |
| Sewer/tunnel | 1.5-2.5s | 15ms | -5 dB | Metallic, resonant |
Blending between zones
When transitioning between zones (e.g., walking from a cave into open air):
- Cross-fade between reverb sends over 0.5-1.0 seconds
- Use portal-based blending if available (Wwise Spatial Audio rooms/portals)
- Never hard-cut between reverb presets - it sounds unnatural
Platform considerations
| Platform | Output | Recommended approach |
|---|---|---|
| PC (speakers) | Stereo/5.1/7.1 | Channel-based panning; HRTF optional for headphones |
| PC (headphones) | Binaural stereo | HRTF-based spatialization |
| Console (TV) | 5.1/7.1 Atmos | Channel-based or Dolby Atmos object audio |
| VR (Quest, PCVR) | Binaural stereo | HRTF mandatory; head tracking updates listener orientation |
| Mobile | Stereo (speakers/buds) | Simple panning; HRTF for earbuds if CPU allows |
VR-specific considerations
- Update listener position AND orientation every frame from the HMD
- Use room-scale HRTF (accounts for near-field sources < 1m)
- Haptic feedback for bass frequencies (controller rumble) enhances immersion
- Budget: 20-30 spatialized sources max on mobile VR (Quest)
Performance budgets
| Platform | Max simultaneous voices | HRTF sources | Budget |
|---|---|---|---|
| PC | 64-128 | 32-64 | 3-5% CPU |
| Console | 48-96 | 24-48 | 2-4% CPU |
| Mobile VR | 24-48 | 12-24 | 4-6% CPU |
| Mobile phone | 16-32 | 8-16 | 2-3% CPU |
Troubleshooting spatial audio
| Symptom | Likely cause | Fix |
|---|---|---|
| Sound doesn't move when turning | Listener orientation not updating | Update listener rotation every frame |
| Sound is always centered | Source and listener at same position | Ensure 3D attributes are set from actual world positions |
| Sound pops when crossing zone boundary | Hard reverb switch | Implement crossfade between reverb zones |
| HRTF sounds "inside head" | Source too close; no externalization | Add slight reverb or early reflections to externalize |
| Elevation not perceived | Using panning instead of HRTF | Switch to HRTF-based spatialization for headphone users |
| Occlusion pops on/off | Single raycast binary result | Use multi-ray averaging or interpolate occlusion value over time |
wwise-guide.md
Wwise Guide
Comprehensive reference for Audiokinetic Wwise integration in game projects, covering project structure, SoundBank workflow, RTPC, states, switches, and engine integration.
Installation and setup
Unity integration
- Install the Wwise Unity Integration from the Audiokinetic Launcher
- The launcher installs the plugin and creates a
WwiseProjectfolder - In Unity: Wwise > Wwise Settings, configure platform targets
- Generate SoundBanks from the Wwise Authoring Tool before running
- SoundBanks are placed in
Assets/StreamingAssets/Audio/GeneratedSoundBanks/
Unreal Engine integration
- Wwise has a built-in Unreal integration - install via Audiokinetic Launcher
- Set the Wwise Project path in Project Settings > Wwise
- Use AkComponent and AkAmbientSound actors for 3D sources
- SoundBanks auto-generate during build (or manually via Wwise Picker)
Core Wwise concepts
Object hierarchy
Project
|- Actor-Mixer Hierarchy (sound design: SFX, Foley, ambience)
| |- Work Units
| |- Actor-Mixers (logical grouping)
| |- Random Containers
| |- Sequence Containers
| |- Switch Containers
| |- Blend Containers
| |- Sounds
|- Interactive Music Hierarchy (adaptive music)
| |- Music Switch Containers
| |- Music Playlist Containers
| |- Music Segments
|- Events (triggers fired from code)
|- Game Syncs (RTPCs, states, switches, triggers)
|- SoundBanks (compiled output for runtime)
|- Busses (mixing hierarchy)Container types
| Container | Purpose | Example |
|---|---|---|
| Random | Play a random child each trigger | Footstep variations |
| Sequence | Play children in order | Dialogue lines, reload sequence |
| Switch | Select child based on a game switch | Surface material for footsteps |
| Blend | Crossfade between children based on RTPC | Wind intensity (calm to storm) |
| Music Switch | Transition between music states | Combat vs exploration music |
| Music Playlist | Sequence music segments with transitions | Level soundtrack |
Events
Events are the bridge between game code and audio content. An event contains one or more actions:
| Action | Description |
|---|---|
| Play | Start playing a sound object |
| Stop | Stop a playing sound |
| Pause / Resume | Pause/resume playback |
| Set Switch | Change a switch value |
| Set State | Change a state value |
| Set Game Parameter | Change an RTPC value |
Game Syncs
RTPC (Real-Time Parameter Control)
RTPCs are continuous parameters that modulate sound properties in real time.
Common RTPCs:
- Health (0-100) -> drives music intensity, heartbeat volume
- Speed (0-300) -> drives engine pitch, wind volume
- Distance (auto) -> built-in distance attenuation
- TimeOfDay (0-24) -> ambient sound blendMap RTPC values to properties:
- In the sound's Property Editor, right-click a property (Volume, Pitch, LPF)
- Add RTPC binding
- Draw a curve mapping RTPC input range to property output range
States
States are discrete, game-wide modes. Only one state per state group is active.
State Groups:
- PlayerState: Alive, Dead, Spectating
- Location: Indoor, Outdoor, Underwater, Cave
- GamePhase: Menu, Gameplay, Cutscene, PausedWhen a state changes, all sounds with state-based property overrides transition smoothly (configurable transition time per state group).
Switches
Switches are per-object selectors (unlike states which are global).
Switch Groups:
- Surface: Concrete, Wood, Metal, Grass, Water
- WeaponType: Pistol, Rifle, Shotgun, Melee
- EnemyType: Zombie, Robot, HumanSwitch Containers select which child to play based on the current switch value.
SoundBank workflow
SoundBanks are the compiled audio packages loaded at runtime.
Bank organization strategy
| Bank | Contents | Load timing |
|---|---|---|
| Init.bnk | Engine initialization data | Game startup (always first) |
| Common.bnk | UI sounds, player sounds, global events | Game startup |
| Music_Exploration.bnk | Exploration music | When entering exploration |
| Music_Combat.bnk | Combat music | When combat begins or level loads |
| Level_Forest.bnk | Forest-specific ambience and SFX | Scene load |
| VO_English.bnk | English voice-over | Based on language setting |
Code integration
// Unity + Wwise example
// Post an event (fire and forget)
AkSoundEngine.PostEvent("Play_Footstep", gameObject);
// Post an event with callback
AkSoundEngine.PostEvent("Play_Dialogue", gameObject,
(uint)AkCallbackType.AK_EndOfEvent, DialogueEndCallback, null);
// Set RTPC value
AkSoundEngine.SetRTPCValue("Health", playerHealth, gameObject);
// Set global RTPC
AkSoundEngine.SetRTPCValue("TimeOfDay", currentHour);
// Set Switch (per game object)
AkSoundEngine.SetSwitch("Surface", "Wood", gameObject);
// Set State (global)
AkSoundEngine.SetState("Location", "Underwater");
// Load/unload banks
AkBankManager.LoadBank("Level_Forest");
AkBankManager.UnloadBank("Level_Forest");Unreal integration
// Post event
UAkGameplayStatics::PostEvent(FootstepEvent, this, 0, FOnAkPostEventCallback());
// Set RTPC
UAkGameplayStatics::SetRTPCValue(nullptr, Health, 0, this, FString("Health"));
// Set Switch
UAkGameplayStatics::SetSwitch(SurfaceSwitchGroup, SurfaceSwitchValue, this);
// Set State
UAkGameplayStatics::SetState(LocationStateGroup, UnderwaterState);Adaptive music in Wwise
Music Switch Container setup
- Create a Music Switch Container
- Assign a State Group or Switch Group (e.g., CombatState: Peaceful, Alert, Combat)
- Add Music Playlist Containers as children - one per state
- Each playlist contains Music Segments (the actual music chunks)
- Define Transition Rules between states:
- Transition at next bar, next beat, next marker, or immediate
- Optional transition segment (stinger/bridge)
- Fade-in/fade-out curves
Transition matrix
-> Peaceful -> Alert -> Combat
Peaceful: N/A Next Bar Next Beat + Stinger
Alert: Next Bar N/A Next Beat
Combat: Next Bar Next Bar N/AVertical layering in Wwise
- Create a Music Segment with multiple tracks (layers)
- Use States or RTPCs to control each track's volume
- Example: drums layer fades in as RTPC "Intensity" rises above 0.5
- All layers share the same tempo/time signature and stay synchronized
Spatial audio in Wwise
Wwise Spatial Audio provides built-in room/portal simulation:
Rooms and portals
Setup:
1. Define AkRoom volumes in your scene (box or mesh colliders)
2. Place AkPortal at doorways between rooms
3. Each room references a reverb aux bus
4. Wwise automatically routes audio through portals
- Sound in adjacent room: audible through portal, with diffraction
- Sound in distant room: attenuated based on portal chainReflect plugin
For real-time early reflections:
- Enable Wwise Reflect on emitters that need reflections
- Define geometry (walls, floors) using AkGeometry components
- Reflect calculates early reflections based on actual scene geometry
- CPU cost scales with geometry complexity - use simplified collision mesh
Common pitfalls
| Issue | Cause | Fix |
|---|---|---|
| Init.bnk not found | Bank path misconfigured or not generated | Regenerate banks; verify StreamingAssets path |
| Event not found | Event not included in any SoundBank | Check SoundBank contents in Wwise; add event to bank |
| Sound plays from wrong position | Missing or stale AkGameObjectID | Ensure gameObject passed to PostEvent is correct |
| Memory overflow | Too many banks loaded simultaneously | Use per-scene bank loading; monitor with Wwise Profiler |
| Music transition sounds wrong | Transition rule misconfigured | Use Wwise Profiler to inspect transition; check rules |
| Switch not working | Switch set on wrong game object | Switches are per-object; verify the correct GameObject |
Frequently Asked Questions
What is game-audio?
Use this skill when designing or implementing audio systems for games - sound effects, adaptive music, spatial/3D audio, and middleware integration with FMOD or Wwise. Triggers on sound design, audio implementation, adaptive music systems, spatial audio, HRTF, audio middleware setup, sound event architecture, audio mixing, dynamic soundscapes, and game audio optimization. Covers FMOD Studio, Audiokinetic Wwise, and engine-native audio APIs.
How do I install game-audio?
Run npx skills add AbsolutelySkilled/AbsolutelySkilled --skill game-audio in your terminal. The skill will be immediately available in your AI coding agent.
What AI agents support game-audio?
game-audio works with claude-code, gemini-cli, openai-codex, mcp. Install it once and use it across any supported AI coding agent.