Audio Sources
Learn how to use the AudioSource component to play sounds with volume, pitch, looping, and playback controls.
The AudioSource component enables entities to emit sounds. It supports both 2D ambient audio and 3D spatial audio with full control over playback parameters.
Component Properties#
| Property | Type | Default | Description |
|---|---|---|---|
| assetId | number | 0 | Asset ID of the audio clip to play. Assign from the Assets panel. |
| playing | boolean | false | Playback state. Set to true to play, false to pause. |
| volume | number | 1.0 | Volume level (0.0 to 1.0). Affected by channel mixer volumes. |
| pitch | number | 1.0 | Playback speed multiplier (0.01 to 4.0). 1.0 is normal speed, 2.0 is double speed. |
| loop | boolean | false | Whether the sound should loop when it reaches the end. |
| spatial | boolean | true | Enable 3D spatial audio. When false, plays as 2D ambient sound. |
| spatialBlend | number | 1.0 | Blend between 2D (0.0) and 3D (1.0) audio. Intermediate values create hybrid sounds. |
| group | AudioChannel | SFX | Audio channel for routing: SFX (0), Music (1), or Voice (2). |
| refDistance | number | 1.0 | Reference distance for volume rolloff. Sound is at full volume within this distance. |
| maxDistance | number | 10000 | Maximum audible distance. Sound is inaudible beyond this distance. |
| rolloffFactor | number | 1.0 | Distance attenuation factor. Higher values make sound drop off faster. |
Basic Playback#
To play a simple sound effect:
- Create an entity or select an existing one
- Add the
AudioSourcecomponent - Import an audio file and assign it to Asset ID
- Set Playing to
true - Adjust Volume if needed (0.0 to 1.0)
One-Shot vs Persistent
For one-shot sound effects (explosion, gunshot, footstep), use the SoundManager API from scripts instead of AudioSource. AudioSource is best for persistent, looping sounds like music or ambient effects.
Looping Audio#
Enable the loop property to make sounds repeat continuously:
import { AudioSource } from '@web-engine-dev/core'; // In your update loop or scriptexport default (api) => { return { onStart() { // Set up looping background music AudioSource.assetId[api.entity] = musicAssetId; AudioSource.volume[api.entity] = 0.5; AudioSource.loop[api.entity] = 1; // Enable looping AudioSource.playing[api.entity] = 1; // Start playing AudioSource.group[api.entity] = 1; // Music channel } };};Looping is perfect for:
- Background music tracks
- Ambient environmental sounds (wind, water, fire)
- Engine sounds for vehicles
- Continuous machinery or technology sounds
Volume and Pitch Control#
Volume#
The volume property controls the base volume level before channel mixing. The final volume is:
// Final volume calculationfinalVolume = source.volume * channel.volume // SFX, Music, or Voice * master.volume // Master volume * (spatial ? distance attenuation : 1.0) * (spatial ? LOD multiplier : 1.0);Volume ranges from 0.0 (silent) to 1.0 (full volume):
- 1.0 — Full volume (default)
- 0.7 — Moderate volume (good for background music)
- 0.5 — Half volume
- 0.3 — Quiet ambient sounds
- 0.0 — Muted
Pitch#
The pitch property controls playback speed, which affects both pitch and duration:
- 2.0 — Double speed, one octave up, half duration
- 1.5 — 1.5× speed, higher pitch
- 1.0 — Normal speed (default)
- 0.75 — Slow motion, lower pitch
- 0.5 — Half speed, one octave down, double duration
// Randomize pitch for variationconst randomPitch = 0.9 + Math.random() * 0.2; // 0.9 to 1.1AudioSource.pitch[entity] = randomPitch; // Gradual pitch shift for engine soundsconst enginePitch = 0.5 + (speed / maxSpeed) * 1.5;AudioSource.pitch[entity] = enginePitch;Pitch Clamping
Pitch is clamped to the range 0.01 to 4.0 to prevent extreme values that could cause audio artifacts or performance issues.
Playback Timing#
Control when sounds start and stop by toggling the playingproperty:
export default (api) => { let soundTimer = 0; const soundInterval = 3.0; // Play every 3 seconds return (dt) => { soundTimer += dt; if (soundTimer >= soundInterval) { soundTimer = 0; // Start playing AudioSource.playing[api.entity] = 1; // Stop after 1 second setTimeout(() => { AudioSource.playing[api.entity] = 0; }, 1000); } };};2D vs 3D Audio#
The spatial property determines whether audio is affected by position and distance:
2D Audio (spatial = false)#
- Plays at consistent volume regardless of position
- No panning or distance attenuation
- Perfect for UI sounds, music, and global effects
- Lower CPU overhead than 3D audio
3D Audio (spatial = true)#
- Volume decreases with distance from listener
- HRTF panning for realistic directional audio
- Requires AudioListener component on camera
- Best for environmental sounds and world objects
// 2D UI button click soundAudioSource.spatial[buttonEntity] = 0;AudioSource.volume[buttonEntity] = 0.8;AudioSource.playing[buttonEntity] = 1; // 3D campfire soundAudioSource.spatial[campfireEntity] = 1;AudioSource.refDistance[campfireEntity] = 5.0;AudioSource.maxDistance[campfireEntity] = 50.0;AudioSource.loop[campfireEntity] = 1;AudioSource.playing[campfireEntity] = 1;Spatial Blend#
The spatialBlend property creates a hybrid between 2D and 3D audio by adjusting how much position affects the sound:
- 0.0 — Pure 2D audio (no spatial effects)
- 0.5 — Blend of 2D and 3D (subtle spatial effects)
- 1.0 — Pure 3D audio (full spatial effects, default)
// Music that has subtle spatial positioning// but doesn't fade out completely when far awayAudioSource.spatial[musicEntity] = 1;AudioSource.spatialBlend[musicEntity] = 0.3; // Mostly 2D, slightly 3DAudioSource.refDistance[musicEntity] = 1000; // Very large ref distanceAudioSource.maxDistance[musicEntity] = 2000;Use Case
Spatial blend is useful for sounds that should have directionality but remain audible at long distances, like background music or ambient atmosphere.
Channel Routing#
Route audio to different mixer channels using the groupproperty:
- SFX (0) — Sound effects, impacts, weapons, UI
- Music (1) — Background music, themes
- Voice (2) — Dialogue, narration, voice-overs
import { AudioChannel } from '@web-engine-dev/core'; // Sound effectAudioSource.group[explosionEntity] = AudioChannel.SFX; // 0 // Background musicAudioSource.group[musicEntity] = AudioChannel.Music; // 1 // Character dialogueAudioSource.group[dialogueEntity] = AudioChannel.Voice; // 2Channel volumes can be controlled globally through the AudioMixer, allowing players to adjust SFX, Music, and Voice independently.
Best Practices#
- Use SoundManager for one-shots — Play(), not AudioSource, for single-fire sounds
- Pool your sounds — Reuse AudioSource entities instead of creating new ones
- Set appropriate distances — Use realistic refDistance and maxDistance values
- Choose the right channel — Route sounds to SFX, Music, or Voice appropriately
- Adjust for gameplay — Lower volume for ambient sounds, higher for important cues
- Test spatial audio — Move camera around to verify 3D positioning works correctly
- Use pitch variation — Add randomness to avoid repetitive sounds