This is NOT for modifying existing sounds! To see how to modify existing sounds, visit Rain World Modding Wiki: Modification Files.
Sounds exist in-game abstractly, that is, rather than you the modder dealing with AudioClip
/AudioSource
instances (belonging to Unity), you will instead use sounds via their abstract SoundID
class, which, like all other ExtEnum<T>
types, contains a unique string ID of your choosing.
Consider creating a new class in your mod, like so:
public static class Sounds {
public static SoundID MyAwesomeSound { get; private set; }
// Call Initialize() from your plugin's Awake method.
internal static void Initialize() {
MyAwesomeSound = new SoundID("My_Awesome_Sound", true);
}
}
NOTE: SoundID instances must be created before the sound system loads! Your BepInEx plugin's Awake()
method is a perfect place for this.
In general, it is not recommended to use static initializers for your sound instances (that is, do not do public static readonly SoundID MyAwesomeSound = new SoundID("My_Awesome_Sound", true);
unless you can guarantee that the class is referenced and used before the sound system loads). If you don't understand what this means, that's fine - the takeaway is that you should do what is done in the example, where a method called in Awake
creates the SoundID
s.
To play the sound, you need a reference to the current room
to call PlaySound(...)
on it. If you do not have a room, but you do have a RoomCamera
, you can use RoomCamera.virtualMicrophone.PlaySound(...)
instead. If you use the camera, make sure you are calling it on the correct camera, as a room may have more than one camera (each screen is a camera).
In your mod's folder, you need to have two subfolders with the following structure:
your_cool_mod
├modify
│└soundeffects
│ └sounds.txt
└soundeffects
└mycoolsound.wav
The modify
folder is what gets used when the game merges data. It follows a specific format that you can see here, in Downpour Reference: Modification Files - it has a soundeffects
subfolder, with sounds.txt
, which is the file it will be modifying.
The soundeffects
folder should contain .wav or .ogg files (no other formats are supported!)
NOTE
: Do NOT put your .wav/.ogg files in your_cool_mod/modify/soundeffects
! They do not go here. They go in the root folder your_cool_mod/soundeffects
. Similarly, do NOT put sounds.txt into your_cool_mod/soundeffects
. It goes into the modify folder your_cool_mod/modify/soundeffects
.
NOTE
: This uses the modify format, meaning you need to reload the mod (usually by restarting the game, but if you have checksum_override_version
set to true in modinfo.json
you will need to turn the mod off and back on too).
Every line of sounds.txt
follows a specific format:
[ADD]soundID/params... : soundfilename_1/params..., soundfilename_2/params..., ...
The following parameters are valid. Some parameters have values (denoted by =...
after the name) and some do not. Every parameter is separated from the next with a /
. These are case sensitive (having the wrong capitalization will break it).
minVol=...
andmaxVol=...
- When used together, they declare a range of volume that is randomly chosen every time the sound plays.- You can put this parameter on the ID and on individual sounds.
vol=...
- Declares a singular volume that the sound is always set to. This is a shorthand version of settingminVol
andmaxVol
to the same value.- You can put this parameter on the ID and on individual sounds.
- This, as well as
minVol
andmaxVol
, is set via a percentage, so1.0
is 100% volume. A proper setup for a sound file usually has its waveform at maximum volume (if you open it in a tool like Audacity, the blue wave should reach the top and bottom) and then a smaller value chosen here to adjust its volume appropriately, usually something around0.25
to0.5
.
minPitch=...
andmaxPitch=...
- When used together, they declare a range of pitch that is randomly chosen every time the sound plays.- You can put this parameter on the ID and on individual sounds.
pitch=...
- Declares a singular pitch that the sound always has. This is a shorthand version of settingminPitch
andmaxPitch
to the same value.- You can put this parameter on the ID and on individual sounds.
- Again, like volume, this and
minPitch
/maxPitch
are set via a percentage, so1.0
is 100% pitch. Pitch directly affects the speed of the sound.
dopplerFac=...
- This declares how intense the doppler effect is when you play the sound at a specific position in the world. The doppler effect is why sounds change pitch when something is moving (it gets lower when going away and higher when coming closer).- You can put this parameter on the ID. You can NOT put this on individual sounds.
- Yet again, this is also a percentage where
1.0
is 100%. A value of0
will remove the effect entirely.
samename
- Allows a shorter audio ID by telling the system to assume the sound filename is the same as the sound ID. This isn't even used in any vanilla examples.- You can put this parameter on the ID. You can NOT put this on individual sounds.
DONTLOG
- Prevents the sound from logging any information about it in vanilla code that does logging. Mostly used for debugging. It's not likely going to be very useful for you.- You can put this parameter on the ID. You can NOT put this on individual sounds.
PLAYALL
- This is only useful if you have more than one sound file on a sound ID (i.e.id : sound_1,sound_2,sound_3
) - if this is present, all of the sounds will play at once when you tell the game to play this sound ID. If not, it will choose from those sounds randomly and play the one it picked.- You can put this parameter on the ID. You can NOT put this on individual sounds.
CACHE
- Once loaded, the sound will remain loaded. The game must be restarted to reflect any changes to the sound. Does not seem to be really used in vanilla, and is not likely useful to you either.- You can put this parameter on the ID. You can NOT put this on individual sounds.
NOTE:
The values used for percentages simply need to be a number, it doesn't matter how you write it so long as it's a valid number. The reason 1.0
is used in place of 1
is purely cosmetic; in computer programming, there are different types of numbers that may or may not support decimals, so adding .0
is a good visual indicator to yourself in the future, or to other programmers, that it supports decimals.
- The sound begins with
[ADD]
because it is a modify file (a file within the modify subdirectory). This tells the merge system to add your data to the list of existing vanilla/mod sounds.- There are other operations, for example
[REPLACE]
, however those are outside of the scope of this document.
- There are other operations, for example
- The sound's ID. The ID is shared with the code. It is this ID you use when doing
new SoundID(id_here, true)
in C#. - Global parameters, separated by a
/
- applies to all sound files belonging to this ID. - The string "
:
" (the surrounding spaces are required).- Note: Do not copy/paste the : from here, I have some invisible characters in there to preserve the spaces.
- One or more sounds:
- Any additional parameters. Any parameter here will override its global counterpart.
- Multiple sounds are separated with commas
a,b
Certain keywords do not work when used on an individual sound. Additionally, your file names must follow a specific format.
dopplerFac
MUST be placed on the sound ID - it does not function when put on an individual sound (example:Sound_Id : file/dopplerFac=0
is INVALID). This is explicitly mentioned because it is a bit counterintuitive at first.samename
,DONTLOG
,PLAYALL
, andCACHE
MUST be placed on the sound ID.- The sound file name MUST NOT use underscores, unless you are making multiple variants of the same sound. In this case, follow the format of
name_X
where X is a number starting from 1. This is how the game numbers your sound effects.- Don't get caught up worrying about which file gets which number, it really doesn't matter. They just need a valid number.
- If you plan to explicitly index your sounds (via
VirtualMicrophone::GetSoundData
), then you at the very least need to pay attention to the numbers you set here. There are very few use cases for this so you will not likely run into this scenario. - Your sound ID can use underscores anywhere. It is only the file name that is affected by this rule.
- Sound IDs and their file names SHOULD BE UNIQUE. If you happen to use the same name as another mod, the mod that loads last will override any sounds with the same name that loaded before it.
- You can use this to overwrite vanilla sounds, however this technique is not recommended (you should instead use
[REPLACE]
in the modify file, which was designed for this one purpose, rather than[ADD]
)
- You can use this to overwrite vanilla sounds, however this technique is not recommended (you should instead use
[ADD]glass_conduitbuzz_LOOP/vol=0.3 : glass-conduitbuzz
[ADD]glass_devicewarn_LOOP/vol=0.75/dopplerFac=0.0 : glass-devicewarn
[ADD]glass_industrial_alarm/vol=0.5/dopplerFac=0.0 : glass-industrialalarm
[ADD]glass_stock_shock/vol=0.3 : glass-stockshock_1/minPitch=0.90/maxPitch=1.10,glass-stockshock_2/minPitch=0.95/maxPitch=1.05
public static SoundID CONDUIT_BUZZ_LOOP { get; private set; } = new SoundID("glass_conduitbuzz_LOOP", true);
public static SoundID STOCK_ZAP_SOUND { get; private set; } = new SoundID("glass_stock_shock", true);
public static SoundID INDUSTRIAL_ALARM { get; private set; } = new SoundID("glass_industrial_alarm", true);
public static SoundID DEVICE_WARNING_LOOP { get; private set; } = new SoundID("glass_devicewarn_LOOP", true);
glass_conduitbuzz_LOOP
has a volume of 0.3glass_devicewarn_LOOP
has a volume of 0.75, and is not affected by the doppler effect.glass_industrial_alarm
has a volume of 0.5, and is not affected by the doppler effect.glass_stock_shock
has a volume of 0.3 on both of its sounds. The first sound can have a pitch from 90% to 110%, and the second sound can have a pitch from 95% to 105%.