using Spine.Unity; using System.Collections.Generic; using UnityEngine; public enum TurretAnimType { None = 0, skeletonAnimation = 1, animation = 2, animator = 3 } public enum TurretState { None = 0, Idle = 1, Attack = 2, LaserStart = 3, LaserLoop = 4, LaserEnd = 5 } public class TurretData : MonoBehaviour { [Header("基础")] public string turretID; public SitPosData setPosData; public Transform tra_BulletStartPosition; public GameObject bulletPrefab_Two; public GameObject bulletPrefab; [Header("UI面板属性")] [Tooltip("炮台编号,对应 TurretResourcesData.turretNumber")] public int turretNumber; [Tooltip("1=普通炮台 2=战神 3=翅膀")] public int turretType = 1; [Tooltip("UI 展示名称")] public string displayName; [Tooltip("品质 1=普通 2=稀有 3=史诗 4=传说")] [Range(1, 5)] public int quality = 1; [Tooltip("解锁所需等级(0=默认拥有)")] public int unlockLevel; [Tooltip("UI 列表/详情用的缩略图")] public Sprite uiIconSprite; [TextArea(2, 4)] [Tooltip("描述文字")] public string description; // ---- 运行时状态(由服务器/UI面板读写) ---- [System.NonSerialized] public bool isUnlocked; [System.NonSerialized] public bool isEquipped; [System.NonSerialized] public int ownStarLevel; [Header("动画组件")] public SkeletonGraphic skeletonAnimation; public Animation old_CurrAnimation; public Animator new_CurrAnimation; public TurretAnimType currTurretType; public bool isFrenzy=false; [Header("动画名")] public string idleAnim; public string attackAnim; // 新增:狂暴专用攻击动画(已经是二倍速帧动画) public string frenzyAttackAnim; private bool useFrenzyAnim = false; public string laserStartAnim; public string laserLoopAnim; public string laserEndAnim; private TurretState currState; /// /// 从资源表查询 TurretResourcesData。表里没有则返回 null,调用方应使用 TurretData 自身的 Inspector 默认值。 /// public TurretResourcesData GetResourcesData() { return TurretResourcesData.GetTurretData(turretNumber); } /// 安全获取攻击音效 ID:表里有就用,没有则返回 0(静音)。 public int GetAttackAudioID() { var res = GetResourcesData(); return res != null ? res.attackAudioID : 0; } /// 安全获取子弹 ID 列表:表里有就用,没有则返回空列表。 public List GetBulletIDs() { var res = GetResourcesData(); return res?.bulletID ?? new List(); } /// 安全获取动画类型:表里有就用,没有则用 Inspector 配置的 currTurretType。 public TurretAnimType GetAnimationType() { var res = GetResourcesData(); return res != null ? (TurretAnimType)res.animationType : currTurretType; } private void Awake() { //if (setPosData != null) // setPosData.OnStateChange = ChangeState; // 自动判断:如果狂暴攻击动画名不为空,就启用切换动画模式 useFrenzyAnim = !string.IsNullOrEmpty(frenzyAttackAnim); } private void OnEnable() { PlayState(TurretState.Idle); } public Vector2 GetBulletStartWorldPos() { if (tra_BulletStartPosition == null) return Vector2.zero; // 如果是 UI RectTransform(UGUI) RectTransform rect = tra_BulletStartPosition.GetComponent(); if (rect != null) { // 1. UI 本地坐标 → Canvas 坐标 Vector2 canvasPos = CoordinateTransformation.AnchoredPos_ToCanvas( rect, UIManager.Instance.uiRoot.GetComponent() ); // 2. Canvas 坐标 → 世界坐标 return CoordinateTransformation.CanvasToWorld( canvasPos, UIManager.Instance.uiRoot.GetComponent(), Camera.main ); } // 如果不是 UI(比如 3D Transform) return tra_BulletStartPosition.position; } public void SetFrenzy(bool value) { isFrenzy = value; if (!useFrenzyAnim) // 没有狂暴动画 → 用速度加倍 { float speed = isFrenzy ? 2f : 1f; if (skeletonAnimation != null) skeletonAnimation.timeScale = speed; if (new_CurrAnimation != null) new_CurrAnimation.speed = speed; if (old_CurrAnimation != null) { foreach (AnimationState state in old_CurrAnimation) state.speed = speed; } } else { // 有狂暴动画 → 不做速度调整,保持 1 倍速 if (skeletonAnimation != null) skeletonAnimation.timeScale = 1f; if (new_CurrAnimation != null) new_CurrAnimation.speed = 1f; if (old_CurrAnimation != null) { foreach (AnimationState state in old_CurrAnimation) state.speed = 1f; } } } public void ChangeState(TurretState newState) { if (currState == newState) return; currState = newState; PlayState(newState); } private void PlayState(TurretState state) { switch (currTurretType) { case TurretAnimType.skeletonAnimation: PlaySkeleton(state); break; case TurretAnimType.animation: PlayLegacy(state); break; case TurretAnimType.animator: PlayAnimator(state); break; } } private void PlaySkeleton(TurretState state) { if (skeletonAnimation == null) return; string anim = state switch { TurretState.Idle => idleAnim, TurretState.Attack => (isFrenzy && useFrenzyAnim) ? frenzyAttackAnim : attackAnim, TurretState.LaserStart => laserStartAnim, TurretState.LaserLoop => laserLoopAnim, TurretState.LaserEnd => laserEndAnim, _ => idleAnim }; bool loop = state == TurretState.Attack || state == TurretState.LaserLoop; skeletonAnimation.AnimationState.SetAnimation(0, anim, loop); if (state == TurretState.LaserStart) { skeletonAnimation.AnimationState.AddAnimation(0, laserLoopAnim, true, 0f); } } private void PlayLegacy(TurretState state) { if (old_CurrAnimation == null) return; string anim = state switch { TurretState.Idle => idleAnim, TurretState.Attack => (isFrenzy && useFrenzyAnim) ? frenzyAttackAnim : attackAnim, TurretState.LaserStart => laserStartAnim, TurretState.LaserLoop => laserLoopAnim, TurretState.LaserEnd => laserEndAnim, _ => idleAnim }; old_CurrAnimation.Play(anim); } private void PlayAnimator(TurretState state) { if (new_CurrAnimation == null) return; if (state == TurretState.Attack && isFrenzy && useFrenzyAnim) { new_CurrAnimation.SetTrigger("FrenzyAttack"); } else { new_CurrAnimation.SetInteger("State", (int)state); } } }