FantasyAsset/Assets/Scripts/Behvaiours/FreezableNavAgent.cs

122 lines
3.2 KiB
C#

using UnityEngine;
using UnityEngine.AI;
using System.Collections;
[RequireComponent(typeof(NavMeshAgent))]
public class FreezableNavAgent : MonoBehaviour, IFreezable
{
[Header("Optional")]
[SerializeField] Animator animator; // optional: pause/resume anim
[SerializeField] string speedParam = "Speed"; // optional: set 0 while frozen
// Saved agent settings
float _origSpeed, _origAccel, _origAngSpeed;
bool _frozen;
Coroutine _freezeCo;
NavMeshAgent _agent;
void Awake()
{
_agent = GetComponent<NavMeshAgent>();
if (!animator) animator = GetComponentInChildren<Animator>();
CacheOriginals();
}
void OnEnable() { CacheOriginals(); }
void CacheOriginals()
{
if (_agent == null) return;
_origSpeed = _agent.speed;
_origAccel = _agent.acceleration;
_origAngSpeed = _agent.angularSpeed;
}
public void Freeze(float duration)
{
// If already frozen, refresh duration
if (_freezeCo != null) StopCoroutine(_freezeCo);
_freezeCo = StartCoroutine(FreezeRoutine(duration));
}
IEnumerator FreezeRoutine(float duration)
{
// Enter freeze
if (!_frozen) EnterFreeze();
// Wait for duration
float t = duration;
while (t > 0f)
{
t -= Time.deltaTime;
yield return null;
}
// Exit
ExitFreeze();
_freezeCo = null;
}
void EnterFreeze()
{
_frozen = true;
// Stop movement immediately
if (_agent)
{
_agent.isStopped = true; // halts pathfinding updates
_agent.ResetPath(); // clear current path
_agent.velocity = Vector3.zero;
// Optional: zero out movement-related params to avoid jitter
_agent.speed = 0f;
_agent.acceleration = 0f;
_agent.angularSpeed = 0f;
}
// Pause animations
if (animator)
{
animator.speed = 0f;
if (!string.IsNullOrEmpty(speedParam) && animator.HasParameterOfType(speedParam, AnimatorControllerParameterType.Float))
animator.SetFloat(speedParam, 0f);
}
}
void ExitFreeze()
{
_frozen = false;
if (_agent)
{
// Restore movement settings
_agent.speed = _origSpeed;
_agent.acceleration = _origAccel;
_agent.angularSpeed = _origAngSpeed;
_agent.isStopped = false;
}
if (animator)
{
animator.speed = 1f;
// (Your AI animation controller will resume updating speedParam from its movement script)
}
}
// Handy debug
[ContextMenu("Debug/Freeze 2s")]
void DebugFreeze2() => Freeze(2f);
}
// Small helper so we can safely check an Animator param
static class AnimatorExt
{
public static bool HasParameterOfType(this Animator self, string name, AnimatorControllerParameterType type)
{
foreach (var p in self.parameters)
if (p.type == type && p.name == name) return true;
return false;
}
}