projectEli/Assets/NeoFPS/Core/Audio/SurfaceFootstepAudioSystem.cs

109 lines
3.5 KiB
C#
Raw Normal View History

2022-11-07 01:28:33 +00:00
using UnityEngine;
using NeoFPS.Constants;
using NeoFPS.CharacterMotion;
using UnityEngine.Events;
namespace NeoFPS
{
[RequireComponent (typeof (MotionController), typeof (ICharacterAudioHandler))]
[HelpURL("https://docs.neofps.com/manual/audioref-mb-surfacefootstepaudiosystem.html")]
public class SurfaceFootstepAudioSystem : MonoBehaviour
{
private MotionController m_MotionController = null;
private ICharacterAudioHandler m_AudioHandler = null;
private ISurfaceFootstepAudio m_AudioSetup = null;
private RaycastHit m_Hit = new RaycastHit();
private FpsSurfaceMaterial m_LastSurfaceId = FpsSurfaceMaterial.Default;
public event UnityAction<FpsSurfaceMaterial> onFootStep;
public enum Direction
{
Down,
InverseGroundNormal,
LocalVector,
WorldVector,
WorldParameter,
WorldParameterInverse,
LocalParameter,
LocalParameterInverse
}
public FpsSurfaceMaterial lastStepMaterial
{
get;
private set;
}
private void Awake()
{
m_MotionController = GetComponent<MotionController>();
m_AudioHandler = GetComponent<ICharacterAudioHandler>();
}
public void SetFootstepAudio(ISurfaceFootstepAudio audio)
{
// Subscribe to step tracking
if (m_AudioSetup == null && audio != null && audio.footstepAudio != null)
m_MotionController.onStep += OnStep;
// Unsubscribe from step tracking
if (m_AudioSetup != null && audio == null)
m_MotionController.onStep -= OnStep;
m_AudioSetup = audio;
}
void OnStep()
{
float sqrSpeed = m_MotionController.characterController.velocity.sqrMagnitude;
float minSpeed = m_AudioSetup.minimumSpeed;
if (sqrSpeed > minSpeed * minSpeed)
{
// Get the surface
var surface = GetGroundSurface();
// Play the audio
float volume;
AudioClip clip = m_AudioSetup.footstepAudio.GetAudioClip(surface, out volume);
if (clip != null)
m_AudioHandler.PlayClip(clip, FpsCharacterAudioSource.Feet, volume);
// Fire footstep event
if (onFootStep != null)
onFootStep(surface);
}
}
FpsSurfaceMaterial GetGroundSurface()
{
FpsSurfaceMaterial result = m_LastSurfaceId;
// Get charactercontroller info
var cc = m_MotionController.characterController;
var radius = cc.radius;
var normalisedHeight = radius / cc.height;
// Raycast for surface type
if (cc.RayCast(normalisedHeight, m_AudioSetup.castDirection * (m_AudioSetup.castRange + radius), m_AudioSetup.castSpace, out m_Hit, PhysicsFilter.Masks.BulletBlockers, QueryTriggerInteraction.Ignore))
{
// Get surface ID from ray hit
Transform t = m_Hit.transform;
if (t != null)
{
BaseSurface s = t.GetComponent<BaseSurface>();
if (s != null)
result = s.GetSurface(m_Hit);
else
result = FpsSurfaceMaterial.Default;
}
m_LastSurfaceId = result;
}
return result;
}
}
}