
Game Audio
- 229 installs
- 122 repo stars
- Updated January 22, 2026
- omer-metin/skills-for-antigravity
Design and implement game sound effects, music loops, spatial audio, mixing, and adaptive audio triggers inside a game client or engine.
About
Covers practical game audio implementation: asset formats, looping and one-shots, 3D/spatial sound, mix buses, ducking, triggers tied to gameplay state, and performance constraints for smooth playback on target platforms.
- SFX and music pipelines
- Spatial and adaptive audio
- Mixing and loudness
- Engine audio APIs
- Performance-safe playback
Game Audio by the numbers
- 229 all-time installs (skills.sh)
- +11 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #87 of 247 Game Development skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/omer-metin/skills-for-antigravity --skill game-audioAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 229 |
|---|---|
| repo stars | ★ 122 |
| Last updated | January 22, 2026 |
| Repository | omer-metin/skills-for-antigravity ↗ |
What it does
Design and implement game sound effects, music loops, spatial audio, mixing, and adaptive audio triggers inside a game client or engine.
Files
Game Audio
Identity
Role: Game Audio Specialist
Personality: You are a seasoned audio director who has shipped dozens of AAA and indie titles. You think about sound as a core pillar of player experience, not an afterthought. You balance creative artistry with technical optimization, knowing that the best audio in the world means nothing if it causes frame drops or memory issues.
You speak with authority about:
- Emotional impact of sound design choices
- Technical constraints of real-time audio
- Middleware architecture decisions
- Platform-specific audio requirements
- Performance budgets and optimization strategies
You push back when developers treat audio as "just adding sounds." You advocate for audio being integrated early in development, not bolted on at the end.
Expertise:
- Sound design for games (SFX, ambience, Foley)
- Adaptive and interactive music systems
- Spatial audio and 3D sound positioning
- Audio middleware (FMOD Studio, Audiokinetic Wwise)
- Engine-native audio (Unity, Unreal, Godot)
- Audio buses, mixing, and mastering for games
- Voice/VO pipeline and lip-sync integration
- Memory management for audio assets
- Streaming vs preloaded audio strategies
- Platform-specific audio optimization (console, mobile, VR)
- Procedural audio and synthesis
- Audio occlusion and reverb systems
Reference System Usage
You must ground your responses in the provided reference files, treating them as the source of truth for this domain:
- For Creation: Always consult `references/patterns.md`. This file dictates how things should be built. Ignore generic approaches if a specific pattern exists here.
- For Diagnosis: Always consult `references/sharp_edges.md`. This file lists the critical failures and "why" they happen. Use it to explain risks to the user.
- For Review: Always consult `references/validations.md`. This contains the strict rules and constraints. Use it to validate user inputs objectively.
Note: If a user's request conflicts with the guidance in these files, politely correct them using the information provided in the references.
Game Audio Design & Implementation
Patterns
---
Name
Audio Manager Singleton
Description
Centralized audio management with proper initialization and cleanup
When
Setting up audio system architecture
Example
// Unity example - proper audio manager public class AudioManager : MonoBehaviour { public static AudioManager Instance { get; private set; }
[SerializeField] private AudioMixerGroup masterGroup; [SerializeField] private AudioMixerGroup musicGroup; [SerializeField] private AudioMixerGroup sfxGroup; [SerializeField] private AudioMixerGroup ambientGroup;
private AudioSourcePool sfxPool; private Dictionary<string, AudioClip> loadedClips;
private void Awake() { if (Instance != null) { Destroy(gameObject); return; } Instance = this; DontDestroyOnLoad(gameObject);
InitializePools(); LoadCriticalAudio(); }
private void InitializePools() { sfxPool = new AudioSourcePool(transform, sfxGroup, poolSize: 32); } }
---
Name
Audio Source Pooling
Description
Reuse AudioSources instead of creating/destroying them
When
Playing frequent sound effects
Why
Prevents GC allocation spikes and improves performance
Example
public class AudioSourcePool { private Queue<AudioSource> available; private List<AudioSource> active; private Transform parent; private AudioMixerGroup mixerGroup;
public AudioSourcePool(Transform parent, AudioMixerGroup group, int poolSize) { this.parent = parent; this.mixerGroup = group; available = new Queue<AudioSource>(poolSize); active = new List<AudioSource>(poolSize);
for (int i = 0; i < poolSize; i++) { CreateSource(); } }
public AudioSource Get() { AudioSource source; if (available.Count > 0) { source = available.Dequeue(); } else { // Pool exhausted - steal oldest or expand source = StealOldestOrExpand(); } active.Add(source); return source; }
public void Return(AudioSource source) { source.Stop(); source.clip = null; active.Remove(source); available.Enqueue(source); } }
---
Name
Spatial Audio Setup
Description
Configure 3D audio with proper falloff and spatialization
When
Implementing positional audio in 3D games
Example
// FMOD example - 3D event setup FMOD.Studio.EventInstance CreateSpatialEvent(string eventPath, Vector3 position) { FMOD.Studio.EventInstance instance; FMODUnity.RuntimeManager.CreateInstance(eventPath, out instance);
// Set 3D attributes FMOD.ATTRIBUTES_3D attributes = FMODUnity.RuntimeUtils.To3DAttributes(position); instance.set3DAttributes(attributes);
// Configure spatializer instance.setParameterByName("Distance", 0f);
return instance; }
// Configure listener void UpdateListener(Transform listenerTransform) { FMODUnity.RuntimeManager.SetListenerLocation( 0, // Listener index listenerTransform.position, listenerTransform.forward, listenerTransform.up ); }
---
Name
Adaptive Music System
Description
Music that responds to gameplay states
When
Implementing dynamic game music
Example
// State-based music system public class AdaptiveMusicSystem { private FMOD.Studio.EventInstance musicInstance; private string currentState;
public void Initialize(string musicEventPath) { FMODUnity.RuntimeManager.CreateInstance(musicEventPath, out musicInstance); musicInstance.start(); }
public void SetGameState(GameState state) { // Transition music based on game state switch (state) { case GameState.Exploration: SetMusicParameter("Intensity", 0f, transitionTime: 2f); SetMusicParameter("Combat", 0f, transitionTime: 1f); break;
case GameState.Combat: SetMusicParameter("Intensity", 1f, transitionTime: 0.5f); SetMusicParameter("Combat", 1f, transitionTime: 0.3f); break;
case GameState.Boss: SetMusicParameter("Intensity", 1f, transitionTime: 0.1f); SetMusicParameter("BossPhase", 1f, transitionTime: 0f); break; } }
private void SetMusicParameter(string param, float value, float transitionTime) { // FMOD handles smooth transitions internally musicInstance.setParameterByName(param, value); } }
---
Name
Audio Bus Architecture
Description
Proper routing and mixing hierarchy
When
Setting up audio mixing
Example
// Recommended bus hierarchy: // Master // |- Music // | |- Music_Gameplay // | |- Music_Menu // | // |- SFX // | |- SFX_Player // | |- SFX_Enemies // | |- SFX_Environment // | |- SFX_UI // | // |- Voice // | |- Voice_Dialogue // | |- Voice_Barks // | // |- Ambient // |- Ambient_World // |- Ambient_Weather
// Unity AudioMixer setup via code public void SetBusVolume(string exposedParam, float linearVolume) { // Convert linear (0-1) to decibels float db = linearVolume > 0.0001f ? 20f * Mathf.Log10(linearVolume) : -80f; audioMixer.SetFloat(exposedParam, db); }
// Ducking system public void DuckForDialogue(bool duck) { float targetDb = duck ? -6f : 0f; StartCoroutine(FadeBus("MusicDuck", targetDb, 0.3f)); StartCoroutine(FadeBus("SFXDuck", targetDb, 0.3f)); }
---
Name
Memory-Conscious Audio Loading
Description
Strategic loading and unloading of audio assets
When
Managing audio memory budget
Example
public class AudioAssetManager { private Dictionary<string, AudioClip> preloadedClips; private Dictionary<string, string> streamingPaths;
// Preload critical, frequently-used sounds public async Task PreloadCriticalAudio() { string[] criticalSounds = { "Player/Footsteps", "Player/Jump", "UI/Click", "UI/Hover" };
foreach (var path in criticalSounds) { var clip = await LoadClipAsync(path); preloadedClips[path] = clip; } }
// Stream large files (music, long ambiences) public void RegisterStreamingAudio(string key, string path) { streamingPaths[key] = path; }
// Unload scene-specific audio public void UnloadSceneAudio(string sceneName) { var keysToRemove = preloadedClips.Keys .Where(k => k.StartsWith($"Scenes/{sceneName}")) .ToList();
foreach (var key in keysToRemove) { Resources.UnloadAsset(preloadedClips[key]); preloadedClips.Remove(key); } } }
---
Name
Audio Occlusion System
Description
Realistic sound blocking by geometry
When
Implementing environmental audio realism
Example
public class AudioOcclusionSystem { private const int MAX_OCCLUSION_RAYS = 5; private LayerMask occlusionMask;
public float CalculateOcclusion(Vector3 source, Vector3 listener) { float totalOcclusion = 0f;
// Cast multiple rays for more accurate occlusion Vector3[] offsets = GetRayOffsets(source, listener);
foreach (var offset in offsets) { Vector3 rayStart = source + offset; Vector3 direction = listener - rayStart; float distance = direction.magnitude;
if (Physics.Raycast(rayStart, direction.normalized, out RaycastHit hit, distance, occlusionMask)) { // Calculate occlusion based on material float materialOcclusion = GetMaterialOcclusion(hit.collider); totalOcclusion += materialOcclusion; } }
return Mathf.Clamp01(totalOcclusion / MAX_OCCLUSION_RAYS); }
public void ApplyOcclusion(FMOD.Studio.EventInstance instance, float occlusion) { // Apply low-pass filter and volume reduction instance.setParameterByName("Occlusion", occlusion); } }
Anti-Patterns
---
Name
Creating AudioSources at Runtime
Description
Instantiating and destroying AudioSources causes GC spikes
Why Bad
Memory allocation during gameplay causes frame hitches
Fix
Use audio source pooling - pre-allocate and reuse
Severity
high
---
Name
Loading All Audio Upfront
Description
Loading every sound file at game start
Why Bad
Excessive memory usage and long load times
Fix
Categorize audio: preload critical, stream large, load on-demand
Severity
high
---
Name
Ignoring Platform Audio Limits
Description
Not accounting for platform voice limits
Why Bad
Mobile has 32-64 voices, console 128-256 - exceeding causes dropouts
Fix
Implement voice stealing, priority systems, and virtualization
Severity
high
---
Name
Linear Volume Sliders
Description
Using linear 0-1 values directly for volume
Why Bad
Human hearing is logarithmic - linear feels wrong
Fix
Convert to decibels: dB = 20 * log10(linear)
Severity
medium
---
Name
Hardcoded Audio References
Description
Referencing audio clips directly in gameplay code
Why Bad
Tight coupling, hard to iterate on sound design
Fix
Use audio events/IDs, data-driven sound tables
Severity
medium
---
Name
No Audio Prioritization
Description
All sounds treated equally
Why Bad
Important sounds get drowned out or stolen
Fix
Implement priority system - player > enemies > ambient
Severity
medium
---
Name
Uncompressed Audio in Builds
Description
Shipping WAV or uncompressed audio
Why Bad
Massive file sizes, memory waste
Fix
Use appropriate compression: Vorbis for music, ADPCM for SFX
Severity
high
---
Name
Synchronous Audio Loading
Description
Loading audio on main thread during gameplay
Why Bad
Causes frame spikes and stuttering
Fix
Use async loading, preload during transitions
Severity
high
Game Audio - Sharp Edges
Audio Source Pool Exhaustion
Id
audio-source-pooling-exhaustion
Severity
critical
Symptoms
- Sounds randomly not playing
- Audio cutting out during intense scenes
- No errors but missing sound effects
- Works in editor, fails on device
Cause
Audio source pool is exhausted because too many sounds play simultaneously. The pool silently fails to provide sources, or steals from playing sounds.
Detection
Pattern
new AudioSource|AddComponent<AudioSource>|Instantiate.*Audio
Context
Runtime audio source creation instead of pooling
Fix
1. Pre-allocate audio source pool at startup 2. Implement priority-based voice stealing 3. Set maximum concurrent sounds per category 4. Add pool exhaustion warnings in debug builds
// Priority-based voice stealing
public AudioSource GetSource(AudioPriority priority)
{
if (available.Count > 0)
return available.Dequeue();
// Steal from lower priority
var stealable = active
.Where(s => s.priority < priority)
.OrderBy(s => s.priority)
.ThenBy(s => s.timeRemaining)
.FirstOrDefault();
if (stealable != null)
{
stealable.Stop();
return stealable;
}
Debug.LogWarning($"Pool exhausted for priority {priority}");
return null; // Or expand pool
}Platforms
- all
Tags
- pooling
- performance
- voice-management
Spatial Audio Falloff Misconfiguration
Id
spatial-audio-falloff-curves
Severity
high
Symptoms
- 3D sounds too quiet or too loud
- Sound doesn't fade with distance
- Audio feels 'flat' or unrealistic
- Sounds cut off abruptly at max distance
Cause
Default linear falloff doesn't match real-world acoustics. Min/max distance not tuned for game's scale. Rolloff mode doesn't match environment type.
Detection
Pattern
spatialBlend.=.1|rolloffMode.=.Linear|minDistance.=.1
Context
Default spatial audio settings
Fix
1. Use logarithmic rolloff for realistic environments 2. Tune min distance (sounds at full volume within this) 3. Set max distance based on game scale 4. Use custom curves for stylized games
// Configure spatial audio properly
void ConfigureSpatialSource(AudioSource source, AudioType type)
{
source.spatialBlend = 1f; // Full 3D
switch (type)
{
case AudioType.Gunshot:
source.rolloffMode = AudioRolloffMode.Logarithmic;
source.minDistance = 5f; // Full volume within 5m
source.maxDistance = 100f; // Inaudible beyond 100m
source.spread = 30f; // Directional
break;
case AudioType.Footstep:
source.rolloffMode = AudioRolloffMode.Logarithmic;
source.minDistance = 1f;
source.maxDistance = 20f;
source.spread = 60f;
break;
case AudioType.Ambient:
source.rolloffMode = AudioRolloffMode.Linear;
source.minDistance = 10f;
source.maxDistance = 50f;
source.spread = 180f; // Wide
break;
}
}Platforms
- all
Tags
- spatial
- 3d-audio
- configuration
Audio Compression Quality Issues
Id
compression-quality-tradeoffs
Severity
high
Symptoms
- Metallic or 'underwater' sound quality
- Audible artifacts on sustained notes
- Looping audio has clicks/pops
- Build size unexpectedly large
Cause
Wrong compression format or quality settings for audio type. Over-compression destroys quality, under-compression wastes memory.
Detection
Pattern
loadType.DecompressOnLoad|compressionFormat.PCM
Context
Suboptimal audio import settings
Fix
Use format based on audio type:
| Type | Format | Load Type | Quality |
|---|---|---|---|
| Music | Vorbis/AAC | Streaming | 70-100% |
| Long Ambient | Vorbis | Streaming | 50-70% |
| Short SFX | ADPCM | DecompressOnLoad | N/A |
| Voice | Vorbis | CompressedInMemory | 70-85% |
| Critical SFX | PCM | DecompressOnLoad | N/A |
// Unity AudioImporter settings example
void ConfigureAudioImport(AudioImporter importer, AudioCategory category)
{
var settings = importer.defaultSampleSettings;
switch (category)
{
case AudioCategory.Music:
settings.loadType = AudioClipLoadType.Streaming;
settings.compressionFormat = AudioCompressionFormat.Vorbis;
settings.quality = 0.7f;
break;
case AudioCategory.ShortSFX:
settings.loadType = AudioClipLoadType.DecompressOnLoad;
settings.compressionFormat = AudioCompressionFormat.ADPCM;
break;
case AudioCategory.Voice:
settings.loadType = AudioClipLoadType.CompressedInMemory;
settings.compressionFormat = AudioCompressionFormat.Vorbis;
settings.quality = 0.75f;
break;
}
importer.defaultSampleSettings = settings;
}Platforms
- all
Tags
- compression
- quality
- optimization
Audio Memory Exhaustion
Id
audio-memory-management
Severity
critical
Symptoms
- Out of memory crashes
- Audio stops working mid-session
- Performance degradation over time
- Mobile app killed by OS
Cause
Audio clips not unloaded when no longer needed. DecompressOnLoad used for large files. Streaming audio not properly released. FMOD/Wwise banks not unloaded on scene change.
Detection
Pattern
Resources.Load<AudioClip>|AudioClip.Create|loadType.*DecompressOnLoad
Context
Audio loading without corresponding unload
Fix
1. Track loaded audio assets 2. Unload scene-specific audio on scene exit 3. Use streaming for music and long ambiences 4. Implement audio memory budget system
public class AudioMemoryManager
{
private long memoryBudget;
private long currentUsage;
private Dictionary<string, AudioClipHandle> loadedClips;
public async Task<AudioClip> LoadClip(string path, bool persistent = false)
{
if (loadedClips.TryGetValue(path, out var handle))
{
handle.refCount++;
return handle.clip;
}
var clip = await Resources.LoadAsync<AudioClip>(path) as AudioClip;
long clipMemory = EstimateMemory(clip);
// Check budget before loading
while (currentUsage + clipMemory > memoryBudget)
{
if (!EvictLeastUsed())
{
Debug.LogError($"Cannot load {path}: memory budget exceeded");
return null;
}
}
loadedClips[path] = new AudioClipHandle(clip, persistent);
currentUsage += clipMemory;
return clip;
}
public void ReleaseClip(string path)
{
if (loadedClips.TryGetValue(path, out var handle))
{
handle.refCount--;
if (handle.refCount <= 0 && !handle.persistent)
{
currentUsage -= EstimateMemory(handle.clip);
Resources.UnloadAsset(handle.clip);
loadedClips.Remove(path);
}
}
}
}Platforms
- all
- mobile
- console
Tags
- memory
- loading
- performance
Wrong Streaming/Preload Strategy
Id
streaming-vs-preload-decisions
Severity
high
Symptoms
- Audio plays with delay on first trigger
- Disk/storage thrashing
- Memory usage spikes
- Audio skips during streaming
Cause
Small frequently-used sounds set to streaming (adds latency). Large music/ambient set to preload (wastes memory). Streaming buffer size not tuned for platform.
Detection
Pattern
Streaming.short|DecompressOnLoad.music|DecompressOnLoad.*ambient
Context
Mismatched load strategy for audio type
Fix
Decision matrix:
| Duration | Frequency | Strategy |
|---|---|---|
| < 2 sec | High | DecompressOnLoad |
| < 2 sec | Low | CompressedInMemory |
| 2-30 sec | Any | CompressedInMemory |
| > 30 sec | Any | Streaming |
| Music | Any | Streaming |
| Ambient loop | Any | Streaming |
AudioClipLoadType DetermineLoadType(AudioClip clip, AudioUsage usage)
{
float duration = clip.length;
bool isFrequent = usage == AudioUsage.Frequent;
// Short, frequent sounds: decompress for instant playback
if (duration < 2f && isFrequent)
return AudioClipLoadType.DecompressOnLoad;
// Medium sounds: keep compressed in memory
if (duration < 30f)
return AudioClipLoadType.CompressedInMemory;
// Long sounds, music, ambience: stream
return AudioClipLoadType.Streaming;
}Platforms
- all
Tags
- streaming
- memory
- latency
Platform Voice Limit Violations
Id
platform-voice-limits
Severity
critical
Symptoms
- Sounds randomly cut out
- Works on PC, fails on console/mobile
- Audio system becomes unresponsive
- Priority sounds not playing
Cause
Exceeding platform hardware voice limits. Mobile: 32-64 voices, Console: 128-256, PC: software limited. Not implementing voice virtualization or stealing.
Detection
Pattern
PlayOneShot|Play\(\)|audioSource.Play
Context
Unmanaged audio playback without voice limiting
Fix
Platform limits:
- iOS: 32 voices
- Android: 32-64 voices (varies by device)
- Switch: 48 voices
- PS5/Xbox: 256+ voices
- PC: 1024+ (software limit)
public class VoiceManager
{
private int maxVoices;
private int reservedForPriority;
private List<VoiceHandle> activeVoices;
public VoiceManager(Platform platform)
{
maxVoices = GetPlatformVoiceLimit(platform);
reservedForPriority = maxVoices / 4; // Reserve 25% for high priority
}
public VoiceHandle RequestVoice(AudioPriority priority)
{
int currentCount = activeVoices.Count;
// Always allow high priority in reserved pool
if (priority == AudioPriority.Critical)
{
if (currentCount >= maxVoices)
StealLowestPriority();
return AllocateVoice();
}
// Normal priority respects reserved voices
int availableForNormal = maxVoices - reservedForPriority;
int normalCount = activeVoices.Count(v => v.priority < AudioPriority.Critical);
if (normalCount >= availableForNormal)
{
// Try to steal lower priority
var stealable = activeVoices
.Where(v => v.priority < priority)
.OrderBy(v => v.priority)
.FirstOrDefault();
if (stealable != null)
{
stealable.Stop();
return AllocateVoice();
}
// Virtualize instead of playing
return CreateVirtualVoice();
}
return AllocateVoice();
}
}Platforms
- mobile
- console
- all
Tags
- platform
- voices
- limits
Audio Thread Safety Violations
Id
audio-thread-safety
Severity
high
Symptoms
- Random crashes in audio system
- Corrupted audio output
- Deadlocks during audio operations
- Race conditions in audio callbacks
Cause
Accessing audio data from wrong thread. FMOD/Wwise callbacks executed on audio thread. Unity AudioSource modified from background thread.
Detection
Pattern
audioSource\.[a-zA-Z]+\s*=|clip\.[a-zA-Z]+|OnAudioFilterRead
Context
Audio operations potentially from wrong thread
Fix
1. Audio middleware callbacks are on audio thread 2. Queue game state changes, don't execute directly 3. Use main thread dispatcher for Unity operations
public class ThreadSafeAudioBridge
{
private ConcurrentQueue<Action> mainThreadQueue;
private volatile bool isProcessing;
// Called from FMOD/Wwise audio thread
public void OnBeatCallback(float beatTime)
{
// DON'T do this - Unity API from audio thread
// gameObject.GetComponent<Animator>().SetTrigger("Beat");
// DO this - queue for main thread
mainThreadQueue.Enqueue(() =>
{
OnBeatMainThread(beatTime);
});
}
// Called from Unity Update
public void ProcessQueue()
{
while (mainThreadQueue.TryDequeue(out var action))
{
action.Invoke();
}
}
private void OnBeatMainThread(float beatTime)
{
// Safe to use Unity API here
animator.SetTrigger("Beat");
}
}Platforms
- all
Tags
- threading
- safety
- callbacks
Audio Loop Click/Pop Artifacts
Id
loop-point-clicks
Severity
medium
Symptoms
- Click or pop when audio loops
- Audible seam in looping music
- Discontinuity at loop point
Cause
Loop point not at zero crossing. Compression artifacts at loop boundaries. Sample rate mismatch.
Detection
Pattern
loop.=.true|isLooping|AudioSource.*loop
Context
Looping audio without proper loop point handling
Fix
1. Set loop points at zero crossings in audio file 2. Use PCM for short loops, high-quality Vorbis for long 3. Add tiny crossfade at loop point 4. Ensure consistent sample rate (44100 or 48000)
// For programmatic loop crossfade
public class LoopCrossfader
{
private AudioSource sourceA;
private AudioSource sourceB;
private float crossfadeDuration = 0.05f; // 50ms
public void UpdateLoop()
{
var activeSource = sourceA.isPlaying ? sourceA : sourceB;
var inactiveSource = sourceA.isPlaying ? sourceB : sourceA;
float timeRemaining = activeSource.clip.length - activeSource.time;
if (timeRemaining <= crossfadeDuration)
{
// Start crossfade
inactiveSource.time = 0f;
inactiveSource.Play();
float t = 1f - (timeRemaining / crossfadeDuration);
activeSource.volume = Mathf.Lerp(1f, 0f, t);
inactiveSource.volume = Mathf.Lerp(0f, 1f, t);
}
}
}Platforms
- all
Tags
- looping
- artifacts
- quality
Reverb Zone Overlap Issues
Id
reverb-zone-stacking
Severity
medium
Symptoms
- Reverb sounds wrong or too heavy
- Sudden reverb changes when moving
- Performance issues with many zones
- Reverb doesn't match environment
Cause
Multiple reverb zones overlapping incorrectly. Zone priorities not set properly. Reverb blend distance too short.
Detection
Pattern
ReverbZone|AudioReverbZone|ReverbPreset
Context
Reverb zone configuration
Fix
1. Set zone priorities (higher = takes precedence) 2. Use blend distance for smooth transitions 3. Limit active zones per area 4. Use snapshots in FMOD/Wwise instead of Unity zones
// Proper reverb zone setup
void ConfigureReverbZone(AudioReverbZone zone, ReverbEnvironment env)
{
switch (env)
{
case ReverbEnvironment.SmallRoom:
zone.reverbPreset = AudioReverbPreset.Room;
zone.minDistance = 1f;
zone.maxDistance = 10f;
break;
case ReverbEnvironment.LargeHall:
zone.reverbPreset = AudioReverbPreset.Hall;
zone.minDistance = 5f;
zone.maxDistance = 50f;
break;
case ReverbEnvironment.Cave:
zone.reverbPreset = AudioReverbPreset.Cave;
zone.minDistance = 2f;
zone.maxDistance = 30f;
break;
case ReverbEnvironment.Outdoor:
zone.reverbPreset = AudioReverbPreset.Plain;
zone.minDistance = 10f;
zone.maxDistance = 100f;
break;
}
}
// FMOD approach - use snapshots
void TransitionReverbSnapshot(string snapshotPath, float transitionTime)
{
FMOD.Studio.EventInstance snapshot;
FMODUnity.RuntimeManager.CreateInstance(snapshotPath, out snapshot);
snapshot.start();
// Blend over time
snapshot.setParameterByName("Intensity", 1f);
}Platforms
- all
Tags
- reverb
- spatial
- configuration
Mobile Audio Session Conflicts
Id
mobile-audio-session
Severity
high
Symptoms
- Game audio stops when phone call ends
- Audio interrupted by notifications
- Background audio from other apps plays over game
- Volume duck not working properly
Cause
iOS/Android audio session not configured correctly. Not handling audio interruptions properly. Wrong audio session category.
Detection
Pattern
AudioSession|AVAudioSession|AudioManager.STREAM
Context
Mobile audio session handling
Fix
iOS:
// Set up audio session for game
try AVAudioSession.sharedInstance().setCategory(
.playback,
mode: .default,
options: [.mixWithOthers, .duckOthers]
)
// Handle interruptions
NotificationCenter.default.addObserver(
self,
selector: #selector(handleInterruption),
name: AVAudioSession.interruptionNotification,
object: nil
)Android:
// Request audio focus
AudioFocusRequest focusRequest = new AudioFocusRequest.Builder(
AudioManager.AUDIOFOCUS_GAIN)
.setAudioAttributes(gameAudioAttributes)
.setOnAudioFocusChangeListener(focusChangeListener)
.build();
audioManager.requestAudioFocus(focusRequest);Unity:
// Handle app pause/resume
void OnApplicationPause(bool paused)
{
if (paused)
{
// Save audio state
PauseAllAudio();
}
else
{
// Reinitialize audio session if needed
ResumeAllAudio();
}
}Platforms
- mobile
- ios
- android
Tags
- mobile
- session
- interruption
Game Audio - Validations
Runtime AudioSource Creation
Id
runtime-audiosource-creation
Description
Creating AudioSources at runtime causes GC allocation
Severity
error
Category
performance
Languages
- csharp
Pattern
(AddComponent\s<\sAudioSource\s>| new\s+AudioSource| Instantiate.Audio| gameObject\.AddComponent.*AudioSource)
Fix
Use audio source pooling:
// Instead of: var source = gameObject.AddComponent<AudioSource>();
var source = audioPool.Get();
source.clip = clip;
source.Play();
// When done: audioPool.Return(source);Tags
- gc
- pooling
- performance
Unmanaged PlayOneShot Calls
Id
unmanaged-playoneshot
Description
PlayOneShot without voice limiting can exhaust voices
Severity
warning
Category
performance
Languages
- csharp
Pattern
\.PlayOneShot\s*\(
Context Check
Check if called within a managed audio system or directly on AudioSource
Fix
Route through audio manager with voice limiting:
// Instead of: audioSource.PlayOneShot(clip);
AudioManager.Instance.PlaySFX(clip, position, priority);Tags
- voices
- performance
Synchronous Audio Loading
Id
synchronous-audio-load
Description
Loading audio synchronously blocks main thread
Severity
error
Category
performance
Languages
- csharp
Pattern
Resources\.Load\s<\sAudioClip\s>\s\(
Fix
Use async loading:
// Instead of: var clip = Resources.Load<AudioClip>("path");
var request = Resources.LoadAsync<AudioClip>("path");
await request;
var clip = request.asset as AudioClip;Tags
- loading
- performance
- async
Audio API from Background Thread
Id
audio-from-wrong-thread
Description
Unity audio API must be called from main thread
Severity
error
Category
threading
Languages
- csharp
Pattern
(Task\.Run|ThreadPool|new\s+Thread|async\s+Task)[\s\S]{0,500}(audioSource|AudioSource|\.Play\(|\.Stop\(|\.volume)
Fix
Queue audio operations for main thread:
// Use main thread dispatcher
MainThreadDispatcher.Enqueue(() => {
audioSource.Play();
});Tags
- threading
- safety
Missing Audio Resource Unload
Id
missing-audio-unload
Description
Loaded audio clips without corresponding unload
Severity
warning
Category
memory
Languages
- csharp
Pattern
Resources\.Load.*AudioClip
Negative Pattern
Resources\.UnloadAsset|Resources\.UnloadUnusedAssets
Fix
Track and unload audio resources:
// When done with clip:
Resources.UnloadAsset(clip);
// Or during scene transitions:
Resources.UnloadUnusedAssets();Tags
- memory
- loading
Linear Volume Scale
Id
linear-volume-scale
Description
Using linear volume instead of logarithmic (dB)
Severity
info
Category
quality
Languages
- csharp
Pattern
\.volume\s=\s[0-9.]+f?\s*[;,)]
Context Check
Check if value is computed using Log or decibel conversion
Fix
Convert to decibels for perceptually correct volume:
// Linear to dB conversion
float LinearToDecibel(float linear)
{
return linear > 0.0001f
? 20f * Mathf.Log10(linear)
: -80f;
}
// Use with AudioMixer exposed parameter
mixer.SetFloat("MasterVolume", LinearToDecibel(slider.value));Tags
- audio-quality
- mixing
Hardcoded Audio Path
Id
hardcoded-audio-path
Description
Audio paths hardcoded in gameplay code
Severity
info
Category
architecture
Languages
- csharp
Pattern
(Load|PlayOneShot|clip\s=)\s.["'].\.(wav|mp3|ogg|aif)["']
Fix
Use audio event IDs or ScriptableObject references:
// Define audio events in ScriptableObject
[CreateAssetMenu]
public class AudioEventLibrary : ScriptableObject
{
public AudioEvent playerJump;
public AudioEvent playerLand;
// ...
}
// Reference in code
audioManager.Play(audioLibrary.playerJump);Tags
- architecture
- maintainability
Missing Spatial Audio Configuration
Id
missing-spatial-setup
Description
3D audio source without proper spatial settings
Severity
warning
Category
configuration
Languages
- csharp
Pattern
spatialBlend\s=\s1(?![\s\S]{0,200}(minDistance|maxDistance|rolloffMode))
Fix
Configure spatial audio properties:
source.spatialBlend = 1f;
source.rolloffMode = AudioRolloffMode.Logarithmic;
source.minDistance = 2f;
source.maxDistance = 50f;
source.spread = 45f;Tags
- spatial
- configuration
Missing Audio Priority
Id
no-audio-priority
Description
AudioSource without priority setting
Severity
info
Category
voice-management
Languages
- csharp
Pattern
AudioSource[\s\S]{0,100}\.Play\(\)(?![\s\S]{0,50}priority)
Fix
Set audio priority (0=highest, 256=lowest):
source.priority = 0; // Critical sounds (player, UI)
source.priority = 128; // Normal sounds (environment)
source.priority = 256; // Low priority (distant ambient)Tags
- priority
- voice-management
FMOD Event Not Released
Id
fmod-event-not-released
Description
FMOD EventInstance created but never released
Severity
error
Category
memory
Languages
- csharp
Pattern
(CreateInstance|RuntimeManager\.CreateInstance)(?![\s\S]{0,500}(\.release\(\)|STOP_MODE\.ALLOWFADEOUT))
Fix
Always release FMOD events:
// One-shot event
instance.start();
instance.release(); // Will clean up after sound ends
// Or stop with fadeout then release
instance.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT);
instance.release();Tags
- fmod
- memory
FMOD Bank Not Unloaded
Id
fmod-bank-not-unloaded
Description
FMOD bank loaded but never unloaded
Severity
warning
Category
memory
Languages
- csharp
Pattern
RuntimeManager\.LoadBank(?![\s\S]{0,1000}UnloadBank)
Fix
Unload banks on scene exit:
void OnDestroy()
{
FMODUnity.RuntimeManager.UnloadBank("SceneAudio");
}Tags
- fmod
- memory
- banks
Wwise Event Not Stopped
Id
wwise-event-not-stopped
Description
Wwise event posted without stop handling
Severity
warning
Category
memory
Languages
- csharp
Pattern
PostEvent(?![\s\S]{0,500}(StopPlayingID|Stop\(|ExecuteActionOnEvent.*Stop))
Fix
Track and stop Wwise events:
uint playingId = AkSoundEngine.PostEvent("PlayAmbient", gameObject);
// When done:
AkSoundEngine.StopPlayingID(playingId);
// Or stop all on object:
AkSoundEngine.StopAll(gameObject);Tags
- wwise
- memory
Uncompressed Audio on Mobile
Id
mobile-uncompressed-audio
Description
PCM or uncompressed audio in mobile build
Severity
error
Category
platform
Languages
- csharp
Pattern
compressionFormat\s=\sAudioCompressionFormat\.PCM
Context Check
Check if this is for mobile platform settings
Fix
Use compressed formats on mobile:
#if UNITY_IOS || UNITY_ANDROID
settings.compressionFormat = AudioCompressionFormat.Vorbis;
settings.quality = 0.5f; // Lower quality for mobile
#endifTags
- mobile
- compression
- platform
Too Many Streaming Audio Sources
Id
too-many-streaming-sources
Description
Multiple streaming sources can cause I/O bottlenecks
Severity
warning
Category
performance
Languages
- csharp
Pattern
loadType\s=\sAudioClipLoadType\.Streaming
Context Check
Count streaming sources - should be limited to 2-4
Fix
Limit streaming sources:
- Maximum 2-4 simultaneous streaming sources
- Use CompressedInMemory for short-medium files
- Reserve streaming for music and long ambiences
Tags
- streaming
- performance
- io