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); /// 是否处于眩晕免疫/霸体状态 public bool isStunImmune = false; private void Awake() { animator = GetComponent(); } public void ApplyStun(float duration) { if (duration <= 0f || isStunImmune) { 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) { UnitBase unitBase = GetComponent(); animator.speed = unitBase != null ? Mathf.Max(0.01f, unitBase.AttackSpeedMultiplier) : 1f; } DestroyIndicator(); } } private void LateUpdate() { if (stunIndicator == null || !IsStunned) { return; } Bounds bounds = new Bounds(transform.position, Vector3.zero); Renderer[] renderers = GetComponentsInChildren(true); bool hasRenderer = false; foreach (Renderer renderer in renderers) { if (stunIndicator != null && renderer.transform.IsChildOf(stunIndicator.transform)) { continue; } if (!hasRenderer) { bounds = renderer.bounds; hasRenderer = true; } else { bounds.Encapsulate(renderer.bounds); } } if (!hasRenderer) { bounds = new Bounds(transform.position, Vector3.zero); } 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, transform); stunIndicator.name = "StunIndicator_Particle"; indicatorTransform = stunIndicator.transform; } private void DestroyIndicator() { if (stunIndicator != null) { ParticleSystem[] particleSystems = stunIndicator.GetComponentsInChildren(true); foreach (ParticleSystem particleSystem in particleSystems) { particleSystem.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear); } Destroy(stunIndicator); } stunIndicator = null; indicatorTransform = null; } private void OnDestroy() { DestroyIndicator(); } }