Nate написавCare to explain?
Hi there, I'm the programmer working on the Code: HARECORE project.
There are several problems in the Spine runtime, it becomes really long as I wrote, so I will post them one by one as I complete them one by one 🙂
The most important of all, the method of updating animation timelines are wrong.
Think of the following case. A bone has a rotation of 0 degree in setup pose. We now play animation A and B at the same time, both with weight (or call it 'alpha') of 50%. In one frame, if the bone has a rotation of 20 degree in A, and a rotation of 40 degree in B (as the illustration below), what is expected to happen? After all the updates, the bone should have a rotation of 30 degree, right?
A
---
[Bone]
---
B
20 30 40
However, check out the code in RotateTimeline.Apply(), which does the following:
float delta = frames[frame + VALUE] - prevFrameValue;
float amount = bone.data.rotation + (prevFrameValue + delta * percent) - bone.rotation;
bone.rotation = bone.rotation + amount * alpha;
In our case, we don't consider interpolation for now, so 'delta' will be 0. OK, then we start updating the rotation timeline of A:
float amount = 0 + (20 + 0 * percent) - 0 = 20;
bone.rotation = 0 + 20 * 0.5 = 10;
Exactly what we want, right? But, when we start updating B:
float amount = 0 + (40 + 0 * percent) - 10 = 30;
bone.rotation = 10 + 30 * 0.5 = 25;
25, not 30. This is exactly where things gone wrong.
Typically, you set your rig to setup pose at the start of each update, and when you updating a timeline, YOU DON'T READ THE CURRENT DATA OF THE BONE. YOU JUST WRITE TO THE CURRENT DATA OF THE BONE.
We modified the update of timeline as the following:
float amount = prevFrameValue + delta * percent;
bone.rotation = bone.rotation + amount * alpha;
We think about the case again.
// Updating A
float amount = 20 + 0 * percent = 20;
bone.rotation = 0 + 20 * 0.5 = 10;
// Updating B
float amount = 40 + 0 * percent = 40;
bone.rotation = 10 + 40 * 0.5 = 30;
We do our aiming animation using a blend tree 1D, like aim-90, aim-45, aim_0, aim_45 and aim_90. We have to care about precision you know 🙁