Hey everyone. So in response to a question asked in another topic, I came up with this system for having bones jiggle around based on a very crude / simple physics model. The physics part is a modified version of Pegorari's "Rubber Simulation Script" (http://forum.unity3d.com/threads/45148-Rubber-Simulation-Script?highlight=rubber+duck) but instead of modifying vertex positions, it applies the results to bone rotations. It also has a "squash and stretch" function, which helps to add a little bit of extra fluid motion. It can be used for effects like bouncy breasts, bouncy hair, etc. Hope you guys like. Also if anyone has any ideas on how to improve it, please contribute: The webplayer has settings set WAY too high. It's set that way for demonstration purposes only, and would have to be adjusted to more real world settings. Screenshot: Webplayer: http://www.mikecookportfolio.com/jiggleBone/jiggleBoneWeb.html And link to the Wiki: Jiggle Bone Unity Wiki
i am working on a character that has jiggly fat. this could be ideal, i cant seem to view the web demo it just asks me to instal the unity player but the one it downloads is older than the one i have installed. nice share though Arthur
Great job, and thanks for sharing.. this is making my dream of a video game with nothing but REALLY fat people look all the better.
@ Lemo Believe it or not, I have no idea where that project went . . . :T Its pretty straight forward, just drag the script onto a transform of the bone on your mesh. You will have to know what axis to shoot it down. For me I had the bone axis set to Z forward, meaning the Z axis was looking down the length of the bone. You can change which axis it uses in the script though so you can mess with the values. If you're still having problems just ask!
Hi. So, I have a bunch of 3d models that are .FBX files from the asset store. I wanted to try this on them. But, they do not have any bones defined for inside the boobs. So, is it possible? Would I have to define new bones in a modeling program and somehow remap the mesh to them? Is there anyway to do this from within Unity (or if not through some plugin to unity?) Because none of the models I have currently has bones to control the boobs as far as I can tell.
Wow, thanks for the great job. And for those who have bones facing -X axis, I made some changes on your code so it works on standard 3dsmax export bones. Code (csharp): // Set bone rotation to look at dynamicPos //transform.LookAt(dynamicPos, upVector); Vector3 negXAxis = (dynamicPos - transform.position).normalized; Vector3 negZAxis = Vector3.Cross(negXAxis, upVector); // -Z = -X cross oldup Vector3 newUp = Vector3.Cross (negZAxis, negXAxis); // Y = -Z cross -X transform.LookAt(transform.position + (-negZAxis), newUp );
So I'm using this and trying to get the workflow down with makehuman to blender to unity. I'm almost there, but for some reason, even with the adjustments TMPxyz added I still have bones that seem to want to point out from straight. As if they are being pushed apart (rotated on the vertical axis) away from each other by about 15 degrees each. This makes a nice separate on some models but on my current one, it would be nice to make them seem a little more 'perky and straight'. Does anyone have tips for Blender rigging and importing to unity? I'm able to use the humanoid rig setup in unity and I do get the bounce effect, however the axis are definitely off and all of my tests have come up with inverted meshes. The only current way it works is to have all axis set to 0. Thanks for this however, since I'm sure its just something simple I am not seeing yet. It really is very configurable. EDIT --- So I found out that my export settings, or some other setting isn't allowing the bone in blender to face the 'right' way, so I had to go by the transform gizmo and a lot of guesswork to get it to the right angle. Once I was able to get it to face forward (z) and have y up the original script worked great. Pro Tip: position the bones where you want the rotation to be based out of. For a while I had my bones outside the mesh (so they were easy to grab) but I soon found my deformation in unity rotation oddly outside the 'mesh body'. Now the extra jiggle control bones are back inside the mesh and it rotates / squishes properly!
We should be paying tribute to the pioneer of breast physics: http://www.youtube.com/watch?v=Wn2IjM7b6yI
I just discovered this not to long ago and at the moment I'm playing with this. i was having some trouble with it screwing up my mesh. the bone rotation was all over the place.... (I think imported that way.) or because of this code. Code (csharp): // Set bone rotation to look at dynamicPos transform.LookAt(dynamicPos, upVector); And since I'm a newb and am clueless as to figure out the problem with that code so i ended up writing a line to give control of the rotation of the bones. i haven't fully tested to see if messing around with the rotation kills the jiggle action. its shouldn't really considering my bone rotation was completely out of wack and they were still jiggling. but I'll test, and get back to it. Code (csharp): // set the bone rotation transform.localRotation = new Quaternion (boneAxis.X, boneAxis.Y, boneAxiz.Z, 0.0f);
Recently I noticed the items using jiggle bone in my application had started behaving oddly, as if there was little or no effect applied at all. As I hadn't changed anything in my project, this puzzled me. After some testing, I realized this had to do with my new monitor. Before I had a 60 Hz one, and my new one is 144Hz. It appears that jiggle bone does not take time into account when making its calculations, making it frame dependent, which is very bad. Also, time scale does not seem to affect it, which is also bad. The changes needed to fix this is a bit over my head, but if anyone could take a look at this it would be awesome. Probably just a couple of multiplications with deltatime and timescale.
Many thanks, my blender export had issues, Z axis pointing to the left, X axis pointing to the front and the other side to the back. I used your script and adjusted the original UP value and it works pretty good.
I always said that the best inventions on the internet were driven by sex. This code has so many applications ... and I will tell you some once I have finished tweaking the Y axis. Why was this not part of Tomb Raider? All the best. Iain
I think it was on some Tomb Raider games but very slight, you have to look for it to notice it. Anyway, I still having some problems, it was working fine but when I rotated the whole character it got weird again, can't we retrieve the axes and compare it to the world and apply UP and gravity correctly? I'll try to study/understand the code further.
I failed to retrieve and set the rotation automatically, I added extra parameters, increment the rotation by 90s, trial and error works fine. Code (csharp): // ============================================================ // Name: Jiggle Bone v.1.0 // Author: Michael Cook (Fishypants) // Edited by: Atmey // Date: 9-3-2013 // License: Free to use. Any credit would be nice :) // // To Use: // Drag this script onto a bone. (ideally bones at the end) // Set the boneAxis to be the front facing axis of the bone. // Done! Now you have bones with jiggle dynamics. // // ============================================================ using UnityEngine; using System.Collections; public class jiggleBone : MonoBehaviour { public bool debugMode = true; // Target and dynamic positions Vector3 targetPos = new Vector3(); Vector3 dynamicPos = new Vector3(); // Bone settings public Vector3 boneAxis = new Vector3(0,0,1); public float targetDistance = 2.0f; public Vector3 upDirection = new Vector3(0,1,0); public Vector3 extraRotation = new Vector3(0,0,0); // Dynamics settings public float bStiffness = 0.1f; public float bMass = 0.9f; public float bDamping = 0.75f; public float bGravity = 0.75f; // Dynamics variables Vector3 force = new Vector3(); Vector3 acc = new Vector3(); Vector3 vel = new Vector3(); // Squash and stretch variables public bool SquashAndStretch = true; public float sideStretch = 0.15f; public float frontStretch = 0.2f; void Awake(){ // Set targetPos and dynamicPos at startup Vector3 targetPos = transform.position + transform.TransformDirection(new Vector3((boneAxis.x * targetDistance),(boneAxis.y * targetDistance),(boneAxis.z * targetDistance))); dynamicPos = targetPos; } void LateUpdate(){ // Reset the bone rotation so we can recalculate the upVector and forwardVector transform.rotation = new Quaternion(); //transform.localRotation = originalQuat; // Update forwardVector and upVector Vector3 forwardVector = transform.TransformDirection(new Vector3((boneAxis.x * targetDistance),(boneAxis.y * targetDistance),(boneAxis.z * targetDistance))); Vector3 upVector = transform.TransformDirection(upDirection); //upVector = upDirection; // Calculate target position Vector3 targetPos = transform.position + transform.TransformDirection(new Vector3((boneAxis.x * targetDistance),(boneAxis.y * targetDistance),(boneAxis.z * targetDistance))); // Calculate force, acceleration, and velocity per X, Y and Z force.x = (targetPos.x - dynamicPos.x) * bStiffness; acc.x = force.x / bMass; vel.x += acc.x * (1 - bDamping); force.y = (targetPos.y - dynamicPos.y) * bStiffness; force.y -= bGravity / 10; // Add some gravity acc.y = force.y / bMass; vel.y += acc.y * (1 - bDamping); force.z = (targetPos.z - dynamicPos.z) * bStiffness; acc.z = force.z / bMass; vel.z += acc.z * (1 - bDamping); // Update dynamic postion dynamicPos += vel + force; // Set bone rotation to look at dynamicPos transform.LookAt(dynamicPos, upVector); //Apply extra rotation transform.Rotate(extraRotation,Space.Self); // ================================================== // Squash and Stretch section // ================================================== if(SquashAndStretch){ // Create a vector from target position to dynamic position // We will measure the magnitude of the vector to determine // how much squash and stretch we will apply Vector3 dynamicVec = dynamicPos - targetPos; // Get the magnitude of the vector float stretchMag = dynamicVec.magnitude; // Here we determine the amount of squash and stretch based on stretchMag // and the direction the Bone Axis is pointed in. Ideally there should be // a vector with two values at 0 and one at 1. Like Vector3(0,0,1) // for the 0 values, we assume those are the sides, and 1 is the direction // the bone is facing float xStretch; float yStretch; float zStretch; if(boneAxis.x == 0) xStretch = 1 + (-stretchMag * sideStretch); else xStretch = 1 + (stretchMag * frontStretch); if(boneAxis.y == 0) yStretch = 1 + (-stretchMag * sideStretch); else yStretch = 1 + (stretchMag * frontStretch); if(boneAxis.z == 0) zStretch = 1 + (-stretchMag * sideStretch); else zStretch = 1 + (stretchMag * frontStretch); // Set the bone scale transform.localScale = new Vector3(xStretch, yStretch, zStretch); } // ================================================== // DEBUG VISUALIZATION // ================================================== // Green line is the bone's local up vector // Blue line is the bone's local foward vector // Yellow line is the target postion // Red line is the dynamic postion if(debugMode){ Debug.DrawRay(transform.position, forwardVector, Color.blue); Debug.DrawRay(transform.position, upVector, Color.green); Debug.DrawRay(targetPos, Vector3.up * 0.2f, Color.yellow); Debug.DrawRay(dynamicPos, Vector3.up * 0.2f, Color.red); } // ================================================== } }
Anyone have any luck using this (brilliant) script with fbx exports from Maya? Z forward, Y up isnt working and, it seems, no matter which way I orient the bones Im getting pretty narly results. It looks like the script is twisting the bones 90 degrees to the right of the character, but reorienting them to counter doesnt fix it. C# is pretty foreign to me, so Im perhaps failing to see something in the script. I have gotten better results using Atmeys update, but the gravities is still wrong and not getting anything like the results in the webplayer. Any tips?
My bone is facing -x, I use TMPxyz 's code but not get luck, I found the bone facing -x should use -x as forward(not z) and lookat "dynamicPos", so I should't use Code (csharp): transform.LookAt(...) I use custom lookat matrix to make my bone's x axis as forward Code (csharp): //由 X 當 forward 的 lookat. static public Matrix4x4 LookAtFromX(Vector3 eye, Vector3 target, Vector3 up) { //http://games.greggman.com/game/webgl-3d-cameras/ //http://3dgep.com/?p=1700#The_View_Matrix //http://msdn.microsoft.com/en-us/library/windows/desktop/bb281710(v=vs.85).aspx Vector3 vx = eye - target; // The "forward". vx.Normalize(); Vector3 vz = Vector3.Cross(up, vx);// The "right" . // vy doesn't need to be normalized because it's a cross // product of 2 normalized vectors Vector3 vy = Vector3.Cross(vz, vx);// The "up". Matrix4x4 inverseViewMatrix = new Matrix4x4(); inverseViewMatrix.SetColumn(0, new Vector4(vx.x, vx.y, vx.z , 0));// inverseViewMatrix.SetColumn(1, new Vector4(vy.x, vy.y, vy.z , 0));// inverseViewMatrix.SetColumn(2, new Vector4(vz.x, vz.y, vz.z , 0));//用 right 當 forward. //inverseViewMatrix.SetColumn(3, new Vector4(-Vector3.Dot(vx, eye), -Vector3.Dot(vy, eye), -Vector3.Dot(vz, eye) , 1)); inverseViewMatrix.SetColumn(3, new Vector4(eye.x, eye.y, eye.z , 1)); return inverseViewMatrix.inverse; } then , I get quaternion from the matrix. Code (csharp): //由 matrix 中 取出 quaternion. static public Quaternion QuaternionFromMatrix(Matrix4x4 m) { // Adapted from: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm Quaternion q = new Quaternion(); q.w = Mathf.Sqrt( Mathf.Max( 0, 1 + m[0,0] + m[1,1] + m[2,2] ) ) / 2; q.x = Mathf.Sqrt( Mathf.Max( 0, 1 + m[0,0] - m[1,1] - m[2,2] ) ) / 2; q.y = Mathf.Sqrt( Mathf.Max( 0, 1 - m[0,0] + m[1,1] - m[2,2] ) ) / 2; q.z = Mathf.Sqrt( Mathf.Max( 0, 1 - m[0,0] - m[1,1] + m[2,2] ) ) / 2; q.x *= Mathf.Sign( q.x * ( m[2,1] - m[1,2] ) ); q.y *= Mathf.Sign( q.y * ( m[0,2] - m[2,0] ) ); q.z *= Mathf.Sign( q.z * ( m[1,0] - m[0,1] ) ); return q; } final code Code (csharp): Matrix4x4 lax = LookAtFromX(transform.position, dynamicPos, Vector3.up); transform.rotation = QuaternionFromMatrix(lax); now my girls breasts works great!!
Hi, This script looks great, but when I try to attach it to my object the boob seems to be somewhat rotated and out of alignment. I think it may be something to do with the default rotation of the bone. When I look character head-on with the bone selected in translate mode, the y seems to be pointing downwards, and the x seems to be point diagonally towards me at about (approx) 45 degrees to the right, and the pointing towards me to the left at about 45 degrees. Would this adversely affect the script? Is there any way to adjust the script to take this into account? Thanks Ray
@raeldor - yeah that will definitely effect the script. It might be possible to try and plot out the correct offset, but you will honestly have a much easier time if the model is rigged correctly to begin with.
Appreciate the response, thank you. The model is exported from Autodesk Character Creator, so I may try and tweak the script so I don't have to do a manual adjustment every time I export. Many Thanks
Have you all seen this one? Looks successful to me... I don't have any need for it in my games, but if I did, I'd certainly study this example.
So I'm looking at the code, but having a hard time getting my head around this one. It seems that my bone's 'up' is not a standard (0,1,0), so I tried putting this into awake()... originalUp = transform.up; And then in LateUpdate() I put... transform.LookAt(dynamicPos, originalUp); But this results in a boob that bounces to the side, though interestingly doesn't have the 'twistedness' it did when using upVector (which is 0,1,0 btw). Thanks Ray
@joe - Yeah that method is ok, but the problem is its kind of like a chase cam, it will lag behind but never follow through with the momentum of the breasts. I guess it depends on what you're going for aesthetic-wise. @raeldor - Its hard to diagnose what the issue could be, without seeing the scene file and the joint orientations. I've been meaning to take another crack at the script since it has been a while since I've looked at it and chances are things could be done better / differently. If I have free time I will try to take a look at it again.
When I turn on debug (rays) I think the problem seems to be that the target is being manipulated in world space co-ordinates, whereas because the original rotation where the breast is at rest (hey, I'm a poet!) is not identity it's resulting in the bounce being in the wrong direction. Is there a way I could rotate the vel+force to be oriented in the correct direction before adding to the dynamicpos? Or maybe it's not that simple, since it re-uses the value of dynamicpos next iteration? Thanks
I think I have it working. I need to do more testing, but I put this in the awake()... originalRotation = transform.rotation; And then in the lateupdate() I put... transform.LookAt (dynamicPos); transform.Rotate(originalRotation.eulerAngles, Space.Self); I'll do some more testing to see if they behave 'naturally'.
Anyone still have the original version of this script? How about a project file demonstrating it in action for us newbs to study?
I know this post is a bit old, but I stumbled across this looking for something for a DOA style fighting game. The models are saved .blend files from blender, which you may know means they are inverse and backwards compared to Unity but by taking the original script and replacing Code (CSharp): // Set bone rotation to look at dynamicPos transform.LookAt(dynamicPos, upVector); with Code (CSharp): transform.localRotation = newQuaternion (boneAxis.x, boneAxis.y, boneAxis.z, 0.0f); it did fix the issue and did not require that I go through and guess values (like i did the first half hour) or perform some nuclear physics type of matrix calculation (like I feared from an earlier post)
Hi @Fishypants Used your awesome script in our project for car antenna physics here: http://forum.unity3d.com/threads/te...ic-graphics-and-gameplay-free-to-play.392020/
@Fishypants Hey man, bravo for that wonderful contribution of brilliant code. I learned a great deal from it and plan to use it in an upcoming project. Will certainly give due credit for this. Thanks again.