feat(StoneGolemSkill): 实现石巨人技能体系与荒野祭司技能设计 - 完成石巨人技能 StoneGolemSkill 的完整实现,包括 1~10 级技能阶梯 - 实现 1~2 级【大地震击】:3.5 米范围 160% 伤害 + 1.5 秒眩晕 - 实现 3~5 级【震荡强化】:伤害提升至 200%,范围扩大至 4.4 米 + 2 秒眩晕 - 实现 6~9 级【坚石护体】:获得 30% 最大生命值护盾,护盾期间霸体免控 - 实现 10 级【天崩地裂】:4.5 米范围 260% 伤害 + 3 米强力击退 + 2 秒眩晕 + 护盾提升至 45% 最大生命值 + 护盾期间受击减伤 35% - 添加护盾特效、冲击波动画、地面裂纹特效等视觉反馈 - 实
194 lines
5.2 KiB
C#
194 lines
5.2 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);
|
|
|
|
/// <summary>是否处于眩晕免疫/霸体状态</summary>
|
|
public bool isStunImmune = false;
|
|
|
|
[Header("易伤状态")]
|
|
private float vulnerabilityRemaining = 0f;
|
|
private float vulnerabilityRatio = 0f;
|
|
|
|
public bool HasVulnerability => vulnerabilityRemaining > 0f;
|
|
public float VulnerabilityRatio => vulnerabilityRemaining > 0f ? vulnerabilityRatio : 0f;
|
|
|
|
/// <summary>
|
|
/// 施加破甲/易伤标记:使目标在持续时间内受到的所有伤害增加指定比例
|
|
/// </summary>
|
|
public void ApplyVulnerability(float duration, float ratio)
|
|
{
|
|
if (duration <= 0f || ratio <= 0f) return;
|
|
vulnerabilityRemaining = Mathf.Max(vulnerabilityRemaining, duration);
|
|
vulnerabilityRatio = Mathf.Max(vulnerabilityRatio, ratio);
|
|
}
|
|
|
|
private void Awake()
|
|
{
|
|
animator = GetComponent<Animator>();
|
|
}
|
|
|
|
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 (vulnerabilityRemaining > 0f)
|
|
{
|
|
vulnerabilityRemaining -= Time.deltaTime;
|
|
if (vulnerabilityRemaining <= 0f)
|
|
{
|
|
vulnerabilityRemaining = 0f;
|
|
vulnerabilityRatio = 0f;
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (stunIndicatorPrefab == null)
|
|
{
|
|
stunIndicatorPrefab = Resources.Load<GameObject>("Prefabs/特效/眩晕头顶星星/眩晕星星粒子");
|
|
#if UNITY_EDITOR
|
|
if (stunIndicatorPrefab == null)
|
|
{
|
|
stunIndicatorPrefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Prefabs/特效/眩晕头顶星星/眩晕星星粒子.prefab");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (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();
|
|
}
|
|
}
|