using System.Collections; using System.Collections.Generic; using UnityEngine; namespace BF { [System.Serializable] public struct CharacterSpineObjectInfo { public uint hashName; public UnityEngine.GameObject gameObject; } [ExecuteInEditMode] [DisallowMultipleComponent] public class CharacterSpineHelper : MonoBehaviour { public GameObject SpineObject; public List ObjectList = new List(); public float PositionX { get; private set; } public float PositionY { get; private set; } public float PositionZ { get; private set; } private Spine.Unity.SkeletonAnimation skeletonAnimation; private Spine.AnimationState animationState; void Awake() { skeletonAnimation = SpineObject.GetComponent(); animationState = skeletonAnimation.AnimationState; } public void Reload() { animationState = skeletonAnimation.AnimationState; } public void PlayAnimation(string animName, bool loop, bool forceRefresh) { animationState.SetAnimation(0, animName, loop); if (forceRefresh) { skeletonAnimation.Update(0); } } public void SetAnimationSpeed(float timeScale) { skeletonAnimation.timeScale = timeScale; } public void SetLoop(bool isLoop) { skeletonAnimation.loop = isLoop; } public GameObject GetSpineObject() { return SpineObject; } public Spine.Unity.SkeletonAnimation GetSkeletonAnimation() { return skeletonAnimation; } public int GetListCount() { return ObjectList.Count; } public GameObject GetGameObjectByIndex(int index) { if (index >= 0 && index < ObjectList.Count) { return ObjectList[index].gameObject; } else if (index < 0) { return this.gameObject; } return null; } public uint GetHashNameByIndex(int index) { if (index >= 0 && index < ObjectList.Count) { return ObjectList[index].hashName; } return 0; } public int GetInstanceID(int index) { if (index >= 0 && index < ObjectList.Count) { return ObjectList[index].gameObject.GetInstanceID(); } return gameObject.GetInstanceID(); } // Lua层可以使用PositionX,PositionY,PositionZ,减少直接传递localPosition的开销 public void CacheLocalPosition(int index) { if (index >= 0 && index < ObjectList.Count) { var localPosition = ObjectList[index].gameObject.transform.localPosition; PositionX = localPosition.x; PositionY = localPosition.y; PositionZ = localPosition.z; } else if (index < 0) { PositionX = this.transform.localPosition.x; PositionY = this.transform.localPosition.y; PositionZ = this.transform.localPosition.z; } } public void SetLocalPosition(int index, float x, float y, float z) { if (index >= 0 && index < ObjectList.Count) { ObjectList[index].gameObject.transform.localPosition = new Vector3(x, y, z); } else if (index < 0) { this.transform.localPosition = new Vector3(x, y, z); } } // Lua层可以使用PositionX,PositionY,PositionZ,减少直接传递position的开销 public void CachePosition(int index) { if (index >= 0 && index < ObjectList.Count) { var position = ObjectList[index].gameObject.transform.position; PositionX = position.x; PositionY = position.y; PositionZ = position.z; } else if (index < 0) { PositionX = this.transform.position.x; PositionY = this.transform.position.y; PositionZ = this.transform.position.z; } } public void CacheBonePosition(string name) { var skeleton = skeletonAnimation.Skeleton; var bone = skeleton.FindBone(name); if (bone != null) { Vector3 unityWorldPosition = skeletonAnimation.transform.TransformPoint(new Vector3(bone.WorldX, bone.WorldY, 0.0f)); PositionX = unityWorldPosition.x; PositionY = unityWorldPosition.y; PositionZ = unityWorldPosition.z; } else { PositionX = 0.0f; PositionY = 0.0f; PositionZ = 0.0f; } } public void SetPosition(int index, float x, float y, float z) { if (index >= 0 && index < ObjectList.Count) { ObjectList[index].gameObject.transform.position = new Vector3(x, y, z); } else if (index < 0) { this.transform.position = new Vector3(x, y, z); } } public void SetLocalEulerAngles(int index, float x, float y, float z) { if (index >= 0 && index < ObjectList.Count) { ObjectList[index].gameObject.transform.localEulerAngles = new Vector3(x, y, z); } else if (index < 0) { this.transform.localEulerAngles = new Vector3(x, y, z); } } public void setEulerAngles(int index, float x, float y, float z) { if (index >= 0 && index < ObjectList.Count) { ObjectList[index].gameObject.transform.eulerAngles = new Vector3(x, y, z); } else if (index < 0) { this.transform.eulerAngles = new Vector3(x, y, z); } } public void SetLocalScale(int index, float x, float y, float z) { if (index >= 0 && index < ObjectList.Count) { ObjectList[index].gameObject.transform.localScale = new Vector3(x, y, z); } else if (index < 0) { this.transform.localScale = new Vector3(x, y, z); } } public void SetLocalScaleX(int index, float x) { if (index >= 0 && index < ObjectList.Count) { var transform = ObjectList[index].gameObject.transform; transform.localScale = new Vector3(x, transform.localScale.y, transform.localScale.z); } else if (index < 0) { transform.localScale = new Vector3(x, transform.localScale.y, transform.localScale.z); } } public void SetMainSpineLocalPosition(float x, float y, float z) { SpineObject.transform.localPosition = new Vector3(x, y, z); } public float GetAnimationDuration(string name) { return skeletonAnimation.skeletonDataAsset.GetAnimationStateData().SkeletonData.FindAnimation(name).Duration; } public void PlayAnimationAndPause(string animName, float percent) { skeletonAnimation.timeScale = 1; animationState.SetAnimation(0, animName, false); var duration = GetAnimationDuration(animName); skeletonAnimation.Update(percent * duration); skeletonAnimation.timeScale = 0; } } }