Utilising Unity's collision without relying on its rigidbody (3D)

Hi everyone.

I’m trying to work out how best to develop a prototype that has quite elaborate physics,. It involves a solar system of planets orbiting with N-body physics (so all planets are attracted to each other), while the player can walk around on one of the planets. The planets are cartoonishly small, but still ‘big’ enough to walk around on.

I started by creating a script called StellarBody.cs, which handled the N-Body simulation of all planets, and was attached as a component. Then I wanted to get physics working for small objects, including the player, resting on the planets. So I’ve tried making a generalised Body.cs script, and two derived classes; StellarBody.cs and ObjectBody.cs. It’s not the subject of my question, but here’s the code for Body.cs:

using UnityEngine;
using System.Collections;

public class Body : MonoBehaviour
{
    // The body's mass.
    public float mass;
    // The gravitational constant, or the overall strength of the force of Gravity.
    public static float gravConstant = 0.1f;
    // An array to store all planets/stars/asteroids in the scene.
    static StellarBody[] stellarBodies;
    // This object's velocity. Exposed for editing the initial velocity.
    public Vector3 vel = new Vector3(0.0f, 0.0f, 0.0f);

    protected virtual void Start()
    {
        // Find all stellar bodies in the scene. Note that only objects with StellarBody components will be considered for gravity.
        stellarBodies = FindObjectsOfType<StellarBody>();
    }

    protected virtual void FixedUpdate()
    {
        // For all stellar bodies aside from this one, change velocity with respect to gravity.
        foreach (StellarBody sb in stellarBodies)
        {
            if (sb != this)
            {
                Gravitate(sb);
            }
        }

        // Translate by velocity, also considering update rate.
        transform.Translate(vel / 60);
    }

    void Gravitate(StellarBody _sb)
    {
        // A one-sided gravity equation: acceleration = (mass / distance squared) x grav constant, in the direction of the attracting body.
        Vector3 acc = ((_sb.mass / Mathf.Pow((transform.position - _sb.transform.position).magnitude, 2)) * gravConstant) * (_sb.transform.position - transform.position).normalized;

        // Apply acceleration to velocity.
        vel += acc;
    }
}

My derived classes are there to override things like Start() and FixedUpdate().

As you can see, I’m sort of trying to work around the already existing Rigidbody functionality. I started by just discarding Rigidbody gravity, but keeping the component to handle collision. However, I’ve come to the point where I want a very specific type of collision, and therefore I want to discard the Rigidbody altogether.

To be specific:

  • I want small objects (ObjectBody.cs) to collide with planets (StellarBody.cs), and appropriately apply force to the small object. For example, I want a cube to bounce around on the surface of a planet, and eventually come to rest on it.
  • BUT I don’t want my small object to apply force to the planet itself. There’s no need for it. I don’t want my planets to have their trajectories updated by the small objects on their surface.
  • So, I want planets to collide with planets, and objects to collide with planets. But when an object collides with a planet, I only want to account for the impact on the object itself.

Unity doesn’t seem to have any pre-build features to get what I want, so I figured I could just code the collision impacts myself. The math seems a little complicated with all the rotational velocity, but not too beyond me.

void OnCollisionEnter(Collision collision)
    {
        // (If colliding with a planet)
        Debug.Log("Collided with Planet.");
     

        // Apply force away from the collision (temporary, until I understand the proper equation).
        vel += collision.contacts[0].normal * 10;
    }

So I used the OnCollisionEnter message to call my objects’ collision response, and also removed the Rigidbody component from both objects and planets. However, it seems that removing the Rigidbody eliminates any chance of registering collisions. This suggests that, to get this working, I’d need to start handling collisions myself as well, which I know is a very complex process. It seems unecessary when perfectly good collision detection is happening, but I can’t use it because the Rigidbody assumes how I want to respond.

Is there a way to utilise collisions without relying on a Rigidbody and all its presumptions?

I think if you have a non kinematic rigidbody, but in the inspector freeze its rotation and position, you would get all the oncollision calls, but since rotation and position is frozen, it wont move on its own.