This Spine-Unity runtime works with data exported from Spine Editor version: 4.1.xx
Package version: spine-unity-4.1-2022-10-04.unitypackage
Imagine the Scenario:Package version: spine-unity-4.1-2022-10-04.unitypackage
1) Play "Roll" Animtion
2) Once finished, play "Idle" animation with MixDuration of 0.5 seconds (quite high!)
3) After 0.25s, play "Run" animation with MixDuration of 0.5 seconds
then repeat steps 2 and 3 over and over again, so you're constantly playing Idle/Run animations 0.25s apart with 0.5s mix time
The bug:
the "Roll" animation seems to retain it's place in the mixingFrom linked list, it never expires, even though it was only played once at the start. I get weird visuals from the blending trying to pull from the Roll animation still, indefinitely (so i still see a fragment of the Roll animation after like 5 minutes of not playing it, aslong as i keep playing idle/walk in the pattern mentioned above)
I suspect it has something to do with mixingFrom linked list not updating properly, specifically the old ones. I never used to have this issue, I assume because mixingFrom is fairly new-ish? Seen from this thread: How to disable multipleMixing in spine3.8
I'm looking suspectly specifically at this snippet of code in AnimationState, although I don't quite fully understand it, I'm having difficulty seeing how the Roll animation would ever expire/finish from the above^
Is this something you could take a look at and try to figure out if I'm correct or not?
If I change the blend time to lower than the 0.25 switching value above, it's fine - it just seems to be anything over the time i am switching between new animations
It would also be nice if there was a way to disable the linked list behaviour of mixingFrom, without that workaround posted in the thread i linked above. I understand there would be a little "animation jump" when mixing between 3 animations, but I'd rather have that than this behaviour and possibly would favor the performance of non-linked-list mixing anyway
/// <summary>Returns true when all mixing from entries are complete.</summary>
private bool UpdateMixingFrom (TrackEntry to, float delta) {
TrackEntry from = to.mixingFrom;
if (from == null) return true;
bool finished = UpdateMixingFrom(from, delta);
from.animationLast = from.nextAnimationLast;
from.trackLast = from.nextTrackLast;
// Require mixTime > 0 to ensure the mixing from entry was applied at least once.
if (to.mixTime > 0 && to.mixTime >= to.mixDuration) {
// Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame).
if (from.totalAlpha == 0 || to.mixDuration == 0) {
to.mixingFrom = from.mixingFrom;
if (from.mixingFrom != null) from.mixingFrom.mixingTo = to;
to.interruptAlpha = from.interruptAlpha;
queue.End(from);
}
return finished;
}
from.trackTime += delta * from.timeScale;
to.mixTime += delta;
return false;
}
EDITprivate bool UpdateMixingFrom (TrackEntry to, float delta) {
TrackEntry from = to.mixingFrom;
if (from == null) return true;
bool finished = UpdateMixingFrom(from, delta);
from.animationLast = from.nextAnimationLast;
from.trackLast = from.nextTrackLast;
// Require mixTime > 0 to ensure the mixing from entry was applied at least once.
if (to.mixTime > 0 && to.mixTime >= to.mixDuration) {
// Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame).
if (from.totalAlpha == 0 || to.mixDuration == 0) {
to.mixingFrom = from.mixingFrom;
if (from.mixingFrom != null) from.mixingFrom.mixingTo = to;
to.interruptAlpha = from.interruptAlpha;
queue.End(from);
}
return finished;
}
from.trackTime += delta * from.timeScale;
to.mixTime += delta;
return false;
}
I just created a little function for myself inside AnimationState to prevent mixingFrom linkedList to never exceed more than 1 mixing from and it seems to solve my problems, i.e. by disabling the linked list behaviour entirely. I would much rather have an official way to do this if possible!!
public void ClearMixingFromDepth()
{
// Ensure no linked list
if (mixingFrom != null) mixingFrom.mixingFrom = null;
}
{
// Ensure no linked list
if (mixingFrom != null) mixingFrom.mixingFrom = null;
}