Two days ago I wanted to get an animation using stretchy bones from 3ds Max to Unity. I tried to simply export it using .fbx, but when I played the animation in Unity, my character, a blob of jello, just waggled a bit, and didn’t squash or stretch. Yesterday I found a working solution, and I thought I’d share this here, just in case someone has a similar problem and finds this.
First a little warning, or two. This might not be suitable for complex rigs, for several reasons, one of which is the second warning: I will be breaking a paradigm here, that I usually adhere to almost religiously. As you might be aware (if not, you will be after reading the next few lines), you should never ever (ever) scale an object that you might want to animate at any point in the future, especially not non-uniformly. Scale only in edit Poly Sub-Object mode or use a XForm Modifier. If you scale on object level, you distort the object’s transformation matrix and all children will move/rotate in this distorted coordinate system. You can easily notice one problem, when you rotate a child of a non-uniformly scaled object. If you really have to scale on object level, always use Reset X-Form afterwards to reset the transformation matrix (rotation is set to (0, 0, 0), scale to (1, 1, 1); position is left untouched), even if you don’t plan on animating the object ever, just to be on the safe side. I try to avoid the pitfalls I know of here, but be careful anyways.
As a little pretext, here is how you’d usually set up a stretchy bone in 3ds Max. First you need a bone (with an end-bone) and two helpers. Align the helpers to the bones, one each. Now all you have to do is use Position Constraints to link the two bones to their respective helpers and a LookAt Constraint to make the parent bone look in the direction of the end-bone’s helper. When you move the helpers around, the bone will stretch to always be the needed length. You can also open the Bone Tools (Animation > Bone Tools) and switch the stretch mode of the bone from ‘scale’ to ‘squash’, which makes the bone get thinner or thicker when you change its length. Sadly Unity (or maybe .fbx) doesn’t import that stretch property.
The solution is not too complex, but also not beginner’s stuff. It involves some scripting and changing controllers, but you should be able to follow this even if you don’t know about these things. If all fails, look at the manual.
I created a single-bone chain (one bone and its end-bone) for each bone in my stretchy chain (I had a simple setup with only two stretchy bones, so I needed two single-bone chains). Position and rotation are handled by a Position Constraint and an Orientation Constraint respectively, both to the stretchy bone. The new bone now stays with the stretchy bone, but it obviously doesn’t scale accordingly. To fix this last thing, I used a Scale Script Controller for the new bone. In this Controller I created a new variable, called Master, and assigned the stretchy bone to it. The script I used is very simple, but it might need some explanation, if you want to understand it (if not, you can still use it without understanding, of course). First the script:
[Master.stretchTM[1][1], Master.stretchTM[2][2], Master.stretchTM[3][3]]
The format expected by the script controller is [X-scale, Y-scale, Z-scale]. The values for each axis, separated by commas in square brackets. Master is of course the reference to the master bone, just as I set it up earlier, and .stretchTM is the stretch Transformation Matrix of that bone. This is a Matrix made from four Point3 vectors (because it has to be multiplied on the nodes transformation matrix; worldTM * stretchTM * objectTM). The first vector has the value for the stretching in x-direction in the first position and two zeros, the second one has the y-stretch in its second position and zeros otherwise, and the third is for the z-stretch. The last vector is completely zero. My script above takes the three stretch values and uses them to scale the model.
Now my new bone follows the stretch bone perfectly, but uses the scale property instead of stretch, and that is exported into Unity perfectly. Now I have a happy, squishy blob in Unity, just waiting for me to make the rest of the game.
But as I said above, scaling bones is dangerous. That is the reason why I use single-bone chains instead of a longer chain. If you try this on a more complex rig, don’t parent any subsequent bones to the scaled ones, only to the stretchy bones. Use the scaled bones only for skinning and exporting (don’t export the stretchy bones, or the children will not be able to move away from their joint, since they would still be parented to the now fixed-length bones), they should not be used to support any other structure of the rig. And don’t forget to write any problems you have in the comments. Then I can update the post to either address that issue, or warn of it.
Here is a screenshot showing the Scale Script dialog and all relevant informations (I hope).
Hi there,
Is there any chance you could please add some more detail? I wouldn’t call myself a complete begninner but I got lost at the scripting part. I tried researching controllers and scripting but with no visual reference I don’t really know what I’m looking for.
Also, for some reason I can’t get this rig setup of stretchy bones to work. My version has just two bones (without end bone) – the first root bone is just linked to a point helper with freeze length unticked and set to squash, and it seems to follow the second bone and stretch nicely. Will your script still work on this or is the second point helper and all the constraints essential?
Thanks very much.
It should also work without the second helper. I am not sure if that setup uses the StretchMatrix, but it there is really no reason, why it should not.
To add the Scale Script, just go to the Motiom Tab, look into the controllers rollout, select the scale controller (not sure right now how the default one is callet exactly, since I am not at my PC right now, hit ‘assign controller’ and choose the scale script controller. I’ll try to remember creating a screen with the settings and stuff of the controller, when I get home.
Gosh, I’m sorry for the late reply – but thanks so much for the extra info. I got it working perfectly!! I’m very grateful, thanks! P.s: you should make a donate button.
Glad you got it working. Don’t think a donate button would do much with the current traffic 😉
In any case I am just writing this stuff down in case someone finds it and finds it useful. The main benefit is that I know where to find this once I forget it XD
Very, very useful! Thanks a lot!