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

This commit is contained in:
Harald Csaszar 2021-09-29 19:32:48 +02:00
parent a3f463a416
commit 39dfca8263
5 changed files with 72 additions and 30 deletions

View File

@ -309,9 +309,11 @@ namespace Spine {
return applied; 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. // 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."); if (skeleton == null) throw new ArgumentNullException("skeleton", "skeleton cannot be null.");
ExposedList<Event> events = this.events; ExposedList<Event> events = this.events;
@ -323,24 +325,28 @@ namespace Spine {
applied = true; applied = true;
// Apply mixing from entries first. // Apply mixing from entries first.
if (current.mixingFrom != null) ApplyMixingFromEventTimelinesOnly(current, skeleton); if (current.mixingFrom != null) ApplyMixingFromEventTimelinesOnly(current, skeleton, issueEvents);
// Apply current entry. // Apply current entry.
float animationLast = current.animationLast, animationTime = current.AnimationTime; float animationLast = current.animationLast, animationTime = current.AnimationTime;
int timelineCount = current.animation.timelines.Count;
Timeline[] timelines = current.animation.timelines.Items; if (issueEvents) {
for (int ii = 0; ii < timelineCount; ii++) { int timelineCount = current.animation.timelines.Count;
Timeline timeline = timelines[ii]; Timeline[] timelines = current.animation.timelines.Items;
if (timeline is EventTimeline) for (int ii = 0; ii < timelineCount; ii++) {
timeline.Apply(skeleton, animationLast, animationTime, events, 1.0f, MixBlend.Setup, MixDirection.In); 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.nextAnimationLast = animationTime;
current.nextTrackLast = current.trackTime; current.nextTrackLast = current.trackTime;
} }
queue.Drain(); if (issueEvents)
queue.Drain();
return applied; return applied;
} }
@ -434,11 +440,14 @@ namespace Spine {
return mix; 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. // 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; TrackEntry from = to.mixingFrom;
if (from.mixingFrom != null) ApplyMixingFromEventTimelinesOnly(from, skeleton); if (from.mixingFrom != null) ApplyMixingFromEventTimelinesOnly(from, skeleton, issueEvents);
float mix; float mix;
if (to.mixDuration == 0) { // Single frame mix to undo mixingFrom changes. if (to.mixDuration == 0) { // Single frame mix to undo mixingFrom changes.
@ -452,16 +461,18 @@ namespace Spine {
if (eventBuffer == null) return mix; if (eventBuffer == null) return mix;
float animationLast = from.animationLast, animationTime = from.AnimationTime; float animationLast = from.animationLast, animationTime = from.AnimationTime;
int timelineCount = from.animation.timelines.Count; if (issueEvents) {
Timeline[] timelines = from.animation.timelines.Items; int timelineCount = from.animation.timelines.Count;
for (int i = 0; i < timelineCount; i++) { Timeline[] timelines = from.animation.timelines.Items;
Timeline timeline = timelines[i]; for (int i = 0; i < timelineCount; i++) {
if (timeline is EventTimeline) Timeline timeline = timelines[i];
timeline.Apply(skeleton, animationLast, animationTime, eventBuffer, 0, MixBlend.Setup, MixDirection.Out); if (timeline is EventTimeline)
} timeline.Apply(skeleton, animationLast, animationTime, eventBuffer, 0, MixBlend.Setup, MixDirection.Out);
}
if (to.mixDuration > 0) QueueEvents(from, animationTime); if (to.mixDuration > 0) QueueEvents(from, animationTime);
this.events.Clear(false); this.events.Clear(false);
}
from.nextAnimationLast = animationTime; from.nextAnimationLast = animationTime;
from.nextTrackLast = from.trackTime; from.nextTrackLast = from.trackTime;

View File

@ -206,8 +206,10 @@ namespace Spine.Unity {
return; return;
UpdateAnimationStatus(deltaTime); UpdateAnimationStatus(deltaTime);
if (updateMode == UpdateMode.OnlyAnimationStatus) if (updateMode == UpdateMode.OnlyAnimationStatus) {
state.ApplyEventTimelinesOnly(skeleton, issueEvents: false);
return; return;
}
ApplyAnimation(); ApplyAnimation();
} }
@ -224,7 +226,7 @@ namespace Spine.Unity {
if (updateMode != UpdateMode.OnlyEventTimelines) if (updateMode != UpdateMode.OnlyEventTimelines)
state.Apply(skeleton); state.Apply(skeleton);
else else
state.ApplyEventTimelinesOnly(skeleton); state.ApplyEventTimelinesOnly(skeleton, issueEvents : true);
if (_UpdateLocal != null) if (_UpdateLocal != null)
_UpdateLocal(this); _UpdateLocal(this);
@ -246,6 +248,18 @@ namespace Spine.Unity {
if (!wasUpdatedAfterInit) Update(0); if (!wasUpdatedAfterInit) Update(0);
base.LateUpdate(); 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();
}
} }
} }

View File

@ -265,10 +265,13 @@ namespace Spine.Unity {
wasUpdatedAfterInit = true; wasUpdatedAfterInit = true;
if (updateMode < UpdateMode.OnlyAnimationStatus) if (updateMode < UpdateMode.OnlyAnimationStatus)
return; return;
UpdateAnimationStatus(deltaTime); UpdateAnimationStatus(deltaTime);
if (updateMode == UpdateMode.OnlyAnimationStatus) if (updateMode == UpdateMode.OnlyAnimationStatus) {
state.ApplyEventTimelinesOnly(skeleton, issueEvents: false);
return; return;
}
ApplyAnimation(); ApplyAnimation();
} }
@ -303,7 +306,7 @@ namespace Spine.Unity {
if (updateMode != UpdateMode.OnlyEventTimelines) if (updateMode != UpdateMode.OnlyEventTimelines)
state.Apply(skeleton); state.Apply(skeleton);
else else
state.ApplyEventTimelinesOnly(skeleton); state.ApplyEventTimelinesOnly(skeleton, issueEvents: true);
if (UpdateLocal != null) if (UpdateLocal != null)
UpdateLocal(this); UpdateLocal(this);

View File

@ -140,6 +140,18 @@ namespace Spine.Unity {
base.LateUpdate(); 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] [System.Serializable]
public class MecanimTranslator { public class MecanimTranslator {

View File

@ -554,11 +554,13 @@ namespace Spine.Unity {
OnMeshAndMaterialsUpdated(this); OnMeshAndMaterialsUpdated(this);
} }
public void OnBecameVisible () { public virtual void OnBecameVisible () {
UpdateMode previousUpdateMode = updateMode; UpdateMode previousUpdateMode = updateMode;
updateMode = UpdateMode.FullUpdate; updateMode = UpdateMode.FullUpdate;
// OnBecameVisible is called after LateUpdate()
if (previousUpdateMode != UpdateMode.FullUpdate) if (previousUpdateMode != UpdateMode.FullUpdate)
LateUpdate(); // OnBecameVisible is called after LateUpdate() LateUpdate();
} }
public void OnBecameInvisible () { public void OnBecameInvisible () {