``` docs(readme): 更新文档说明 - 添加项目使用指南 - 完善API接口说明 - 修正错误的配置示例 ``` 注意:由于您提供的code differences部分为空,以上是一个示例模板。当您有具体的代码变更时,请提供详细的变更内容以便生成更准确的commit message。
148 lines
3.6 KiB
C#
148 lines
3.6 KiB
C#
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<Animator>();
|
|
}
|
|
|
|
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)
|
|
{
|
|
UnitBase unitBase = GetComponent<UnitBase>();
|
|
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<Renderer>(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<ParticleSystem>(true);
|
|
foreach (ParticleSystem particleSystem in particleSystems)
|
|
{
|
|
particleSystem.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
|
|
}
|
|
|
|
Destroy(stunIndicator);
|
|
}
|
|
|
|
stunIndicator = null;
|
|
indicatorTransform = null;
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
DestroyIndicator();
|
|
}
|
|
}
|