using UnityEngine; public class StatusEffectController : MonoBehaviour { [Header("通用眩晕显示")] [SerializeField] private bool showStunIndicator = true; [SerializeField] private float indicatorHeight = 0.35f; [SerializeField] private GameObject stunIndicatorPrefab; private Animator animator; private float stunnedRemaining; private float animatorSpeedBeforeStun = 1f; private GameObject stunIndicator; private Transform indicatorTransform; public bool IsStunned => stunnedRemaining > 0f; public float StunnedRemaining => Mathf.Max(0f, stunnedRemaining); private void Awake() { animator = GetComponent(); } public void ApplyStun(float duration) { if (duration <= 0f) { return; } if (!IsStunned && animator != null) { animatorSpeedBeforeStun = animator.speed; } stunnedRemaining = Mathf.Max(stunnedRemaining, duration); if (animator != null) { animator.speed = 0f; } if (showStunIndicator) { EnsureIndicator(); } } private void Update() { if (!IsStunned) { return; } stunnedRemaining -= Time.deltaTime; if (animator != null) { animator.speed = 0f; } if (stunnedRemaining <= 0f) { stunnedRemaining = 0f; if (animator != null) { animator.speed = Mathf.Max(0.01f, animatorSpeedBeforeStun); } DestroyIndicator(); } } private void LateUpdate() { if (indicatorTransform == null) { return; } Bounds bounds = new Bounds(transform.position, Vector3.zero); Renderer[] renderers = GetComponentsInChildren(true); if (renderers.Length > 0) { bounds = renderers[0].bounds; for (int i = 1; i < renderers.Length; i++) { bounds.Encapsulate(renderers[i].bounds); } } indicatorTransform.position = new Vector3( bounds.center.x, bounds.max.y + indicatorHeight, bounds.center.z); } private void EnsureIndicator() { if (stunIndicator != null || stunIndicatorPrefab == null) { return; } stunIndicator = Instantiate(stunIndicatorPrefab); stunIndicator.name = "StunIndicator_Particle"; indicatorTransform = stunIndicator.transform; } private void DestroyIndicator() { if (stunIndicator != null) { Destroy(stunIndicator); } stunIndicator = null; indicatorTransform = null; } private void OnDestroy() { DestroyIndicator(); } }