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(); if (!animator) animator = GetComponentInChildren(); 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; } }