- 수정됨
Disabling inherit scale breaks rotation (v3.4.0.1)
Bug can be reproduced with simple 3 bone setup.
I disable scale inheritance on the last bone and the first bone has key on x or y scale to some negative value. Then if I rotate middle bone, the last one rotates in the wrong direction.
Test project is in attachment.
Go to animation mode and try rotating bone2.
This is an interesting case we encountered while implementing the new scaling in v3. It must work this way if we want to be able to animate scale from negative to positive and have the child not affected. The bone appearing to rotate in the wrong direction is rotating to undo the scaling, which is technically correct (as annoying as it may be).
Disable inherit scale (and disable inherit rotation) is a hold over from pre-v3, where it worked without such behavior because scaling was much simpler (and hardly useful). Disable inherit scale is useful as a convenient way to not inherit scale, but unfortunately the math has some edge cases like you've found. I don't think I've ever seen a 2D or 3D tool that allows to disable a part of the transform, probably to avoid those cases.
As an alternative, you can use a transform constraint (which can also be more powerful). This uses different math and results in disabling scale in a different way. Here is a project showing the setup (Spine Professional is required for transform constraints):
disable_scale_1.spine
I added bone new bone
so I could set its scaleX to -1 instead of flipping the root. Instead of using disable inherit scale on bone3
, it has a transform constraint that copies the scale and shear from the root bone. The end result is that bone3
does not inherit scale from its parents, however this differs from the disable inherit scale checkbox because scaling the parents does cause the rotation to change. To see this, scale bone2
in animate mode.
This is arguably more sane and we could actually change disable inherit scale to work the same way. What do you guys think? If we make this change, affect existing projects who rely on scale not affecting the rotation could be affected and need minor fix up, though I expect most projects would not have any problems (it took 6+ months for someone to report the edge case above).
Note copying the shear is needed to prevent bone3
from flipping over. Since there are no attachments, I added bone4
just so we can see that bone3
does not flip over.
Also note if you wanted to prevent the rotation, you can set the transform constraint rotate mix to 100. You probably want to use a bone specifically to control the rotation though, not the root bone. Here is a project showing this:
disable_scale_2.spine
Thanks for a great reply.
We've found another workaround for our case (disable inherit scale for one more bone up in the hierarchy).
I think that everything can be left in its current state, as you point out this is a very rare case.
I believe the right way is to trying to avoid negative scale as much as you can. Like prefer flipping the attachments in setup pose, not bones.
Transform constraint is a great tool!
Disabling a bone higher in the hierarchy is a bit of a coincidental fix. Rare case or not, it's better for the features to be stable, plus if it's ever going to change then the sooner the less impact it'll have. We've committed new math for the "disable inherit scale" feature to the dev
branch in Git:
[libgdx] New math for disable inherit scale. · EsotericSoftware/spine-runtimes@2dee5d6 · GitHub
The math is better (no loops) and the behavior is more stable, so I think we'll end up merging this to master
.
We're looking to do the same for "disable inherit rotation", which has similar failures (worse in some cases and is also use more often, eg typically with IK to keep feet from rotating with the shin bone) with negative scale, but it's a bit more difficult.
I was just scratching my head having the very same rotation problem, then manually applying the math patch above plus disabling the bone inherit scale fixed the problem.
Great!
We are working on a similar solution for disable inherit rotation, though it's not quite ready.
Experimental disable inherit rotation. · EsotericSoftware/spine-runtimes@438f002 · GitHub