- Home /
Can I control mass density of colliders in a rigidbody independent of their size?
I am building a 3D rigidbody physics simulation with modular attachable components. I have a single rigidbody on a parent object, and as I attach or remove modules I add to or subtract from the parent rigidbody mass. I also have a collider associated with each component, and I would like to use the rigidbody physics to automatically calculate the inertia tensor and center of mass of the full system of colliders.
The Unity rigidbody component seems to assume uniform mass density among children colliders. Is there a way for me to adjust that assumption that is not based on collider size? I would like to be able to assign a small, attachable module a large mass without making its collider larger than its physical size.
If I can't adjust collider density, I will have to manually calculate the mass properties of my system of objects. I have started coding this already, and while center of mass is easy to find, I am struggling to calculated the inertia tensor of asymmetric bodies.
Answer by Captain_Pineapple · Feb 27, 2018 at 10:08 PM
This piece of code should do the trick: Warning: This is only accurate for cube Sized Modules as children. If you want to use other things use a different approach for inertia of simple geometry forms. ->wikipedia or something. (for cubes its mass*sidelength/6)
private void recalculateMassAndInertia()
{
Vector3 newCenterOfMass = Vector3.zero;
Vector3 newInertiaVector = Vector3.zero;
Vector3 distance = Vector3.zero;
YourModuleScript m;
float sumOfMass = 0;
foreach (Transform t in allConnectedModules) {
if (t.gameObject.GetActive ()) {
m = t.GetComponent<YourModuleScript> ();
newCenterOfMass += (t.localPosition * m.mass);
sumOfMass += m.mass;
}
}
newCenterOfMass = newCenterOfMass /sumOfMass;
Debug.Log (newCenterOfMass);
foreach (Transform t in allConnectedModules) {
if (t.gameObject.GetActive ()) {
m = t.GetComponent<YourModuleScript> ();
distance = new Vector3 (Mathf.Pow (t.localPosition.y - newCenterOfMass.y, 2.0f) + Mathf.Pow (t.localPosition.z - newCenterOfMass.z, 2.0f), Mathf.Pow (t.localPosition.x - newCenterOfMass.x, 2.0f) + Mathf.Pow (t.localPosition.z - newCenterOfMass.z, 2.0f), Mathf.Pow (t.localPosition.x - newCenterOfMass.x, 2.0f) + Mathf.Pow (t.localPosition.y - newCenterOfMass.y, 2.0f));
newInertiaVector += ((Vector3.one * m.mass *m.sidelength/ 6.0f) + m.mass* distance);
// if your parent object is in the list: detect it and use this line for this module:
//newInertiaVector += (Vector3.one * m.mass *m.sidelength/ 6.0f);
}
}
GetComponent<Rigidbody> ().centerOfMass = newCenterOfMass;
GetComponent<Rigidbody> ().inertiaTensor = newInertiaVector;
GetComponent<Rigidbody> ().mass = sumOfMass;
Debug.Log (sumOfMass);
}
You have to add your own script to keep track of the modules mass. This should go wherever you find "yourModuleScript" and it should have a public float property named "mass". Also this script assumes that you have all your modules set in a List "allConnectedModules".
Note: im not sure in wich order to set the mass/inertia/center of mass to prevent unity from automatically recalculating on its own. Please let me know if you have any idea about this.
Thanks for the suggestion. The inertia tensor is the part I have had the most trouble with. Do you know if your code works for children that have been rotated?
If I understand it correctly, the inertia tensor that Unity stores is the moments of inertia around the principal axes of rotation. The rotation vector rotates from object local frame to the frame aligned with those principal axes. I know how to calculate these things with straight matrix math, but it involves solving for eigenvalues and stuff, and I haven't done much straight matrix math inside Unity, so I know I'd have to learn a bit to make my functions.
It would be super helpful, since Unity is already doing all of this under the hood, if they would add the option to set density of individual colliders in a system underneath a single rigidbody. That would allow their rigidbody system, while it's calculating all of this stuff, to assign proper mass to each collider ins$$anonymous$$d of dividing it up proportionally.
yeah i'm totally with you. A mass setting for 3-D Colliders Would be dope.. But i guess they have kind of a similar problem as you. As far as my Script is concerned: It assumes that your blocks are somewhat aligned to each other. So rotations of +-k*90° is fine but anything else will not be precise. The transformation of the main axis to a different system is indeed a difficult matter... Question is: Do you actually need this precision? And what kind of Colliders are you using? Is it acceptable to just approximate the bodys you are using? Especially since i guess that the extra precision you gain will be lost due to the massive calculationtime and unitys sometimes not so precise physics-calculations.
Your answer
Follow this Question
Related Questions
Rigidbodies won't collide if mass difference is too high 0 Answers
How to give dynamically add mass to a gameobject from volume(collider.bounds.size) and density 1 Answer
Rigidbody mass not updating in inspector after calling SetDensity 2 Answers
Players slips on slopes for no reason. 0 Answers
make 2 object not collide? 2 Answers