<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Procedural Audio 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/procedural-audio/</link><description>Recent content in Procedural Audio on DAD 424 Sound Design for Games</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Tue, 21 Oct 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://dsu-digital-sound-design.github.io/f-25-dad-424-sound-design-for-games/tags/procedural-audio/index.xml" rel="self" type="application/rss+xml"/><item><title>Building Dynamic Footstep Sounds in Unity with FMOD and Raycasting</title><link>https://dsu-digital-sound-design.github.io/f-25-dad-424-sound-design-for-games/lectures/week-9/automating-audio-with-parameters-2/</link><pubDate>Tue, 21 Oct 2025 00:00:00 +0000</pubDate><guid>https://dsu-digital-sound-design.github.io/f-25-dad-424-sound-design-for-games/lectures/week-9/automating-audio-with-parameters-2/</guid><description>Create adaptive footsteps in Unity with FMOD using raycasts, surface tags, and an enum-backed parameter that maps directly to FMOD.</description><content>&lt;h2 id="introduction">Introduction&lt;/h2>
&lt;p>Creating immersive game soundscapes often comes down to subtle details—like the sound of footsteps adapting to different surfaces. In this tutorial, we’ll expand upon previous FMOD parameter work by integrating Unity’s physics system to detect materials underfoot. Using &lt;strong>raycasting&lt;/strong> and &lt;strong>tags&lt;/strong>, we’ll dynamically alter footstep sounds to reflect the player’s environment—be it grass, stone, puddles, or earth.&lt;/p>
&lt;p>This guide walks through each step: tagging surfaces, scripting raycasts, and linking an enum-backed FMOD parameter for a responsive, data‑driven footstep system. If you follow along from top to bottom, you’ll go from a blank scene to fully adaptive footsteps.&lt;/p>
&lt;hr>
&lt;h2 id="recap-where-we-left-off">Recap: Where We Left Off&lt;/h2>
&lt;p>In the previous session, we created a simple FMOD event that played footstep sounds through Unity animation triggers. We:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Created a footstep event&lt;/strong> in FMOD with a “Material” parameter.&lt;/li>
&lt;li>&lt;strong>Wrote a Unity C# script&lt;/strong> to instantiate, play, and destroy the event on each step.&lt;/li>
&lt;li>&lt;strong>Linked animation events&lt;/strong> to ensure footstep sounds triggered precisely in sync.&lt;/li>
&lt;/ol>
&lt;p>Now, we’ll enhance that system so footsteps automatically change depending on what surface the player is walking or running across.&lt;/p>
&lt;hr>
&lt;h2 id="step-1-setting-up-tags-in-unity">Step 1: Setting Up Tags in Unity&lt;/h2>
&lt;p>Tags let you label objects and detect them in scripts. Each surface type gets a unique tag.&lt;/p>
&lt;ol>
&lt;li>Navigate to &lt;strong>Edit → Project Settings → Tags &amp;amp; Layers&lt;/strong>.&lt;/li>
&lt;li>Under &lt;strong>Tags&lt;/strong>, click &lt;strong>+&lt;/strong> and add:
&lt;ul>
&lt;li>Earth&lt;/li>
&lt;li>Stone&lt;/li>
&lt;li>Puddle&lt;/li>
&lt;li>Grass&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>&lt;img alt="alt text" src="https://dsu-digital-sound-design.github.io/f-25-dad-424-sound-design-for-games/f-25-dad-424-sound-design-for-games/lectures/week-9/automating-audio-with-parameters-2/tags.png">&lt;/p>
&lt;p>Assign these tags to relevant scene objects—terrain, stairs, platforms, etc. Apply the tag to the collider you expect the raycast to hit (often on the same GameObject that has the Mesh Collider or Box Collider).&lt;/p>
&lt;p>&lt;img alt="alt text" src="https://dsu-digital-sound-design.github.io/f-25-dad-424-sound-design-for-games/f-25-dad-424-sound-design-for-games/lectures/week-9/automating-audio-with-parameters-2/tag-stone.png">
Tagging even a few surfaces is enough to test. Later, we&amp;rsquo;ll expand this system to cover more materials using Physics Materials or Terrain Textures.&lt;/p>
&lt;hr>
&lt;h2 id="step-2-script-framework">Step 2: Script Framework&lt;/h2>
&lt;p>Start by defining an enum for surface types and the core fields/methods in your player script. Add this to your player controller (or a dedicated audio component on the player).&lt;/p>
&lt;blockquote>
&lt;p>An enum is a new data type we haven&amp;rsquo;t used yet. It lets us define a set of named constants, which we can use to represent discrete values (like surface types). This makes our code more readable and less error-prone than using raw integers or strings.&lt;/p>
&lt;/blockquote>
&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">enum&lt;/span> MaterialType { Earth = &lt;span style="color:#ae81ff">0&lt;/span>, Stone = &lt;span style="color:#ae81ff">1&lt;/span>, Puddle = &lt;span style="color:#ae81ff">2&lt;/span>, Grass = &lt;span style="color:#ae81ff">3&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">public&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">F_Player&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:#a6e22e"> [SerializeField]&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> LayerMask groundLayerMask;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e"> [SerializeField]&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">float&lt;/span> rayDistance = &lt;span style="color:#ae81ff">1.5f&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">private&lt;/span> MaterialType currentMaterial;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> RaycastHit hitInfo;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> Rigidbody rb;
&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> &lt;span style="color:#66d9ef">void&lt;/span> Awake()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rb = 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">private&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> Update()
&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">// Step 4 will explain this debug line&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Debug.DrawRay(transform.position, Vector3.down * rayDistance, Color.red);
&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">public&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> PlayRunEvent(&lt;span style="color:#66d9ef">string&lt;/span> eventPath)
&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> (&lt;span style="color:#66d9ef">string&lt;/span>.IsNullOrEmpty(eventPath)) &lt;span style="color:#66d9ef">return&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> MaterialCheck();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> EventInstance run = RuntimeManager.CreateInstance(eventPath);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> RuntimeManager.AttachInstanceToGameObject(run, gameObject, rb);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Step 6: we&amp;#39;ll create/start the FMOD event and set the parameter&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">private&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> MaterialCheck()
&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">// Steps 3–5: raycast and set currentMaterial&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;/code>&lt;/pre>&lt;/div>&lt;p>Notes:&lt;/p>
&lt;ul>
&lt;li>Enum names must match tags exactly: &lt;code>Earth&lt;/code>, &lt;code>Stone&lt;/code>, &lt;code>Puddle&lt;/code>, &lt;code>Grass&lt;/code>.&lt;/li>
&lt;li>&lt;code>groundLayerMask&lt;/code> should include only layers containing walkable geometry.&lt;/li>
&lt;li>&lt;code>rayDistance&lt;/code> defaults to 1.5m; adjust to your character height.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="step-3-raycasting-to-detect-surfaces">Step 3: Raycasting to Detect Surfaces&lt;/h2>
&lt;p>The script casts a ray downward from the player to find the surface beneath:&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">if&lt;/span> (Physics.Raycast(transform.position, Vector3.down, &lt;span style="color:#66d9ef">out&lt;/span> hitInfo, rayDistance, groundLayerMask))
&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">// hitInfo.collider is the surface collider we tagged&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;code>transform.position&lt;/code> = Player position&lt;/li>
&lt;li>&lt;code>Vector3.down&lt;/code> = Direction toward the ground&lt;/li>
&lt;li>&lt;code>rayDistance&lt;/code> = Ray length (default 1.5m)&lt;/li>
&lt;li>&lt;code>groundLayerMask&lt;/code> = Limit detection to your environment layers (e.g., &lt;code>Environment&lt;/code>, &lt;code>WaterGeometry&lt;/code>)&lt;/li>
&lt;/ul>
&lt;p>In the Inspector, assign the &lt;code>groundLayerMask&lt;/code> to include only layers with tagged ground geometry.&lt;/p>
&lt;p>If you find gaps on stairs or steep terrain, consider a small sphere cast:&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">if&lt;/span> (Physics.SphereCast(transform.position, &lt;span style="color:#ae81ff">0.1f&lt;/span>, Vector3.down, &lt;span style="color:#66d9ef">out&lt;/span> hitInfo, rayDistance, groundLayerMask))
&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">// Slightly more forgiving than a thin ray&lt;/span>
&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="step-4-visualize-the-ray">Step 4: Visualize the Ray&lt;/h2>
&lt;p>The script draws the ray each frame for easy debugging:&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>Debug.DrawRay(transform.position, Vector3.down * rayDistance, Color.red);
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>View this in the Scene window as you move the player to ensure correct origin and length.&lt;/p>
&lt;hr>
&lt;h2 id="step-5-tags--enum-mapping">Step 5: Tags → Enum Mapping&lt;/h2>
&lt;p>Inside &lt;code>MaterialCheck()&lt;/code> and &lt;code>Raycast&lt;/code> if statement, add this code to convert the detected tag into the enum value:&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">if&lt;/span> (System.Enum.TryParse(hitInfo.collider.tag, &lt;span style="color:#66d9ef">out&lt;/span> MaterialType material))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> currentMaterial = material;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>TryParse: Attempts to map the tag (e.g., &amp;ldquo;Stone&amp;rdquo;) to &lt;code>MaterialType.Stone&lt;/code>.&lt;/li>
&lt;li>Safe update: Only assigns &lt;code>currentMaterial&lt;/code> when parsing returns true; otherwise the previous value remains.&lt;/li>
&lt;li>Optional default: If you want an explicit fallback when parsing fails, add an else:&lt;/li>
&lt;/ul>
&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">if&lt;/span> (System.Enum.TryParse(hitInfo.collider.tag, &lt;span style="color:#66d9ef">out&lt;/span> MaterialType material))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> currentMaterial = material;
&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">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> currentMaterial = MaterialType.Earth; &lt;span style="color:#75715e">// default&lt;/span>
&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="step-6-fmod-parameter-setup">Step 6: FMOD Parameter Setup&lt;/h2>
&lt;p>The script sets the parameter via, which you&amp;rsquo;ll add inside &lt;code>PlayRunEvent&lt;/code> before starting the event:&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>run.setParameterByName(&lt;span style="color:#e6db74">&amp;#34;Material&amp;#34;&lt;/span>, (&lt;span style="color:#66d9ef">float&lt;/span>)currentMaterial);
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="step-7-full-script">Step 7: Full Script&lt;/h2>
&lt;p>Here’s the complete script with all steps combined:&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">enum&lt;/span> MaterialType
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Earth = &lt;span style="color:#ae81ff">0&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Stone = &lt;span style="color:#ae81ff">1&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Puddle = &lt;span style="color:#ae81ff">2&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Grass = &lt;span style="color:#ae81ff">3&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">public&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">F_Player&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:#a6e22e"> [SerializeField]&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> LayerMask groundLayerMask;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e"> [SerializeField]&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">float&lt;/span> rayDistance = &lt;span style="color:#ae81ff">1.5f&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">private&lt;/span> MaterialType currentMaterial;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> RaycastHit hitInfo;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> Rigidbody rb;
&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> &lt;span style="color:#66d9ef">void&lt;/span> Awake()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rb = 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">private&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> Update()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Debug.DrawRay(transform.position, Vector3.down * rayDistance, Color.red);
&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">public&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> PlayRunEvent(&lt;span style="color:#66d9ef">string&lt;/span> eventPath)
&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> (&lt;span style="color:#66d9ef">string&lt;/span>.IsNullOrEmpty(eventPath)) &lt;span style="color:#66d9ef">return&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> MaterialCheck();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> EventInstance run = RuntimeManager.CreateInstance(eventPath);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> RuntimeManager.AttachInstanceToGameObject(run, gameObject, rb);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> run.setParameterByName(&lt;span style="color:#e6db74">&amp;#34;Material&amp;#34;&lt;/span>, (&lt;span style="color:#66d9ef">float&lt;/span>)currentMaterial);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> run.start();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> run.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;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> MaterialCheck()
&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> (Physics.Raycast(transform.position, Vector3.down, &lt;span style="color:#66d9ef">out&lt;/span> hitInfo, rayDistance, groundLayerMask))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Debug.Log(&lt;span style="color:#e6db74">&amp;#34;Hit material: &amp;#34;&lt;/span> + hitInfo.collider.tag);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> (System.Enum.TryParse(hitInfo.collider.tag, &lt;span style="color:#66d9ef">out&lt;/span> MaterialType material))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> currentMaterial = material;
&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>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;p>&lt;em>References:&lt;/em>&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://docs.unity3d.com/ScriptReference/Physics.Raycast.html">Unity Raycasting Documentation&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://docs.unity3d.com/ScriptReference/Vector3.html">Unity Vector3 Directions&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://fmod.com/resources/documentation-api">FMOD Studio API Reference&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://docs.unity3d.com/ScriptReference/Color.html">Unity Color Struct&lt;/a>&lt;/li>
&lt;/ul></content></item></channel></rss>