Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save mandarinx/a2c9611c6b370d915273 to your computer and use it in GitHub Desktop.

Select an option

Save mandarinx/a2c9611c6b370d915273 to your computer and use it in GitHub Desktop.

Revisions

  1. @FreyaHolmer FreyaHolmer created this gist Dec 18, 2015.
    72 changes: 72 additions & 0 deletions RigidbodyMassCalculator.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,72 @@
    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;
    }

    }