124 lines
3.2 KiB
C#
124 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 bool isFrozen { get; set; }
|
|
|
|
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;
|
|
}
|
|
}
|