Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

FInding the center of mass of a collection of rigidbodies

Discussion in 'Scripting' started by HarvesteR, Apr 30, 2011.

  1. HarvesteR

    HarvesteR

    Joined:
    May 22, 2009
    Posts:
    530
    Hello once more!

    I'm wondering about what would be the correct procedure for findind the center of mass of a group of rigidbodies...

    These rigidbodies are linked to one another, so they form a larger structure... Now, I need to find the overall center of mass of the entire assembly...

    I'm thinking a weighted average of all the rigidbodies in the assembly would do the trick, but is that reliable?
    Also, the amount of rigidbodies in the assembly is not predetermined, so it'll probably require an iterative solution...

    So, I thought up this code here:

    Code (csharp):
    1.  
    2.  
    3. Vector3 CoM = Vector3.zero;
    4. int count = 0;
    5. foreach (GameObject part in assembly)
    6. {
    7.     CoM += part.rigidbody.centerOfMass * part.rigidbody.mass;
    8.     count ++;
    9. }
    10.  
    11. CoM /= count;
    12.  
    13.  
    Am I on the right track with this? I'm really not too confident with my math, so I wanted some confirmation ;)

    Later on I'm also gonna need to find the center of thrust for the assembly (it's a ship)... So I'm thinking this same solution could be applied there, too... only instead of weighing the thrust vectors by mass, I'd weigh 'em by thrust rating (which is a standard unit, so hopefully it should apply)

    Hmm, actually, the thrust vector are probably be a little more complicated... since they're not only a position, but they also have a direction... I guess I can just average those direction out too, right?

    Thanks in advance for any help

    Cheers
     
    Last edited: Apr 30, 2011
    krishnanpc likes this.
  2. HarvesteR

    HarvesteR

    Joined:
    May 22, 2009
    Posts:
    530
    Well, Wikipedia saves the day again:

    Didn't think there would be such a straightforward explanation there... usually formulas on Wikipedia are way more than what is needed for the simplified physics of a phys sim.

    Cheers
     
    Dave_LeDev likes this.
  3. HarvesteR

    HarvesteR

    Joined:
    May 22, 2009
    Posts:
    530
    As it turned out, my math was indeed wrong :p

    The code above will yield bad results, since it doesn't divide by the correct value in the end.
    The correct algorithm would be:

    Code (csharp):
    1.  
    2. Vector3 CoM = Vector3.zero;
    3. float c = 0f;
    4.  
    5. foreach (GameObject part in assembly)
    6. {
    7.     CoM += part.rigidbody.worldCenterOfMass * part.rigidbody.mass;
    8.     c += part.rigidbody.mass;
    9. }
    10.  
    11. CoM /= c;
    12.  
    13.  
    this 'c' variable must be the sum of all weights, not the number of elements.

    Now it does work!!

    Cheers
     
    Last edited: May 2, 2011
    Noah-Essa24, Nothke, NotaNaN and 3 others like this.
  4. CreativeMatter

    CreativeMatter

    Joined:
    Dec 13, 2013
    Posts:
    2
    Awesome stuff, you solved something that has been a mystery to me for many months. Thanks HarvesteR. I'm sure many people came here to steal your code in silence :)
     
  5. neonleif

    neonleif

    Joined:
    Feb 25, 2009
    Posts:
    29
    Nice. I've used it for controlling a top-down camera that has to follow several units.

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class FollowUnitsCentreOfMass : MonoBehaviour
    5. {
    6.     Vector3 centreOfMass = Vector3.zero;
    7.     GameObject[] units;
    8.     public Vector3 offset = Vector3.zero;
    9.  
    10.  
    11.     void Update ()
    12.     {
    13.         centreOfMass = Vector3.zero;
    14.         float sumOfWeights = 0f;
    15.    
    16.         units = GameObject.FindGameObjectsWithTag("Player");
    17.  
    18.         if (units.Length <= 0)
    19.         {
    20.             /
    21.             if (GameObject.FindGameObjectWithTag("VIP"))
    22.             {
    23.                 centreOfMass = GameObject.FindGameObjectWithTag("VIP").transform.position;
    24.                 transform.position = Vector3.Lerp(transform.position, new Vector3 (centreOfMass.x, transform.position.y, centreOfMass.z) - offset, Time.deltaTime);
    25.             }
    26.             return;
    27.         }
    28.  
    29.         foreach (GameObject part in units)
    30.         {
    31.             centreOfMass += part.rigidbody.worldCenterOfMass * part.rigidbody.mass;
    32.             sumOfWeights += part.rigidbody.mass;
    33.         }
    34.  
    35.         centreOfMass /= sumOfWeights;
    36.  
    37.         transform.position = Vector3.Lerp(transform.position, new Vector3 (centreOfMass.x, transform.position.y, centreOfMass.z) - offset, Time.deltaTime);
    38.         Debug.Log(centreOfMass);
    39.     }
    40.  
    41.     void OnDrawGizmos ()
    42.     {
    43.         Gizmos.color = Color.cyan;
    44.         Gizmos.DrawSphere(centreOfMass, 1f);
    45.     }
    46. }
     
  6. msl_manni

    msl_manni

    Joined:
    Jul 5, 2011
    Posts:
    272
    Nicolaj Schweitz - How to restrict movement of units not to leave a camera view space. I want to restrict player movement if they leave the camera sphere. Its for 4 player game.
     
  7. darkAbacus247

    darkAbacus247

    Joined:
    Sep 7, 2010
    Posts:
    251
    UGG...I guess I found the "Complicated" Wiki link...
    Thanks a bunch man, this saved me...I dunno, days of trial and error.
     
  8. TheGameLearner

    TheGameLearner

    Joined:
    Feb 10, 2018
    Posts:
    20
    Thanks, I was replacing a Car with a bike for a game as I don't have a proper Bike controller asset.
    Changing the shape of my car to fit the Bike's view made it fall at Turns. Now I know that its centre of mass was too high to stay safe at turns as the car had little bend angle during turns. I can think of a proper solution to this problem now.

    Also am new to Unity so detailed explanation and simple codes are greatly appreciated. :D
     
  9. krishnanpc

    krishnanpc

    Joined:
    Oct 30, 2017
    Posts:
    19
    I did ;)
     
    NotaNaN and hippocoder like this.
  10. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    But you weren't silent :p
     
    NotaNaN, krishnanpc and SparrowGS like this.
  11. florinel2102

    florinel2102

    Joined:
    May 21, 2019
    Posts:
    76
  12. gabriel-diquinzio

    gabriel-diquinzio

    Joined:
    Nov 3, 2015
    Posts:
    3
    I Made it into a Static class.
    Just add the dependency and there you go :)

    using Utils.Physics;


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace Utils.Physics.Rigidbodies
    6. {
    7.     public static class CenterOfMass
    8.     {
    9.         public static Vector3 Get(Rigidbody[] bodies)
    10.         {
    11.             Vector3 centerOfMass = Vector3.zero;
    12.             float totalMass = 0f;
    13.  
    14.             foreach (Rigidbody body in bodies)
    15.             {
    16.                 centerOfMass += body.worldCenterOfMass * body.mass;
    17.                 totalMass += body.mass;
    18.             }
    19.             return centerOfMass / totalMass;
    20.         }
    21.  
    22.         public static Vector3 Get(Rigidbody2D[] bodies)
    23.         {
    24.             Vector2 centerOfMass = Vector2.zero;
    25.             float totalMass = 0f;
    26.  
    27.             foreach (Rigidbody2D body in bodies)
    28.             {
    29.                 centerOfMass += body.worldCenterOfMass * body.mass;
    30.                 totalMass += body.mass;
    31.             }
    32.             return centerOfMass / totalMass;
    33.         }
    34.     }
    35. }
     

    Attached Files:

    Last edited: Apr 10, 2022
    emilyst and florinel2102 like this.