Forked from FreyaHolmer/RigidbodyMassCalculator.cs
Created
December 22, 2015 20:09
-
-
Save mandarinx/a2c9611c6b370d915273 to your computer and use it in GitHub Desktop.
Used to approximate a proper mass value for all the colliders in a given Rigidbody
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Linq; | |
[RequireComponent(typeof(Rigidbody))] | |
public class RigidbodyMassCalculator : MonoBehaviour { | |
public float density = 1f; | |
public bool recalculateOnAwake = true; | |
Rigidbody rb; | |
void Awake () { | |
rb = GetComponent<Rigidbody>(); | |
if( recalculateOnAwake ) | |
RecalculateMass(); | |
} | |
public void RecalculateMass() { | |
Collider[] cols = GetComponentsInChildren<Collider>(); | |
float volume = cols.Sum( x => GetVolume( x, transform.localScale ) ); | |
rb.mass = volume * density; | |
} | |
static float GetVolume( Collider c, Vector3 scale ) { | |
if( c is BoxCollider ) | |
return BoxVolume( Vector3.Scale(( c as BoxCollider ).size, scale) ); | |
if( c is MeshCollider ) // Approximate. Might want to use actual convex polytype volume | |
return BoxVolume( Vector3.Scale( c.bounds.extents * 2, scale ) ); | |
float uniScale = scale.x * scale.y * scale.z; | |
if( c is SphereCollider ) | |
return SphereVolume( ( c as SphereCollider ).radius * uniScale ); | |
if( c is CapsuleCollider ) { | |
CapsuleCollider cc = c as CapsuleCollider; | |
return CapsuleVolume( cc.height * scale[cc.direction], cc.radius * uniScale ); | |
} | |
if( c is CharacterController ) { | |
CharacterController chc = c as CharacterController; | |
return CapsuleVolume( chc.height * scale.y, chc.radius * uniScale ); | |
} | |
Debug.Log( "Invalid attempt to get volume of " + c.GetType().Name, c.gameObject ); | |
return 0f; | |
} | |
static float BoxVolume( Vector3 size ) { | |
return size.x * size.y * size.z; | |
} | |
static float SphereVolume( float r ) { | |
return r * r * r * Mathf.PI * ( 4f / 3f ); | |
} | |
static float CylinderVolume( float h, float r ) { | |
return h * r * r * Mathf.PI; | |
} | |
static float CapsuleVolume( float h, float r ) { | |
float cylHeight = h - 2 * r; | |
float sphereVol = SphereVolume( r ); | |
// If radius is twice as large or bigger than h - it degenerates into a sphere | |
if( cylHeight <= 0 ) | |
return sphereVol; | |
float cylVol = CylinderVolume( cylHeight, r ); | |
return sphereVol + cylVol; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment