diff --git a/spine-unity/Assets/spine-unity/BoneFollower.cs b/spine-unity/Assets/spine-unity/BoneFollower.cs index c7d3ea1a2..b1b740281 100644 --- a/spine-unity/Assets/spine-unity/BoneFollower.cs +++ b/spine-unity/Assets/spine-unity/BoneFollower.cs @@ -137,7 +137,16 @@ public void LateUpdate () { if (skeletonTransformIsParent) { // Recommended setup: Use local transform properties if Spine GameObject is the immediate parent thisTransform.localPosition = new Vector3(bone.worldX, bone.worldY, followZPosition ? 0f : thisTransform.localPosition.z); - if (followBoneRotation) thisTransform.localRotation = bone.GetQuaternion(); + if (followBoneRotation) { + var halfRotation = Mathf.Atan2(bone.c, bone.a) * 0.5f; + if (followLocalScale && bone.scaleX < 0) // Negate rotation from negative scaleX. Don't use negative determinant. local scaleY doesn't factor into used rotation. + halfRotation += Mathf.PI * 0.5f; + + var q = default(Quaternion); + q.z = Mathf.Sin(halfRotation); + q.w = Mathf.Cos(halfRotation); + thisTransform.localRotation = q; + } } else { // For special cases: Use transform world properties if transform relationship is complicated Vector3 targetWorldPosition = skeletonTransform.TransformPoint(new Vector3(bone.worldX, bone.worldY, 0f)); @@ -154,11 +163,12 @@ public void LateUpdate () { if (followBoneRotation) { Vector3 worldRotation = skeletonTransform.rotation.eulerAngles; + if (followLocalScale && bone.scaleX < 0) boneWorldRotation += 180f; #if UNITY_5_6_OR_NEWER - thisTransform.SetPositionAndRotation(targetWorldPosition, Quaternion.Euler(worldRotation.x, worldRotation.y, skeletonTransform.rotation.eulerAngles.z + boneWorldRotation)); + thisTransform.SetPositionAndRotation(targetWorldPosition, Quaternion.Euler(worldRotation.x, worldRotation.y, worldRotation.z + boneWorldRotation)); #else thisTransform.position = targetWorldPosition; - thisTransform.rotation = Quaternion.Euler(worldRotation.x, worldRotation.y, skeletonTransform.rotation.eulerAngles.z + bone.WorldRotationX); + thisTransform.rotation = Quaternion.Euler(worldRotation.x, worldRotation.y, worldRotation.z + bone.WorldRotationX); #endif } else { thisTransform.position = targetWorldPosition; diff --git a/spine-unity/Assets/spine-unity/SkeletonAnimator.cs b/spine-unity/Assets/spine-unity/SkeletonAnimator.cs index 5bdbcd0d7..c9d0c4da6 100644 --- a/spine-unity/Assets/spine-unity/SkeletonAnimator.cs +++ b/spine-unity/Assets/spine-unity/SkeletonAnimator.cs @@ -28,7 +28,9 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -// Contributed by: Mitch Thompson +#if UNITY_5_6_OR_NEWER +#define UNITY_CLIPINFOCACHE +#endif using UnityEngine; using System.Collections.Generic; @@ -116,21 +118,29 @@ public enum MixMode { AlwaysMix, MixNext, SpineStyle } readonly Dictionary animationTable = new Dictionary(IntEqualityComparer.Instance); readonly Dictionary clipNameHashCodeTable = new Dictionary(AnimationClipEqualityComparer.Instance); readonly List previousAnimations = new List(); - #if UNITY_2017_1_OR_NEWER + #if UNITY_CLIPINFOCACHE readonly List clipInfoCache = new List(); readonly List nextClipInfoCache = new List(); #endif - Animator animator; + Animator animator; public Animator Animator { get { return this.animator; } } public void Initialize (Animator animator, SkeletonDataAsset skeletonDataAsset) { this.animator = animator; + + previousAnimations.Clear(); + animationTable.Clear(); - clipNameHashCodeTable.Clear(); var data = skeletonDataAsset.GetSkeletonData(true); foreach (var a in data.Animations) animationTable.Add(a.Name.GetHashCode(), a); + + clipNameHashCodeTable.Clear(); + #if UNITY_CLIPINFOCACHE + clipInfoCache.Clear(); + nextClipInfoCache.Clear(); + #endif } public void Apply (Skeleton skeleton) { @@ -255,7 +265,7 @@ void GetAnimatorClipInfos ( out int nextClipInfoCount, out IList clipInfo, out IList nextClipInfo) { - #if UNITY_2017_1_OR_NEWER + #if UNITY_CLIPINFOCACHE clipInfoCount = animator.GetCurrentAnimatorClipInfoCount(layer); nextClipInfoCount = animator.GetNextAnimatorClipInfoCount(layer); if (clipInfoCache.Capacity < clipInfoCount) clipInfoCache.Capacity = clipInfoCount;