From 39dfca8263a32be7d35148f6a793ccae8a8c4bf5 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Wed, 29 Sep 2021 19:32:48 +0200 Subject: [PATCH] [Unity] Fixed `Update When Invisible` mode causing strange Event timing. Closes #1954. --- spine-csharp/src/AnimationState.cs | 59 +++++++++++-------- .../Components/SkeletonAnimation.cs | 18 +++++- .../spine-unity/Components/SkeletonGraphic.cs | 7 ++- .../spine-unity/Components/SkeletonMecanim.cs | 12 ++++ .../Components/SkeletonRenderer.cs | 6 +- 5 files changed, 72 insertions(+), 30 deletions(-) diff --git a/spine-csharp/src/AnimationState.cs b/spine-csharp/src/AnimationState.cs index e8c97d595..db55683b0 100644 --- a/spine-csharp/src/AnimationState.cs +++ b/spine-csharp/src/AnimationState.cs @@ -309,9 +309,11 @@ namespace Spine { return applied; } - /// Version of only applying EventTimelines for lightweight off-screen updates. + /// Version of only applying and updating time at + /// EventTimelines for lightweight off-screen updates. + /// When set to false, only animation times of TrackEntries are updated. // Note: This method is not part of the libgdx reference implementation. - public bool ApplyEventTimelinesOnly (Skeleton skeleton) { + public bool ApplyEventTimelinesOnly (Skeleton skeleton, bool issueEvents = true) { if (skeleton == null) throw new ArgumentNullException("skeleton", "skeleton cannot be null."); ExposedList events = this.events; @@ -323,24 +325,28 @@ namespace Spine { applied = true; // Apply mixing from entries first. - if (current.mixingFrom != null) ApplyMixingFromEventTimelinesOnly(current, skeleton); + if (current.mixingFrom != null) ApplyMixingFromEventTimelinesOnly(current, skeleton, issueEvents); // Apply current entry. float animationLast = current.animationLast, animationTime = current.AnimationTime; - int timelineCount = current.animation.timelines.Count; - Timeline[] timelines = current.animation.timelines.Items; - for (int ii = 0; ii < timelineCount; ii++) { - Timeline timeline = timelines[ii]; - if (timeline is EventTimeline) - timeline.Apply(skeleton, animationLast, animationTime, events, 1.0f, MixBlend.Setup, MixDirection.In); + + if (issueEvents) { + int timelineCount = current.animation.timelines.Count; + Timeline[] timelines = current.animation.timelines.Items; + for (int ii = 0; ii < timelineCount; ii++) { + Timeline timeline = timelines[ii]; + if (timeline is EventTimeline) + timeline.Apply(skeleton, animationLast, animationTime, events, 1.0f, MixBlend.Setup, MixDirection.In); + } + QueueEvents(current, animationTime); + events.Clear(false); } - QueueEvents(current, animationTime); - events.Clear(false); current.nextAnimationLast = animationTime; current.nextTrackLast = current.trackTime; } - queue.Drain(); + if (issueEvents) + queue.Drain(); return applied; } @@ -434,11 +440,14 @@ namespace Spine { return mix; } - /// Version of only applying EventTimelines for lightweight off-screen updates. + /// Version of only applying and updating time at + /// EventTimelines for lightweight off-screen updates. + /// When set to false, only animation times of TrackEntries are updated. // Note: This method is not part of the libgdx reference implementation. - private float ApplyMixingFromEventTimelinesOnly (TrackEntry to, Skeleton skeleton) { + private float ApplyMixingFromEventTimelinesOnly (TrackEntry to, Skeleton skeleton, bool issueEvents) { TrackEntry from = to.mixingFrom; - if (from.mixingFrom != null) ApplyMixingFromEventTimelinesOnly(from, skeleton); + if (from.mixingFrom != null) ApplyMixingFromEventTimelinesOnly(from, skeleton, issueEvents); + float mix; if (to.mixDuration == 0) { // Single frame mix to undo mixingFrom changes. @@ -452,16 +461,18 @@ namespace Spine { if (eventBuffer == null) return mix; float animationLast = from.animationLast, animationTime = from.AnimationTime; - int timelineCount = from.animation.timelines.Count; - Timeline[] timelines = from.animation.timelines.Items; - for (int i = 0; i < timelineCount; i++) { - Timeline timeline = timelines[i]; - if (timeline is EventTimeline) - timeline.Apply(skeleton, animationLast, animationTime, eventBuffer, 0, MixBlend.Setup, MixDirection.Out); - } + if (issueEvents) { + int timelineCount = from.animation.timelines.Count; + Timeline[] timelines = from.animation.timelines.Items; + for (int i = 0; i < timelineCount; i++) { + Timeline timeline = timelines[i]; + if (timeline is EventTimeline) + timeline.Apply(skeleton, animationLast, animationTime, eventBuffer, 0, MixBlend.Setup, MixDirection.Out); + } - if (to.mixDuration > 0) QueueEvents(from, animationTime); - this.events.Clear(false); + if (to.mixDuration > 0) QueueEvents(from, animationTime); + this.events.Clear(false); + } from.nextAnimationLast = animationTime; from.nextTrackLast = from.trackTime; diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonAnimation.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonAnimation.cs index 4d774134b..1fafbfac8 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonAnimation.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonAnimation.cs @@ -206,8 +206,10 @@ namespace Spine.Unity { return; UpdateAnimationStatus(deltaTime); - if (updateMode == UpdateMode.OnlyAnimationStatus) + if (updateMode == UpdateMode.OnlyAnimationStatus) { + state.ApplyEventTimelinesOnly(skeleton, issueEvents: false); return; + } ApplyAnimation(); } @@ -224,7 +226,7 @@ namespace Spine.Unity { if (updateMode != UpdateMode.OnlyEventTimelines) state.Apply(skeleton); else - state.ApplyEventTimelinesOnly(skeleton); + state.ApplyEventTimelinesOnly(skeleton, issueEvents : true); if (_UpdateLocal != null) _UpdateLocal(this); @@ -246,6 +248,18 @@ namespace Spine.Unity { if (!wasUpdatedAfterInit) Update(0); base.LateUpdate(); } + + public override void OnBecameVisible () { + UpdateMode previousUpdateMode = updateMode; + updateMode = UpdateMode.FullUpdate; + + // OnBecameVisible is called after LateUpdate() + if (previousUpdateMode != UpdateMode.FullUpdate && + previousUpdateMode != UpdateMode.EverythingExceptMesh) + Update(0); + if (previousUpdateMode != UpdateMode.FullUpdate) + LateUpdate(); + } } } diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonGraphic.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonGraphic.cs index c9a2191bb..a11d3409c 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonGraphic.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonGraphic.cs @@ -265,10 +265,13 @@ namespace Spine.Unity { wasUpdatedAfterInit = true; if (updateMode < UpdateMode.OnlyAnimationStatus) return; + UpdateAnimationStatus(deltaTime); - if (updateMode == UpdateMode.OnlyAnimationStatus) + if (updateMode == UpdateMode.OnlyAnimationStatus) { + state.ApplyEventTimelinesOnly(skeleton, issueEvents: false); return; + } ApplyAnimation(); } @@ -303,7 +306,7 @@ namespace Spine.Unity { if (updateMode != UpdateMode.OnlyEventTimelines) state.Apply(skeleton); else - state.ApplyEventTimelinesOnly(skeleton); + state.ApplyEventTimelinesOnly(skeleton, issueEvents: true); if (UpdateLocal != null) UpdateLocal(this); diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonMecanim.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonMecanim.cs index a67b42a87..c32f0fa55 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonMecanim.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonMecanim.cs @@ -140,6 +140,18 @@ namespace Spine.Unity { base.LateUpdate(); } + public override void OnBecameVisible () { + UpdateMode previousUpdateMode = updateMode; + updateMode = UpdateMode.FullUpdate; + + // OnBecameVisible is called after LateUpdate() + if (previousUpdateMode != UpdateMode.FullUpdate && + previousUpdateMode != UpdateMode.EverythingExceptMesh) + Update(); + if (previousUpdateMode != UpdateMode.FullUpdate) + LateUpdate(); + } + [System.Serializable] public class MecanimTranslator { diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs index 935019df8..1ea62a110 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs @@ -554,11 +554,13 @@ namespace Spine.Unity { OnMeshAndMaterialsUpdated(this); } - public void OnBecameVisible () { + public virtual void OnBecameVisible () { UpdateMode previousUpdateMode = updateMode; updateMode = UpdateMode.FullUpdate; + + // OnBecameVisible is called after LateUpdate() if (previousUpdateMode != UpdateMode.FullUpdate) - LateUpdate(); // OnBecameVisible is called after LateUpdate() + LateUpdate(); } public void OnBecameInvisible () {