Solution to infinite force when gravitational objects overlap at centers?

I’m trying to create a object merging simulation. I started with two spheres and a basic physics setup using the gravitational formula F = G * ((m1*m2)/r^2). My problem is that when the objects get closer and closer, the force pulling/pushing each becomes exponentially large due to the nature of the formula, since the distance between them (r) is decreasing.

I’d like the objects to stick together, perfectly overlapping at a center point. What is the proper way to do this in a realistic looking way?

9511126--1340389--6c85c1a17b6b10847a491c8d7d8a8808.gif

When the objects start to penetrate then you can add an opposing force. And when they’re very close together then you can delete one because realistically there’s no longer two objects. Oh, and you should make them grow in size the more they penetrate. It’ll look cool! :sunglasses:

1 Like

Appreciate the suggestion! I’ll definitely be applying code to grow the spheres as they overlap. As far as deleting one of the objects goes, I actually don’t want to delete anything, because I need the objects to be able to unmerge again. I like the idea of using an opposing force to get them to slow down–I’m curious if you know an equation that would help me derive the proper counterforce to be added?

What I came up with so far before reading your reply is to use a minimum distance threshold for the gravitational equation, below which no force gets applied to the objects. Without much parameter tweaking, it looks like this. I like the spring motion, but ideally the force should tend toward zero.
9511363--1340437--cc757f5b3d2b7ab2653d6ab396eeceb4.gif

I want this to follow proper physics as much as possible!

He didn’t say a threshold. He said an opposing force.

Your descent toward the core of the planet is blocked by the ground. Gravity wasn’t stopped. It’s just opposed by an equal but opposite force called the Normal force (in the direction of the normal of the surface). *

If you used the Unity Physics engine to do this, each would have a collider. Each would attempt to penetrate the other. Each would calculate the overlap distance and apply an opposing impulse to dis-entangle the objects so they didn’t overlap anymore.

If you’re going for a totally elastic collision (things sticking together), you need to decide when they’re stuck, and modify it to be a single object. One approach is to set the parent of object A to object B, and then set the center of mass of object B to the centroid of both. If using Rigidbody, you would want to destroy the Rigidbody of the child object once they’ve joined.

  • (Pedants will indicate that the Normal force is just a bookeeping fiction, but then again, some physicists will say the same thing about Gravity.)
2 Likes

Good point, Halley. Given enough constant force the physics engine will annoyingly allow two objects to penetrate each other and then try to pull them apart as opposed to just resetting their positions.

Gitlinjoss,

I’m not a maths or physics guy and so I don’t know of a “proper formula” for doing this. I’m a games programmer and so I wouldn’t attempt to come up with some all encompassing formula for it because I lean more towards the more simple and optimal methods. So if the distance of the objects are within penetrating distance then I would add in an opposing force.

1 Like

Hey guys, thanks for the advice! I’ve been able to come up with a merge solution that uses a counter force, as suggested. The key to get this working was checking whether the objects were moving towards or away from each other.

9517420--1342018--de8649358e1dd555534f45a34e873877.gif

For anyone interested in my code:

if (isMovingTowards && forceMagnitude >= maxTowardsForce)
        {
            forceMagnitude = maxTowardsForce * gravityForceDamper;
        }
        else if (!isMovingTowards && forceMagnitude >= maxAwayFromForce)
        {
            forceMagnitude = maxAwayFromForce;
        }

        Vector3 forceDirection = direction.normalized;
        Vector3 forceVector = forceDirection*forceMagnitude;

        // Only add gravity until a certain distance
        if (distance > stopGravityDistance)
        {
            target.rb.AddForce(forceVector);
        }

        float midpointDistance = distance / 2f;

        // Stop object at a certain disance and speed
        if (midpointDistance < stopMovingDistance && target.rb.velocity.magnitude < stopVelocity)
        {
            target.rb.velocity = Vector3.zero;
        }
1 Like

If you don’t want the elasticity that comes with an opposing force then you could just increase drag as the objects overlap.

   void FixedUpdate()
   {
      Vector3 v=target.position-rb.position;
      float d=v.magnitude;
      rb.AddForce(v.normalized*Mathf.Clamp01(1/(d*d))*10); 
      rb.drag=Mathf.Clamp01(1-d)*20;   // increase drag the more we overlap
   }
1 Like