159 lines
4.0 KiB
C#
159 lines
4.0 KiB
C#
using UnityEngine;
|
|
|
|
namespace TPSBR
|
|
{
|
|
[DefaultExecutionOrder(10000)]
|
|
public sealed class AgentFootsteps : MonoBehaviour
|
|
{
|
|
// PRIVATE MEMBERS
|
|
|
|
[SerializeField]
|
|
private AudioEffect _leftFootEffect;
|
|
[SerializeField]
|
|
private AudioEffect _rightFootEffect;
|
|
[SerializeField]
|
|
private FootstepSetup _footstepSetup;
|
|
[SerializeField]
|
|
private float _defaultDelay = 0.03f;
|
|
[SerializeField]
|
|
private float _minFootstepTime = 0.2f;
|
|
[SerializeField]
|
|
private float _checkDistanceUp = 0.1f;
|
|
[SerializeField]
|
|
private float _checkDistanceDown = 0.05f;
|
|
[SerializeField]
|
|
private float _maxStepCorrectionTime = 0.7f;
|
|
[SerializeField]
|
|
private float _minSpeed = 0.1f;
|
|
[SerializeField]
|
|
private float _runSpeedTreshold = 2f;
|
|
[SerializeField]
|
|
private LayerMask _hitMask;
|
|
|
|
private FootData _leftFootData = new FootData();
|
|
private FootData _rightFootData = new FootData();
|
|
|
|
private float _lastStepTime;
|
|
|
|
private Agent _agent;
|
|
private Character _character;
|
|
|
|
// PUBLIC METHODS
|
|
|
|
public void OnAgentRender()
|
|
{
|
|
PlayFootsteps();
|
|
}
|
|
|
|
// MonoBehaviour INTERFACE
|
|
|
|
private void Awake()
|
|
{
|
|
_agent = GetComponent<Agent>();
|
|
_character = GetComponent<Character>();
|
|
|
|
_leftFootData.Transform = _character.ThirdPersonView.LeftFoot;
|
|
_rightFootData.Transform = _character.ThirdPersonView.RightFoot;
|
|
|
|
_leftFootData.Effect = _leftFootEffect;
|
|
_rightFootData.Effect = _rightFootEffect;
|
|
}
|
|
|
|
// PRIVATE METHODS
|
|
|
|
private void PlayFootsteps()
|
|
{
|
|
_leftFootData.Cooldown -= Time.deltaTime;
|
|
_rightFootData.Cooldown -= Time.deltaTime;
|
|
|
|
if (_character.CharacterController.FixedData.IsGrounded == false)
|
|
{
|
|
_leftFootData.IsUp = true;
|
|
_rightFootData.IsUp = true;
|
|
return;
|
|
}
|
|
|
|
if (_character.CharacterController.FixedData.RealSpeed < _minSpeed)
|
|
return;
|
|
|
|
float timeFromLastStep = Time.time - _lastStepTime;
|
|
|
|
CheckFoot(_leftFootData, timeFromLastStep);
|
|
CheckFoot(_rightFootData, timeFromLastStep);
|
|
}
|
|
|
|
private void CheckFoot(FootData foot, float timeFromAnyLastStep)
|
|
{
|
|
if (foot.IsUp == true && foot.Cooldown > 0f)
|
|
return;
|
|
|
|
float distanceFromBottom = (foot.Transform.position - transform.position).y;
|
|
|
|
if (foot.IsUp == false && distanceFromBottom > _checkDistanceUp)
|
|
{
|
|
foot.IsUp = true;
|
|
}
|
|
else if (foot.IsUp == true && distanceFromBottom < _checkDistanceDown)
|
|
{
|
|
var newSetupSource = _footstepSetup.GetSound(GetSurfaceTagHash(foot.Transform), _character.CharacterController.FixedData.RealSpeed > _runSpeedTreshold);
|
|
|
|
if (foot.SetupSource != newSetupSource)
|
|
{
|
|
foot.Setup.CopyFrom(newSetupSource);
|
|
foot.SetupSource = newSetupSource;
|
|
}
|
|
|
|
float timeFromThisLastStep = -foot.Cooldown + _minFootstepTime;
|
|
|
|
if (timeFromAnyLastStep < _maxStepCorrectionTime && timeFromThisLastStep * 0.5f < _maxStepCorrectionTime)
|
|
{
|
|
// Pace correction
|
|
foot.Setup.Delay = (timeFromThisLastStep * 0.5f - timeFromAnyLastStep) * 0.75f;
|
|
}
|
|
else
|
|
{
|
|
foot.Setup.Delay = _defaultDelay;
|
|
}
|
|
|
|
foot.Effect.Play(foot.Setup, EForceBehaviour.ForceAny);
|
|
|
|
// Make sure same sound is not played twice in a row
|
|
_leftFootData.Effect.LastPlayedClipIndex = foot.Effect.LastPlayedClipIndex;
|
|
_rightFootData.Effect.LastPlayedClipIndex = foot.Effect.LastPlayedClipIndex;
|
|
|
|
_lastStepTime = Time.time + foot.Setup.Delay;
|
|
|
|
foot.IsUp = false;
|
|
foot.Cooldown = _minFootstepTime;
|
|
}
|
|
}
|
|
|
|
private int GetSurfaceTagHash(Transform foot)
|
|
{
|
|
var physicsScene = _agent.Runner.SimulationUnityScene.GetPhysicsScene();
|
|
if (physicsScene.Raycast(foot.position + Vector3.up, Vector3.down, out RaycastHit hit, 1.5f, _hitMask, QueryTriggerInteraction.Collide) == true)
|
|
{
|
|
var collider = hit.collider;
|
|
if (collider != null)
|
|
{
|
|
return collider.tag.GetHashCode();
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// HELPERS
|
|
|
|
private class FootData
|
|
{
|
|
public bool IsUp;
|
|
public float Cooldown;
|
|
public Transform Transform;
|
|
public AudioEffect Effect;
|
|
public AudioSetup Setup = new AudioSetup();
|
|
public AudioSetup SetupSource;
|
|
}
|
|
}
|
|
}
|