NOTE: This script is deprecated in AC v1.81 and later - as AC's updated Footstep Sounds component can now auto-detect Surfaces using raycasting.[]
A character with the Footstep Sounds component will play walk and run sounds as they move around the scene. These sounds can be changed using the "Sound: Change footsteps" Action, placed in e.g. a Trigger. This script, however, allows you to change sounds automatically based on what surface the character is standing on.
To use:
- For each floor collider that can be stood on, create and assign it a Unity "Physic Material" asset.
- Create a new C# file named AutoSetFootstepSounds.cs, and paste in the code below.
- Attach the new Auto Set Footstep Sounds component to your character.
- Fill in the component's Inspector: assigning both the layer that the floor colliders are placed on, and create an entry for each created Physic Material in the "Footstep Materials" array, pairing the material with a set of footstep sounds.
AutoSetFootstepSounds.cs:
using UnityEngine;
using AC;
public class AutoSetFootstepSounds : MonoBehaviour
{
[SerializeField] private LayerMask layerMask = new LayerMask ();
[SerializeField] private float rayLength = 0.2f;
[SerializeField] private FootstepMaterial[] footstepMaterials = new FootstepMaterial[0];
private Char character;
private FootstepSounds footstepSounds;
private PhysicMaterial standingOnMaterial;
private void Awake ()
{
character = GetComponent<Char> ();
footstepSounds = GetComponentInChildren<FootstepSounds> ();
}
private void LateUpdate ()
{
Vector3 rayStart = transform.position + (0.5f * rayLength * Vector3.up);
Debug.DrawRay (rayStart, Vector3.up * -rayLength);
RaycastHit hitInfo = new RaycastHit ();
if (Physics.Raycast (rayStart, Vector3.down, out hitInfo, rayLength, layerMask))
{
if (hitInfo.collider.sharedMaterial && standingOnMaterial != hitInfo.collider.sharedMaterial)
{
standingOnMaterial = hitInfo.collider.sharedMaterial;
OnStandMaterial (standingOnMaterial);
}
}
}
private void OnStandMaterial (PhysicMaterial material)
{
foreach (FootstepMaterial footstepMaterial in footstepMaterials)
{
if (footstepMaterial.Material == material)
{
footstepMaterial.Apply (footstepSounds);
return;
}
}
}
[System.Serializable]
private class FootstepMaterial
{
[SerializeField] private PhysicMaterial material = null;
[SerializeField] private AudioClip[] walkSounds = new AudioClip[0];
[SerializeField] private AudioClip[] runSounds = new AudioClip[0];
public void Apply (FootstepSounds footstepSounds)
{
if (walkSounds.Length > 0)
{
footstepSounds.footstepSounds = walkSounds;
}
if (runSounds.Length > 0)
{
footstepSounds.runSounds = runSounds;
}
if (!footstepSounds.character.IsGrounded () && walkSounds.Length > 0)
{
footstepSounds.soundToPlayFrom.audioSource.clip = walkSounds[0];
}
}
public PhysicMaterial Material { get { return material; } }
}
}