volume-highSound Effects

Play one-shot and positional sound effects (and simple looping audio).

Use the SFX API to play short sound effects (UI clicks, footsteps, impacts) and simple looping audio (ambient loops, music).

circle-exclamation

Quick start (play a sound)

click := get_asset(SFX_Asset, "sfx/click.wav");

desc := SFX.default_sfx_desc();
SFX.play(click, desc);

SFX API reference

SFX_Asset :: class : Asset {}

SFX_Desc_Flags :: enum {
    POSITIONAL :: 1 << 0;
}

SFX_Channel :: enum {
    SFX;
    MUSIC;
}

SFX_Desc :: struct {
    flags:            SFX_Desc_Flags;
    position:         v2 #read_only;
    delay:            float;
    volume:           float;
    speed:            float;
    volume_perturb:   float;
    speed_perturb:    float;
    range_multiplier: float;
    loop_timeout:     float;
    entity_to_follow: u64;
    loop:             bool;
    channel:          SFX_Channel;

    set_position :: method(p: v2);
}

SFX :: struct {
    play            :: proc(asset: SFX_Asset, desc: SFX_Desc) -> u64;
    stop            :: proc(id: u64);
    default_sfx_desc :: proc() -> SFX_Desc;
}

Getting an SFX_Asset

Sound effects live in your game’s res folder (often under res/sfx/).

  • Drag sounds in from the Asset Catalog (editor downloads them into res/)

  • Or add your own .wav file into res/ from your local machine

Then reference them by path:

circle-exclamation
circle-info

Some built-in platform assets are referenced via $AO/... paths. For example: get_asset(SFX_Asset, "$AO/click.wav").

Positional (3D-ish) sounds

By default, SFX plays as a non-positional “2D” sound. To make it positional, set a position:

Following an entity (moving sound source)

If a sound should move with an entity (engine hum, buzzing projectile, etc), set entity_to_follow:

circle-info

If entity_to_follow is set, you usually don’t need to also call set_position (it’s fine if you do).

Looping + stopping

SFX.play returns an ID you can stop later:

circle-exclamation

If you play the same sound frequently (footsteps, pickups), add subtle variation:

circle-info

Keep volume_perturb / speed_perturb subtle. Values above ~0.3 usually sound wrong.

Server vs client (networking + prediction)

SFX can be played from either side, depending on intent:

  • Authoritative gameplay events (everyone should hear it): play on the server

  • Local/UI feedback (only the local player): play on the client

Example: authoritative positional SFX:

Last updated