using System; using Spine.Unity; using UnityEngine; using UnityEngine.UI; public class HorseController : MonoBehaviour { private GameObjectPoolManager.GameObjectPool pool; private int skinID; protected SkeletonGraphic skeletonGraphic; protected Spine.AnimationState spineAnimationState; private GameObject instanceGO; protected UIHeroController hero; private Action onComplete; private bool isHeroShowBefore = false; public void Create(int _skinID, int _heroSkinID = 0, float scale = 1f, Action _onComplete = null, string motionName = "idle") { if (skinID == _skinID) { CreateHero(_heroSkinID); //避免重复创建 return; } skinID = _skinID; var skinConfig = HorseSkinConfig.Get(skinID); this.transform.localScale = Vector3.one * scale; onComplete = _onComplete; pool = GameObjectPoolManager.Instance.RequestPool(UILoader.LoadPrefab("UIHorse")); if (!transform.gameObject.activeSelf) { transform.SetActive(true); } if (instanceGO == null) { instanceGO = pool.Request(); instanceGO.transform.SetParent(transform); //transform 的Pivot Y是0,让instanceGO 居中 instanceGO.transform.localPosition = new Vector3(0, instanceGO.GetComponent().sizeDelta.y * 0.5f); //instanceGO.transform.localPosition = Vector3.zero; instanceGO.transform.localScale = Vector3.one; instanceGO.transform.localRotation = Quaternion.identity; } skeletonGraphic = instanceGO.GetComponentInChildren(true); skeletonGraphic.skeletonDataAsset = ResManager.Instance.LoadAsset("UIEffect/Spine/Horse", skinConfig.Spine); if (skeletonGraphic.skeletonDataAsset == null) { transform.SetActive(false); if (pool != null) pool.Release(instanceGO); skeletonGraphic = null; Destroy(instanceGO); Debug.LogError("未配置spine"); return; } skeletonGraphic.Initialize(true); skeletonGraphic.transform.localPosition = new Vector3(skinConfig.Poses[0], skinConfig.Poses[1], 0); isHeroShowBefore = skinConfig.heroFirst == 1; spineAnimationState = skeletonGraphic.AnimationState; spineAnimationState.Data.DefaultMix = 0f; if (motionName == "") motionName = GetFistSpineAnim(); PlayAnimation(motionName, true); CreateHero(_heroSkinID); spineAnimationState.Complete -= OnAnimationComplete; spineAnimationState.Complete += OnAnimationComplete; } public void CreateHero(int heroSkinID) { if (instanceGO == null) { return; } hero = instanceGO.GetComponentInChildren(true); if (hero == null) { return; } if (heroSkinID == 0) { hero.SetActive(false); return; } hero.SetActive(true); hero.Create(heroSkinID); //约定骑乘点骨骼名 hero.GetComponent().boneName = "mountPoint"; if (isHeroShowBefore) { hero.transform.SetAsLastSibling(); } else { hero.transform.SetAsFirstSibling(); } } public void HeroPlay(string motionName, bool loop = false, bool replay=true) { hero.PlayAnimation(motionName, loop, replay); } protected void OnDestroy() { if (spineAnimationState != null) { spineAnimationState.Complete -= OnAnimationComplete; } if (pool != null) pool.Release(instanceGO); skeletonGraphic = null; pool = null; } /// /// 播放 Spine 动画 /// /// 动作名 /// 循环 /// 如果相同动作是否再次重播,比如跑步重播就会跳帧不顺滑 public virtual void PlayAnimation(string motionName, bool loop = false, bool replay=true) { if (spineAnimationState == null) return; if (GetCurrentAnimationName() == motionName && !replay) return; // 直接使用 ToString() 而不是调用 GetAnimationName spineAnimationState.SetAnimation(0, motionName.ToString(), loop); } // 播放第一个动画(作为默认动画) string GetFistSpineAnim() { var skeletonData = skeletonGraphic.Skeleton.Data; if (skeletonData.Animations.Count > 0) { return skeletonData.Animations.Items[0].Name; } else { Debug.LogError("Spine 数据中没有找到任何动画!武将皮肤:" + skinID); } return ""; } /// /// 获取当前正在播放的 Spine 动画名称 /// /// 当前动画名称,如果没有动画则返回空字符串 public string GetCurrentAnimationName() { if (spineAnimationState == null || spineAnimationState.GetCurrent(0) == null) { return string.Empty; } return spineAnimationState.GetCurrent(0).Animation.Name; } /// /// 动画完成事件处理 /// protected virtual void OnAnimationComplete(Spine.TrackEntry trackEntry) { onComplete?.Invoke(); } //越大越快 public void SetSpeed(float speed) { spineAnimationState.TimeScale = speed; } public void SetEnabled(bool isEnable) { if (skeletonGraphic == null) { return; } skeletonGraphic.enabled = isEnable; } }