<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Snapshots on DAD 424 Sound Design for Games</title><link>https://dsu-digital-sound-design.github.io/f-25-dad-424-sound-design-for-games/tags/snapshots/</link><description>Recent content in Snapshots on DAD 424 Sound Design for Games</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Wed, 12 Jun 2024 00:00:00 +0000</lastBuildDate><atom:link href="https://dsu-digital-sound-design.github.io/f-25-dad-424-sound-design-for-games/tags/snapshots/index.xml" rel="self" type="application/rss+xml"/><item><title>Creating Audio Zones and Dynamic Mixing with Snapshots</title><link>https://dsu-digital-sound-design.github.io/f-25-dad-424-sound-design-for-games/lectures/week-14/snapshots/</link><pubDate>Wed, 12 Jun 2024 00:00:00 +0000</pubDate><guid>https://dsu-digital-sound-design.github.io/f-25-dad-424-sound-design-for-games/lectures/week-14/snapshots/</guid><description>In our previous tutorial, we mastered Playback States to control when sounds play. Now, we’re going to control how they sound based on the game environment.
Have you ever noticed how audio changes when a character walks into a cave (reverb kicks in) or when they are low on health (the sound gets muffled and bass-heavy)? In FMOD, these dynamic mixing changes are handled by Snapshots.
In this guide, we will cover:</description><content>&lt;p>In our previous tutorial, we mastered &lt;strong>Playback States&lt;/strong> to control &lt;em>when&lt;/em> sounds play. Now, we’re going to control &lt;em>how&lt;/em> they sound based on the game environment.&lt;/p>
&lt;p>Have you ever noticed how audio changes when a character walks into a cave (reverb kicks in) or when they are low on health (the sound gets muffled and bass-heavy)? In FMOD, these dynamic mixing changes are handled by &lt;strong>Snapshots&lt;/strong>.&lt;/p>
&lt;p>In this guide, we will cover:&lt;/p>
&lt;ol>
&lt;li>What Snapshots are and how to create them.&lt;/li>
&lt;li>Creating a &lt;strong>Reverb Zone&lt;/strong> using Triggers.&lt;/li>
&lt;li>Handling signal routing (so your UI clicks don&amp;rsquo;t echo!).&lt;/li>
&lt;li>Creating a &lt;strong>&amp;ldquo;Low Health&amp;rdquo; filter&lt;/strong> using Parameters.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="what-is-a-snapshot">What is a Snapshot?&lt;/h2>
&lt;p>Think of a Snapshot as a &amp;ldquo;preset&amp;rdquo; for your FMOD Mixer. When active, a Snapshot can change the volume of buses, toggle effects on and off, or change effect parameters.&lt;/p>
&lt;p>There are two main types:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Overriding:&lt;/strong> Forces values to a specific state (good for absolute changes).&lt;/li>
&lt;li>&lt;strong>Blending:&lt;/strong> Adds changes on top of existing values (good for layering).&lt;/li>
&lt;/ul>
&lt;p>For this tutorial, we will focus on &lt;strong>Overriding&lt;/strong> snapshots to create distinct audio zones.&lt;/p>
&lt;hr>
&lt;h2 id="part-1-the-reverb-zone-trigger-based">Part 1: The Reverb Zone (Trigger-Based)&lt;/h2>
&lt;p>Let’s create a system where entering a tunnel applies reverb to our sound effects.&lt;/p>
&lt;h3 id="step-1-fmod-setup">Step 1: FMOD Setup&lt;/h3>
&lt;ol>
&lt;li>Go to the &lt;strong>Mixer&lt;/strong> window in FMOD.&lt;/li>
&lt;li>Create a Return Bus for Reverb if you haven&amp;rsquo;t already, and add a Reverb effect to it.&lt;/li>
&lt;li>Go to the &lt;strong>Snapshots&lt;/strong> tab and create a new &lt;strong>Overriding Snapshot&lt;/strong> named &amp;ldquo;Reverb Zone 1&amp;rdquo;.&lt;/li>
&lt;li>Deselect your snapshot for the time being.&lt;/li>
&lt;li>Select the SFX Bus and add a &lt;strong>Send&lt;/strong> to the Reverb Return Bus. Set the send level to around -6dB (adjust to taste).&lt;/li>
&lt;li>&lt;strong>Scoping:&lt;/strong> When you select the snapshot, your mixer faders will turn into yellow outlines. This means they are &amp;ldquo;scoped out&amp;rdquo; (unaffected).
&lt;ol>
&lt;li>Select the snapshot again. Mixer controls will appear with yellow outlines, meaning they are currently scoped out.&lt;/li>
&lt;li>Click the reverb send level on the SFX Bus so it becomes fully yellow, indicating it is scoped in and will be driven by the snapshot.&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>When you select the snapshot, the reverb send will be set to the value defined in the snapshot.&lt;/li>
&lt;li>&lt;strong>Modulation:&lt;/strong> To make the reverb fade in smoothly, right-click the Snapshot&amp;rsquo;s &lt;strong>Intensity&lt;/strong> dial (in the deck area) and add an &lt;strong>AHDSR Modulator&lt;/strong>. This ensures the reverb doesn&amp;rsquo;t snap on/off instantly.&lt;/li>
&lt;/ol>
&lt;h3 id="step-2-the-unity-script">Step 2: The Unity Script&lt;/h3>
&lt;p>Open Level 2 in Unity. This scene has more tunnels that we can use for testing reverb.&lt;/p>
&lt;p>In Unity, Snapshots are treated almost exactly like Events. We create an instance, play it, and stop it.&lt;/p>
&lt;p>Create a cube object with Create &amp;gt; 3D Object &amp;gt; Cube. Scale it to form a tunnel entrance and set its position so the player can walk through it. Make sure to set the cube&amp;rsquo;s collider to &lt;strong>Is Trigger&lt;/strong>. Call it &lt;code>Reverb Zone&lt;/code>. Also make sure the layer is set to &lt;code>Environment&lt;/code>.&lt;/p>
&lt;p>We&amp;rsquo;ll leave the &lt;code>Mesh Renderer&lt;/code> on so you can see the zone in the scene, but in a real game, you would likely turn this off.&lt;/p>
&lt;p>Create a script called &lt;code>F_ReverbZone&lt;/code> and attach it to the &lt;code>Reverb Zone&lt;/code> object.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-csharp" data-lang="csharp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">using&lt;/span> UnityEngine;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">using&lt;/span> FMODUnity;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">using&lt;/span> FMOD.Studio;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">ReverbZone&lt;/span> : MonoBehaviour
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> EventInstance reverbSnapshot;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">void&lt;/span> Start()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Create the instance just like a normal event&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Note: The path starts with &amp;#34;snapshot:/&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> reverbSnapshot = RuntimeManager.CreateInstance(&lt;span style="color:#e6db74">&amp;#34;snapshot:/Reverb Zone&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">void&lt;/span> OnTriggerEnter(Collider other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> (other.CompareTag(&lt;span style="color:#e6db74">&amp;#34;Player&amp;#34;&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> reverbSnapshot.start();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">void&lt;/span> OnTriggerExit(Collider other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> (other.CompareTag(&lt;span style="color:#e6db74">&amp;#34;Player&amp;#34;&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Allow the AHDSR to fade it out naturally&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> reverbSnapshot.stop(STOP_MODE.ALLOWFADEOUT);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">void&lt;/span> OnDestroy()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> reverbSnapshot.release();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="step-3-fixing-the-signal-path-the-ui-echo-problem">Step 3: Fixing the Signal Path (The UI Echo Problem)&lt;/h3>
&lt;p>If you test the game now, entering the zone will reverb &lt;em>everything&lt;/em> sent to the SFX bus—including your UI menu clicks! That’s not what we want. We need to split the signal.&lt;/p>
&lt;p>&lt;strong>In the FMOD Mixer:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>Delete the send that goes from the &lt;strong>SFX&lt;/strong> bus to the &lt;strong>Reverb&lt;/strong> bus.&lt;/li>
&lt;li>Create two new Group Buses under your main &lt;strong>SFX&lt;/strong> bus: call them &lt;strong>In-Game&lt;/strong> and &lt;strong>UI&lt;/strong>.&lt;/li>
&lt;li>Route your footsteps, attacks, and environmental sounds into &lt;strong>In-Game&lt;/strong>.&lt;/li>
&lt;li>Route your menu sounds into &lt;strong>UI&lt;/strong>.&lt;/li>
&lt;li>Place the &lt;strong>Reverb Send&lt;/strong> on the &lt;strong>In-Game&lt;/strong> bus only.&lt;/li>
&lt;/ol>
&lt;p>Now, your UI remains crisp and dry, while the game world echoes around you.&lt;/p>
&lt;hr>
&lt;h2 id="part-2-the-distance-based-zone-automation">Part 2: The Distance-Based Zone (Automation)&lt;/h2>
&lt;p>Sometimes you don&amp;rsquo;t want a hard trigger; you want the effect to get stronger as you get closer to a specific object.&lt;/p>
&lt;h3 id="fmod-setup">FMOD Setup&lt;/h3>
&lt;ol>
&lt;li>Create a new snapshot (e.g., &amp;ldquo;Reverb Zone 2&amp;rdquo;).&lt;/li>
&lt;li>Instead of an AHDSR on the &lt;strong>Intensity&lt;/strong> dial, right-click and &lt;strong>Add Automation&lt;/strong>.&lt;/li>
&lt;li>Select the built-in &lt;strong>Distance&lt;/strong> parameter.&lt;/li>
&lt;li>Draw a curve:
&lt;ul>
&lt;li>At 5 meters, Intensity = 100%&lt;/li>
&lt;li>At 10 meters, Intensity = 0%&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h3 id="unity-script">Unity Script&lt;/h3>
&lt;p>Since this relies on distance, we must tell FMOD where the snapshot is located in 3D space.&lt;/p>
&lt;p>Create an Empty GameObject called &lt;code>Reverb Zone 2&lt;/code> and position at (-1, -3, 28.5). Create a new script and attach to the gameObject:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-csharp" data-lang="csharp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> Start()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> reverbSnapshot = RuntimeManager.CreateInstance(&lt;span style="color:#e6db74">&amp;#34;snapshot:/Reverb Zone 2&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> reverbSnapshot.start(); &lt;span style="color:#75715e">// Start immediately&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Attach the instance to this object so FMOD knows its location&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> RuntimeManager.AttachInstanceToGameObject(reverbSnapshot, transform, GetComponent&amp;lt;Rigidbody&amp;gt;());
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> OnDestroy()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> reverbSnapshot.stop(STOP_MODE.IMMEDIATE);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> reverbSnapshot.release();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="part-3-the-low-health-filter-parameter-control">Part 3: The &amp;ldquo;Low Health&amp;rdquo; Filter (Parameter Control)&lt;/h2>
&lt;p>A common game mechanic is muffling audio when the player is dying. We can achieve this by controlling a Snapshot via a script parameter.&lt;/p>
&lt;h3 id="step-1-fmod-setup-1">Step 1: FMOD Setup&lt;/h3>
&lt;ol>
&lt;li>Add a &lt;strong>3-EQ Effect&lt;/strong> to your &lt;strong>In-Game&lt;/strong> bus.&lt;/li>
&lt;li>Create a Snapshot called &amp;ldquo;Low Health&amp;rdquo;.&lt;/li>
&lt;li>Scope in the &lt;strong>High&lt;/strong> and &lt;strong>Mid&lt;/strong> bands of the EQ and turn them all the way down (leaving only low frequencies).&lt;/li>
&lt;li>Right-click the Snapshot&amp;rsquo;s &lt;strong>Intensity&lt;/strong> dial and select &lt;strong>Expose as Parameter&lt;/strong>.&lt;/li>
&lt;li>Set the range of the parameter from 1 to 5.&lt;/li>
&lt;li>&lt;strong>Invert the curve:&lt;/strong>
&lt;ul>
&lt;li>When Parameter = 5 (Full Health), Intensity = 0% (No filter).&lt;/li>
&lt;li>When Parameter = 1 (Low Health), Intensity = 100% (Fully muffled).&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h3 id="step-2-linking-health-to-audio">Step 2: Linking Health to Audio&lt;/h3>
&lt;p>In your Player Controller script, you need to update the snapshot whenever health changes.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-csharp" data-lang="csharp">&lt;span style="display:flex;">&lt;span>FMOD.Studio.EventInstance healthFilter;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> Start()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> healthFilter = RuntimeManager.CreateInstance(&lt;span style="color:#e6db74">&amp;#34;snapshot:/Low Health&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> healthFilter.start();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> healthFilter.release(); &lt;span style="color:#75715e">// Release immediately so it cleans up when stopped&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// Call this function whenever the player takes damage or heals&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> SetHealthSnapshot() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> healthFilter.setParameterByName(&lt;span style="color:#e6db74">&amp;#34;Intensity&amp;#34;&lt;/span>, m_Damageable.currentHitPoints); &lt;span style="color:#75715e">// currentHealth should be between 1 and 5&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> OnDestroy()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> healthFilter.stop(STOP_MODE.IMMEDIATE);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>By hooking the &lt;code>UpdateAudioHealth&lt;/code> function into your existing damage logic (using Unity Events or direct method calls), your audio will dynamically react to the player&amp;rsquo;s survival status.&lt;/p>
&lt;hr>
&lt;h2 id="summary">Summary&lt;/h2>
&lt;p>Snapshots are powerful tools that move beyond simple &amp;ldquo;Play/Stop&amp;rdquo; commands. By treating them as Event Instances in code, you can:&lt;/p>
&lt;ul>
&lt;li>Trigger reverb zones using &lt;strong>Colliders&lt;/strong>.&lt;/li>
&lt;li>Automate audio changes based on &lt;strong>3D Distance&lt;/strong>.&lt;/li>
&lt;li>Drive mix changes using gameplay variables like &lt;strong>Player Health&lt;/strong>.&lt;/li>
&lt;/ul>
&lt;p>With these tools, you&amp;rsquo;ve now covered the core pillars of FMOD implementation: Events, Parameters, Playback States, and Snapshots.&lt;/p></content></item></channel></rss>