Search Unity

Resolved Solution to infinite force when gravitational objects overlap at centers?

Discussion in 'Physics' started by ssojyeti2, Dec 4, 2023.

  1. ssojyeti2

    ssojyeti2

    Joined:
    Mar 16, 2020
    Posts:
    16
    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?

    6c85c1a17b6b10847a491c8d7d8a8808.gif
     
  2. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    1,000
    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! :cool:
     
    Last edited: Dec 5, 2023
    ssojyeti2 likes this.
  3. ssojyeti2

    ssojyeti2

    Joined:
    Mar 16, 2020
    Posts:
    16
    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.
    cc757f5b3d2b7ab2653d6ab396eeceb4.gif


    I want this to follow proper physics as much as possible!
     
  4. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,437
    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.)
     
    ssojyeti2 and zulo3d like this.
  5. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    1,000
    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.
     
    Last edited: Dec 5, 2023
    ssojyeti2 likes this.
  6. ssojyeti2

    ssojyeti2

    Joined:
    Mar 16, 2020
    Posts:
    16
    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.

    de8649358e1dd555534f45a34e873877.gif

    For anyone interested in my code:
    Code (CSharp):
    1. if (isMovingTowards && forceMagnitude >= maxTowardsForce)
    2.         {
    3.             forceMagnitude = maxTowardsForce * gravityForceDamper;
    4.         }
    5.         else if (!isMovingTowards && forceMagnitude >= maxAwayFromForce)
    6.         {
    7.             forceMagnitude = maxAwayFromForce;
    8.         }
    9.  
    10.         Vector3 forceDirection = direction.normalized;
    11.         Vector3 forceVector = forceDirection*forceMagnitude;
    12.  
    13.         // Only add gravity until a certain distance
    14.         if (distance > stopGravityDistance)
    15.         {
    16.             target.rb.AddForce(forceVector);
    17.         }
    18.  
    19.         float midpointDistance = distance / 2f;
    20.  
    21.         // Stop object at a certain disance and speed
    22.         if (midpointDistance < stopMovingDistance && target.rb.velocity.magnitude < stopVelocity)
    23.         {
    24.             target.rb.velocity = Vector3.zero;
    25.         }
     
    halley likes this.
  7. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    1,000
    If you don't want the elasticity that comes with an opposing force then you could just increase drag as the objects overlap.

    Code (CSharp):
    1.    void FixedUpdate()
    2.    {
    3.       Vector3 v=target.position-rb.position;
    4.       float d=v.magnitude;
    5.       rb.AddForce(v.normalized*Mathf.Clamp01(1/(d*d))*10);
    6.       rb.drag=Mathf.Clamp01(1-d)*20;   // increase drag the more we overlap
    7.    }
     
    ssojyeti2 likes this.