FInding the center of mass of a collection of rigidbodies

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:

Vector3 CoM = Vector3.zero;
int count = 0;
foreach (GameObject part in assembly)
{
    CoM += part.rigidbody.centerOfMass * part.rigidbody.mass;
    count ++;
}

CoM /= count;

Am I on the right track with this? I’m really not too confident with my math, so I wanted some confirmation :wink:

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

2 Likes

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

2 Likes

As it turned out, my math was indeed wrong :stuck_out_tongue:

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

Vector3 CoM = Vector3.zero;
float c = 0f;

foreach (GameObject part in assembly)
{
    CoM += part.rigidbody.worldCenterOfMass * part.rigidbody.mass;
    c += part.rigidbody.mass;
}

CoM /= c;

this ‘c’ variable must be the sum of all weights, not the number of elements.

Now it does work!!

Cheers

7 Likes

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 :slight_smile:

2 Likes

Nice. I’ve used it for controlling a top-down camera that has to follow several units.

https://vimeo.com/92880483

using UnityEngine;
using System.Collections;

public class FollowUnitsCentreOfMass : MonoBehaviour
{
	Vector3 centreOfMass = Vector3.zero;
	GameObject[] units;
	public Vector3 offset = Vector3.zero;


	void Update ()
	{
		centreOfMass = Vector3.zero;
		float sumOfWeights = 0f;
	
		units = GameObject.FindGameObjectsWithTag("Player");

		if (units.Length <= 0)
		{
			/
			if (GameObject.FindGameObjectWithTag("VIP"))
			{
				centreOfMass = GameObject.FindGameObjectWithTag("VIP").transform.position;
				transform.position = Vector3.Lerp(transform.position, new Vector3 (centreOfMass.x, transform.position.y, centreOfMass.z) - offset, Time.deltaTime);
			}
			return;
		}

		foreach (GameObject part in units)
		{
			centreOfMass += part.rigidbody.worldCenterOfMass * part.rigidbody.mass;
			sumOfWeights += part.rigidbody.mass;
		}

		centreOfMass /= sumOfWeights;

		transform.position = Vector3.Lerp(transform.position, new Vector3 (centreOfMass.x, transform.position.y, centreOfMass.z) - offset, Time.deltaTime);
		Debug.Log(centreOfMass);
	}

	void OnDrawGizmos ()
	{
		Gizmos.color = Color.cyan;
		Gizmos.DrawSphere(centreOfMass, 1f);
	}
}

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.

UGG…I guess I found the “Complicated” Wiki link…
Thanks a bunch man, this saved me…I dunno, days of trial and error.

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. :smile:

I did :wink:

2 Likes

But you weren’t silent :stuck_out_tongue:

3 Likes

Thanks ! :slight_smile:

I Made it into a Static class.
Just add the dependency and there you go :slight_smile:

using Utils.Physics;

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Utils.Physics.Rigidbodies
{
    public static class CenterOfMass
    {
        public static Vector3 Get(Rigidbody[] bodies)
        {
            Vector3 centerOfMass = Vector3.zero;
            float totalMass = 0f;

            foreach (Rigidbody body in bodies)
            {
                centerOfMass += body.worldCenterOfMass * body.mass;
                totalMass += body.mass;
            }
            return centerOfMass / totalMass;
        }

        public static Vector3 Get(Rigidbody2D[] bodies)
        {
            Vector2 centerOfMass = Vector2.zero;
            float totalMass = 0f;

            foreach (Rigidbody2D body in bodies)
            {
                centerOfMass += body.worldCenterOfMass * body.mass;
                totalMass += body.mass;
            }
            return centerOfMass / totalMass;
        }
    }
}

8035817–1036187–CenterOfMass.cs (978 Bytes)

2 Likes