Rain World’s sound table maps a registered global::SoundID to one or more sample names and playback instructions. Loose samples, asset-bundle clips, and mod overrides then follow different loading branches. Sound playback covers calls such as Room.PlaySound. This page covers the files those calls depend on.

flowchart TD
    A[Sound table entry] --> B{Bundled sample?}
    B -->|yes| C[audioClipThroughUnity]
    B -->|no| D[Loose sample]
    C --> E[Check override]
    C --> F[Bundle fallback]
    D --> G[SoundImporter]

Sound table entries

global::SoundLoader.LoadSounds() reads the resolved soundeffects/sounds.txt. It creates trigger storage from registered global::SoundID values, compares trigger names without case sensitivity, and parses matching lines. An installed entry has this form:

Slugcat_Step_A : walk3A/vol=0.3

Slugcat_Step_A is the trigger name. walk3A is a sample name. /vol=0.3 is an instruction attached to that sample. A registered SoundID with no matching valid table entry does not become a working trigger.

For each sample, the loader checks the loadedsoundeffects asset bundle first. If the bundle contains the sample or its _1 variant, the matching allAudio entry gets audioClipThroughUnity = true. Otherwise global::SoundLoader.CheckIfFileExistsAsExternal(System.String) probes these loose paths through AssetManager:

soundeffects/<name>.wav
soundeffects/<name>_1.wav
soundeffects/<name>.ogg
soundeffects/<name>_1.ogg

If none exists, the trigger is marked with a missing-file error. Loose samples use the SoundImporter branch, which enumerates soundeffects, matches files to allAudio entries where audioClipThroughUnity is false, and loads .ogg or .wav clips. The external variation counter checks numbered .wav files after the first sample. Numbered .ogg variation behavior therefore needs a game test.

These checks describe discovery and loading. They do not establish that adding a table line and a loose file is a complete custom-sound packaging recipe across mod merges, enum registration, reloads, and supported platforms.

LoadedSoundEffects overrides bundle clips

The exact baseline signature is global::SoundLoader.GetAudioClip(System.Int32,out AssetBundleLoadAssetOperation,out System.String). Its loadedsoundeffects file check occurs only when allAudio[i].audioClipThroughUnity is true.

For that branch, the method chooses a variation name and first resolves the WAV override. The source also contains an Ogg retry path:

loadedsoundeffects/<name>.wav
loadedsoundeffects/<name>.ogg

The Ogg retry is conditional: the resolved WAV path must differ from the base fallback path and be missing. Since ResolveFilePath normally returns that base fallback when no file exists, a lone Ogg override does not reliably reach this retry. Use a WAV override for this source-described route and test the exact package before relying on Ogg behavior.

If a resolved override exists outside the base fallback path, the method loads that clip. Otherwise it retrieves or requests the clip from the loadedsoundeffects asset bundle. When audioClipThroughUnity is false, GetAudioClip returns the clip already populated by the loose soundeffects importer.

This distinction matters when diagnosing a silent trigger. soundeffects/<name> supplies an external sample selected during table loading. loadedsoundeffects/<name> overrides a sample that the loader already classified as a Unity or asset-bundle clip. The two directories are not interchangeable registration locations.

Ambient discovery and overrides

global::SoundLoader.LoadAllAmbientSounds() enumerates the resolved directory set for soundeffects/ambient and sends each filename to global::SoundLoader.RequestAmbientAudioClip(System.String). The request first checks an active resolved override at:

loadedsoundeffects/ambient/<same filename>

That override is loaded as WAV when the resolved path ends in .wav. Other extensions use the Ogg Vorbis loader. Without an override, the method checks the loadedsoundeffects_ambient bundle, then uses the ambient importer for the enumerated loose file. Installed content includes loadedsoundeffects/ambient/AM_ENV-Outside.ogg as an override example.

Use the override path only with an existing, verified ambient filename. Static source shows how directory enumeration and requests connect, but this article does not claim a tested recipe for registering a new room ambience name. Author room records through the workflow in Room settings and verify discovery, playback, and reload behavior in game.

Procedural music stops at the bundle boundary

global::Music.ProceduralMusic.ProceduralMusicInstruction..ctor(System.String) resolves text from music/procedural/<name>.txt. An installed region instruction includes:

TH_CC - KICK : NEUTRAL <PA>
Layer : TH_CC - KICK, TH_CC - PERC1, TH_CC - NOISE

The referenced procedural clips come from the music_procedural asset bundle. Song playback similarly uses the music_songs bundle. The inspected source establishes the text path and bundle dependency. It does not establish a supported asset-bundle build and mod placement process, so there is no custom music bundle recipe here.

All behavior on this page is source-verified against build 22785462. File case behavior, mod merge results, loose sample playback, ambience registration, and override reloads remain runtime checks.

Sources

  • Rain World v1.11.8, Steam build 22785462: global::SoundLoader.LoadSounds(), global::SoundLoader.CheckIfFileExistsAsExternal(System.String), and global::SoundLoader.GetAudioClip(System.Int32,out AssetBundleLoadAssetOperation,out System.String) in the assembly identified by Runtime reference.
  • Rain World v1.11.8, Steam build 22785462: global::SoundLoader.LoadAllAmbientSounds(), global::SoundLoader.RequestAmbientAudioClip(System.String), and global::Music.ProceduralMusic.ProceduralMusicInstruction..ctor(System.String).