# Boing Kit: Dynamic Bouncy Bones (with tech breakdown)

Hi, all. I’ve finally finished my bouncy bone tech addition to my Unity extension. I initially used Unity-Chan as my test model, but then I decided that I wanted to make my own test model, doubling as a mascot for this extension, so I began learning Blender and made UFO Bunny.

This is a silly video I made that shows off UFO Bunny being initially stiff and becoming bouncy when the bouncy bones feature is turned on. Later on, the video also demonstrates some other applications of the core bouncy tech.

Here is a tech breakdown of how I made the bouncy bones effects:

Data Definition & Construction

First off, I build a chain of bone data by specifying a root bone, referenced by the bone’s Transform component. Then I perform a breadth-first search to visit all of the transform’s direct and indirect children. All the transforms visited are added to an array of bone data in the visited order. This way, when I want to iterate through the bone data, I can just go through the array once from start to end, guaranteed to always process parents first and then the children. Thus, when it’s a child’s turn to be processed and it needs to inherit proceed data from its parent (e.g. transform, bone chain length from root, etc.), the parent’s data would have already been processed earlier in the array.

Making the Bones Bouncy

The core bouncy logic makes use of numeric springing (Intro / Examples / More Info). It is essentially a specialized type of soft constraint. When given a target value (e.g. float, vector, etc.), a numeric spring tracks its current value closer towards the target by each simulation step, with smooth-changing velocity. For bouncy bones, the core problem is how to compute the target transforms for the bones to be sprung to.

I model the problem using “pose stiffness” and “length stiffness”, each of which can be defined as a curve, where the input is the percentage of a bone’s chain length from root v.s. the entire chain length, and the output is the stiffness percentage.

I define pose stiffness as a child bone’s desire to maintain its relative transform to its parent. So for a bone with full pose stiffness, its target transform is its relative transform to its parent appendeded to its parent’s current transform spring values in world space.

As for length stiffness, I define it as a child bone’s desire to maintain its distance from its parent. So for a bone with full length stiffness, its target transform will maintain the same distance away from its parent’s current transform spring values. Further, during each time step, I remove a percentage equal to length stiffness from a child bone’s linear velocity parallel to the vector pointing from its parent to itself, so at full stiffness, there will be no linear velocity component that would alter the distance between the two.

With the target transforms (positions & rotations) defined, the next step is to simulate the numeric springs to track the target values. For position, it’s pretty straight forward: just apply numeric springing to individual vector components. However, with rotation, it’s a bit tricky. There are multiple ways to represent rotation in 3D, the most common being (1) 3x3 transform matrices, (2) axis-angle vectors (direction is rotation axis & magnitude is rotation angle), and (3) quaternions.

At first I chose (2) axis-angle vectors, because I’ve been accumulating effectors in this data format (more on effector’s later). So my first try on rotation spring is basically a vector spring, where the vector is the axis-angle vector that gets converted to quaternions as a final step (formula here). At first, I thought it was working alright, until I noticed occasional kinks in UFO Bunny’s ear (can be observed here when she spin around). Upon further investigation, it was due to the “360-degree wrap-around problem”. Basically, a target axis-angle vector of length PI (180 degree) is equivalent to its negated vector, because rotating 180 degrees around an axis is the same as rotating 180 degrees around the opposite axis. So while the logical & spatial target rotation remains the same, the underlying target vector changes drastically, shooting the numeric spring in the other direction wildly.

I tried various way to come up with a mathematically correct way to spring quaternions, but only got as close as to figuring out how to spring a point on a 3D unit sphere surface, and I haven’t been able to extend that to 4D (yet). I thought the the 3D unit sphere spring was already too computationally heavy for this task, let alone trying to extend it to 4D, so I decided to cheat by just springing individual components of quaternions as if they are 4D vectors. And, the values are normalized before being read back from the spring into quaternions. It’s not ideal. The rotation angle is not sprung in a mathematically correct way. But hey, it LOOKS OKAY, and it’s computationally cheap. So that is my final solution.

You can find my code for vector & quaternion springs here.

Effector Accumulation

Effectors are force sources that push or pull things around. I mentioned earlier that I implement this logic using angle-axis vectors. The reasoning comes from torque accumulation in physics simulation. No matter in which order you apply a series of forces, the resulting accumulated torque is always the same. In other words, torque application is order-independent. It is done by taking the cross product each force with the vector from the center of mass to the point of force application. Adding these cross products together gives the final total torque from all forces.

I wanted effectors to apply rotational effects in the same order-independentway, so I accumulate their rotational effects by adding together the cross products of each effector’s linear velocity vector and the vector from the affected object’s center to the effector’s center. Once I have the final accumulated rotational effect, I convert it to a quaternion and combined with a bone’s target rotation, computed via the method mentioned above.

Transform Update

Lastly, I have the sprung transform results, and I have to apply them to the bone’s Transform component. I can’t just set the Transform component’s position and rotation to the sprung values, because what values can I base off of to compute new target values in the next frame? So I cache the bone’s original transform (position, rotation, and scale; why scale? more on that later) at the beginning of LateUpdate, compute the target transforms, update the transform springs, set the transform values to the sprung values, so the renderer would use these values for rendering, and then restore the transform back to the cached values post-render (using the Camera.OnPostRender() delegate).

Squash & Stretch

I cache scale as well because there’s an additional feature that alters a bone’s scale for volume preservation (squash & stretch). Imagine a rubber block that’s stretched to 4 times its original length in the direction of, say, its local Z axis. If nothing is done to its scale, its volume would become 4 times as large. This is where squash & stretch comes in. To maintain volume, the block needs to be shrunk in the directions perpendicular to the stretching axis, in this case, its X and Y axes. The scale value to shrink to in each perpendicular axis is the square root of the reciprocal of the stretch amount; in this case, it is 1/2 in both the local X and Y axes (4 * (1/2) * (1/2) == 1). Same thing applies when the block is squashed to 1/4 its original length, its local scale in X and Y axes would need to become 2 to maintain volume.

I have the information of each child bone’s original distance from its parent. It is compared to the distance between the sprung child bone and its parent. If the sprung distance is larger than the original, it’s stretched; otherwise, it’s squashed. Bones are scaled accordingly to create the sense of volume preservation.

That’s all!
Feel free to ask if you’d like me to elaborate on certain details or explain things I forgot to mention.
And I hope you like the video!

5 Likes

I love the Asset but I have one question

As soon as I duplicate a prefab I loose the effect and get this warning:

There should be one material data entry per instance. Instance data entries: 2, material data entries: 1.

Hi. I just grabbed this yesterday and I’m having some fun with it. I’m wondering if you can help me figure out a couple things.

I threw this on my character which has a hat with several bones. When I start running, the tail of the hat is very jumpy. What should I be looking at in particular to change this? Is there a framerate setting that needs to be changed to 60?

I also wanted to see if this was a better solution to what I’m using for my character’s chest physics, so I threw it on there too. The chest has two bones for each side and they’re pointing slightly outwards, so flat collision from the spine might not be a solution for me. When walking/running, the chest sinks deep inside itself. What should I be changing so that there’s drastically less of this effect? Or maybe boing bones is the wrong technique for this?

Thank you.

Just purchased and I’m enjoying playing around with the Boing Bones portion.

However, I am using the Universal RP (Unity 2019.3.01f) and I have no idea how to implement the custom shader needed for Boing Fields, etc. to work with URP, or whether that would be possible at all? At a guess I’m thinking some code could be added through a custom function node in Shader Graph, but other than that I don’t know exactly (I am not experienced at hand-coding shaders).

I understand URP support hasn’t been listed (or Shader Graph), but I’m hoping it’s possible, or perhaps support might be added at some point?

1 Like

Hi.

Can you elaborate on your repro steps? Which component did you use? What are the steps did you take to construct and duplicate the prefab?

Thanks.

Hi.

As of now, the only way to get the reactor field effects on meshes in SRP is by calling the shader functions provided in your vector shaders. I am looking into making it available as a node in shader graph.

2 Likes

Hi.

Boing bones are updated via fixed update for stability reasons, so game objects that use boing boing should also update their transforms in fixed update.

Also, I’m not sure I can picture the chest problem properly. Would you be able to provide gifs or animations showing the issues your are having?

What would help me figure out the cause of both issues better is if you can send your project (or a stripped-down version that is the bare minimum needed to repro the issues) to me via email, so I can debug it.

I was able to get rid of the error, turned out the prefab was static.
Is GPU instancing supported?

You mean instancing objects with the reactor field GPU sampler component? The provided example standard materials support instancing, yes. As for custom shaders using Boing Kit’s shader functions in vertex shaders, it’s up to the custom shader to enable and support instancing.

Yes the standard material, thanks for confirming

Any way to add bone chain to non skinned object using your asset?
I want to animate a long plant, it’s not skinned and if I add reactor - it reacts only when I touch the root of the plant. I want it to be more flexible.

I’m really enjoying Boing Kit! Thank-you for making it.

How do I set up Exclusion in a bone chain?
Adding transforms to the Exclusion array causes an error on launch.

IndexOutOfRangeException: Index was outside the bounds of the array.
BoingKit.BoingWork+Params+InstanceData.PullResults (BoingKit.BoingBones bones) (at Assets/Boing Kit/Script/BoingWork.cs:493)
BoingKit.BoingWork+Params.PullResults (BoingKit.BoingBones bones) (at Assets/Boing Kit/Script/BoingWork.cs:828)
BoingKit.BoingWorkAsynchronous.PullBonesResults (BoingKit.BoingEffector+Params[] aEffectorParams, System.Collections.Generic.Dictionary`2[TKey,TValue] bonesMap) (at Assets/Boing Kit/Script/BoingWorkAsynchronous.cs:291)
BoingKit.BoingManager.PullBonesResults () (at Assets/Boing Kit/Script/BoingManager.cs:683)
BoingKit.BoingManager.LateUpdate () (at Assets/Boing Kit/Script/BoingManager.cs:378)
BoingKit.BoingManagerUpdatePump.LateUpdate () (at Assets/Boing Kit/Script/BoingManagerUpdatePump.cs:26)

Hello, we have evaluated this plugin and appreciate your work very much.
I want to ask if we want to use unity collision without adding collision one by one, juat automatically adding all the colliders in the scene, or 10 colliders near this bone, is this possible?

Hi,

I would like to ask if you have encountered the following behaviour, or know why this is happening:

When I press play mode, in the scene view the boing effector/reactor works (actually copied from a demo scene), but in the game window nothing is happening, see sample video:

Unity 2018.4.14f1 in use.

Hi, wondered if anyone can comment on this? Many thanks.

Ever since the latest object I’m having problems with objects with gravity applied. They shake constantly, in FixedUpdate and Update mode.

Unfortunately I don’t think the developer reads this forum.

Time for a refund… no support it seems… its a pity.

@dock @montify @khos @Source-technology
Somehow Unity Forums unchecked my email notification (seems like others are experiencing the same issue). I’ve re-enabled the option and will check the forums every more often to make sure the email notification is actually working.

So here are my replies to your questions:

@dock

1. When this exception was thrown, did you add transforms to the exclusion in edit mode, in play mode, or via script in play mode?
2. Can you send me your project (stripped down to the essentials if it’s too large) via email, so I can look at your use case? (longbunnylabs@gmail.com)

@montify
Sorry. The boing bones component only works with skinned mesh or transform hierarchy. I think I’ve seen an asset that lets you paint vertex weight and add extra bones directly in Unity with a simple UI. However, I don’t think I’ll have the time and manpower to include a similar feature, nor will I be able to create an in-editor skinning feature nearly as good as any existing professional 3D modeling software like Blender or Maya.

@khos
What is the version of Boing Kit you’re using? There was an update (v1.2.12) that addresses multi-view issues in the editor. If you’re already using a version as new as v1.2.12 and this issue still occurs, can you email me your project (stripped down to the essentials if the project is too large), so I can take a closer look? (longbunnylabs@gmail.com)

@Source-technology
Sorry. Such feature is not currently supported, but let me do some research first and see if there’s anything I can do to include such feature in future updates.

@Allen-Chou

I have a question about the collision.
Can i receive collision event from “boing collider” or “unity collider” collision?

The boing bones component does not dispatch such events, and I intend to keep it that way, in order not to introduce extra performance overhead for the users that don’t need them.

However, you can achieve the same results by adding trigger colliders to the bones/transforms of your interest.