Browse Source

[Unity] Fixed `Update When Invisible` mode causing strange Event timing. Closes #1954.

Harald Csaszar 4 years ago
parent
commit
39dfca8263

+ 35 - 24
spine-csharp/src/AnimationState.cs

@@ -309,9 +309,11 @@ namespace Spine {
 			return applied;
 		}
 
-		/// <summary>Version of <see cref="Apply"/> only applying EventTimelines for lightweight off-screen updates.</summary>
+		/// <summary>Version of <see cref="Apply"/> only applying and updating time at
+		/// EventTimelines for lightweight off-screen updates.</summary>
+		/// <param name="issueEvents">When set to false, only animation times of TrackEntries are updated.</param>
 		// 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<Event> 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;
 		}
 
-		/// <summary>Version of <see cref="ApplyMixingFrom"/> only applying EventTimelines for lightweight off-screen updates.</summary>
+		/// <summary>Version of <see cref="ApplyMixingFrom"/> only applying and updating time at
+		/// EventTimelines for lightweight off-screen updates.</summary>
+		/// <param name="issueEvents">When set to false, only animation times of TrackEntries are updated.</param>
 		// 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;
 

+ 16 - 2
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();
+		}
 	}
 
 }

+ 5 - 2
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);

+ 12 - 0
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 {
 

+ 4 - 2
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 () {