0
\$\begingroup\$

I have a large asteroid object, and I want to use physics2D to have smaller objects be attracted to it as if by gravity, and come to rest on its surface. The asteroid itself is also a dynamic physics2D object to allow it to drift around, and receive transferred momentum from impacts.

My current arrangement on the asteroid object is:

  • Smaller CircleCollider2D on surface of asteroid asset for collisions
  • RigidBody2D
  • Larger CircleCollider2D for point effector
  • PointEffector2D with negative force to attract objects

Other objects are just colliders and rigidBody2D's

The problem is that when an object comes to rest on the surface of the asteroid, since it has not reached the actual point effector coordinates, a force is still applied to that object in the direction of the point effector ie center of the asteroid. This force in turn gets imparted on to the asteroid, and if several objects build up in a certain direction the asteroid will move in the opposite direction.

How can I approximate the behavior of a real asteroid whereby an object will impart some momentum on impact, but once they come to rest the forces reach equilibrium?

Obviously in real life the center of gravity would be slightly altered, I don't need that level of precision. I just don't want the asteroid zipping around.

I have tried using the collision masks / matrix. I can not find a configuration that both allows the asteroid to collide with the smaller objects, but not receive the force imparted by them after colliding.

\$\endgroup\$
5
  • \$\begingroup\$ Have you considered using a component to apply attractive forces bidirectionally, so the asteroid feels as much tug toward the object as the object feels toward the asteroid? This keeps the forces in balance by construction, and matches how Newtonian gravity works. \$\endgroup\$
    – DMGregory
    Dec 24, 2023 at 18:28
  • \$\begingroup\$ that was a great suggestion! i think it worked. thanks \$\endgroup\$ Dec 24, 2023 at 21:49
  • \$\begingroup\$ If that solved your problem, please post your script as an answer below. \$\endgroup\$
    – DMGregory
    Dec 24, 2023 at 22:27
  • \$\begingroup\$ i found issues with it. if i solve those, i will post\ \$\endgroup\$ Dec 24, 2023 at 23:38
  • \$\begingroup\$ Sounds good. You can also edit your question to show your attempt and document the issues you observed with it, so that other users can suggest ways to fix them. \$\endgroup\$
    – DMGregory
    Dec 24, 2023 at 23:40

1 Answer 1

1
\$\begingroup\$

This solution worked for me:

private Vector2 totalForce;

private void FixedUpdate()
{
    _rigidBody.AddForce(-totalForce);
    totalForce = Vector2.zero;
    
    foreach (var rb in affectedRigidbodies)
    { 
        Vector3 forceDirection = ((Vector2)transform.position - rb.position).normalized;
        float forceMagnitude = _timeNumberMgmt.hourGravForceMag * rb.mass;
        Vector2 force = forceDirection * forceMagnitude;
        rb.AddForce(force);
        totalForce += force;
    }
}

private void OnTriggerEnter2D(Collider2D other)
{
    Rigidbody2D rb = other.GetComponent<Rigidbody2D>();
    if (rb != null)
    { 
        affectedRigidbodies.Add(rb);
    }
}

void OnTriggerExit2D(Collider2D other)
{
    Rigidbody2D rb = other.GetComponent<Rigidbody2D>();
    if (rb != null)
    {
        affectedRigidbodies.Remove(rb);
    }
}

A point effector based system seemed more performant. However using RigidBody.AddForce() more closely resembles Newtonian gravity as all objects accelerate at the same speed towards the attractor irrespective of their mass, whereas a point effector has a more gradual effect on objects of greater mass.

It also allows me to accumulate the total force of the system and apply the inverse of that to the attractor, which neutralizes the net pushing force the objects are imparting on the attractor while still simulating transfer of momentum from large impacts.

It deliberately ignores the inverse square scaling of newtonian gravity as that isn't desired for my purposes, but that would be easy enough to implement.

I expect there is a more efficient way but this works for now.

\$\endgroup\$
1
  • \$\begingroup\$ If any of your objects have multiple colliders, you may want to modify your add/remove functions to ensure you don't add the same body twice: once when its first collider enters range, and once when the next collider enters. \$\endgroup\$
    – DMGregory
    Dec 25, 2023 at 14:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .