A car’s engine follows its RPM, footsteps change with the ground, and the mix shifts when the player dives underwater. Pepper.SFX gives each a home: parameters for numbers, switches for choices and states for game modes, set from code or from an event’s actions.
How it works
- Parameter assets (RTPCs) are named numbers with a range, a unit label, a default and Smoothing: None, Rate or Ease, with separate rise and fall. The string API (
SetRTPC("CombatIntensity", 0.7f)) and an asset with that Parameter Name are the same parameter. - Three scopes. A value can be set on one sound’s handle, on an Audio Emitter (every sound on one car), or globally. A sound reads the closest one that has a value, so two cars can play the same engine Blend at different RPMs.
- Built-in values. Set a parameter’s Value From to Distance, Approach Speed or Angle and Pepper works it out for each sound, from the listening point.
- Parameter Curves on any container drive its volume (dB), pitch (cents), low-pass or high-pass (Hz) from a parameter, with no code. A Blend Container crossfades its layers along one.
- Values at post.
PostValuescarries up to four parameter values and two switch values, so a one-shot’s first sample hears them. - Switch Group assets list a switch’s values (Asphalt, Gravel, Grass). Set them globally, per emitter or per handle, and a Switch Container plays the matching child. When Switch Changes (Next Play Only, Crossfade, Restart) decides what a playing loop does. A group can also be Driven By a parameter through ranges, with hysteresis.
- Audio State assets belong to a State Group, and one state per group is active. A state sets bus volumes, switches, RTPCs and exposed mixer effect values, easing the levels over a transition time.
Example
using UnityEngine;
using AudioSystem;
[RequireComponent(typeof(AudioEmitter))]
public class CarAudio : MonoBehaviour
{
[SerializeField] private AudioEvent engineEvent; // a Blend Container on RPM
[SerializeField] private AudioEvent impactEvent;
[SerializeField] private AudioParameter rpm; // 800-7000, Smoothing: Ease
[SerializeField] private AudioParameter impactStrength; // 0-1
[SerializeField] private AudioSwitchGroup surface; // Asphalt, Gravel, Grass
private AudioEmitter emitter;
void Start()
{
emitter = GetComponent<AudioEmitter>();
emitter.Post(engineEvent);
}
public void UpdateEngine(float engineRpm) => emitter.SetParameter(rpm, engineRpm); // this car only
public void OnSurfaceChanged(string value) => emitter.SetSwitch(surface, value);
void OnCollisionEnter(Collision collision)
{
float strength = Mathf.Clamp01(collision.relativeVelocity.magnitude / 20f);
emitter.Post(impactEvent, PostValues.Of(impactStrength, strength));
}
}
Each car keeps its RPM and surface on its Audio Emitter, so many cars share one engine event, and the impact’s strength travels with the post. A game mode is one global call: AudioManager.Instance.SetState("Underwater", 1.5f).
Setting it up
- Assets > Create > Audio System > Parameter. Set Unit Label, Min Value, Max Value, Default Value and Smoothing.
- Assets > Create > Audio System > Switch Group. List its Values and set a Default Value.
- On a container, add a Parameter Curve, set a Blend Container’s Blend Parameter, or set a Switch Container’s Switch Group.
- Add Add Component > Audio System > Audio Emitter to each object that needs its own values, and post its sounds on it.
- Assets > Create > Audio System > Audio State. Set its State Name and State Group, then the bus volumes, switches and RTPCs it changes. Keep states in
Resources/Audio/States, or list them in an Audio Event Registry.
Good to know
- Values set by name (
SetRTPC,TransitionRTPC) are never smoothed. Smoothing applies to writes through the asset (SetParameter,RampParameter). - Code can’t set a built-in value:
SetParameteron one is ignored with a warning. - A value that isn’t a number (NaN or infinity) is refused with a warning, and sounds keep the last good value.
- Setting a state applies only its own values: nothing from the previous state is undone, so give each state in a group a value for everything its siblings change. The exception is Bus Volume Mode Offset: its offsets go back when the state ends.
- Parameters update once a frame, after every LateUpdate, so a value written anywhere this frame is heard this frame.
- In Play mode, Window > Audio System > Live View shows every Audio Emitter’s values and sounds.