Planet Rider --- Gravity implementation


In this devlog I will explain how I implemented the gravity for my game.

I made a script based on something I found on this forum. It uses 

foreach (Collider collider in Physics.OverlapSphere(transform.position, pullRadius))

I had to adapt this line to 

foreach (Collider2D collider in Physics2D.OverlapCircleAll(transform.position, pullRadius))

because my game is in 2D and not in 3D.


First of all, I disabled normal gravity for my player by setting gravity scale in the rigidbody to 0.


This script is used for the planets, the black holes and the start platform. This is why I added an ObjectShape class, to use it with rectangles and circles.

I use a layermask to be sure not to try to attract planets or black holes but only the player (and meteorits but finally I didn't add them).

Then, in the FixedUpdate I check if my object is a circle or a rectangle.  If it's a circle, I calculate the direction vector and the distance between the player and the the centre of the planet (or black hole) to know in which direction I will have to add a force and how strong. I also add a force for the rotation, otherwise the player will be attracted to the centre of the planet but won't rotate with it.

After that, the OnTriggerEnter2D is only used with blackholes (that is why I make the collider trigger in the Start if it is a blackhole). It detects if the player enters in it and calls a function in my GameManager that will restart the level.

The OnDrawGizmos function is very useful to visualize the zones in which the planets will attract things.

I made GetRotationForce to know how the rotation force should be.


using UnityEngine;
[System.Serializable] public enum ObjectShape
{
    Square,
    Circle,
}
public class ObjectPuller : MonoBehaviour
{
    public float pullRadius = 2;
    public float pullForce = 1;
    public bool blackHole = false;
    [Space]
    public ObjectShape shape;
    [Tooltip("This will only be used with the square !")] public Vector2 squareSize;
    
    LayerMask layerMask;
    RigidBody2D rb;
    private void Start()
    {
        layerMask = ~LayerMask.GetMask("Planets");
        rb = GetComponent<RigidBody2D>();
        if (GetComponent<Collider2D>() && blackHole)
        {
            GetComponent<Collider2D>().isTrigger = true;
        }
    }
    public void FixedUpdate()
    {
        if (shape == ObjectShape.Circle)
        {
            foreach (Collider2D collider in Physics2D.OverlapCircleAll(transform.position, pullRadius, layerMask))
            {
                if (collider.attachedRigidbody)
                { // calculate direction from other object to this object
                    Vector3 forceDirection = transform.position - collider.transform.position;
                    float distance = forceDirection.magnitude;
                    // apply force on other object towards this object
                    collider.attachedRigidbody.AddForce(forceDirection.normalized * pullForce * pullRadius / distance * Time.fixedDeltaTime);
                    // apply force on other object regarding to the rotation
                    collider.attachedRigidbody.AddForce(GetRotationForce(forceDirection.normalized) * (pullForce / 3) * (pullRadius / distance) * Time.fixedDeltaTime);
                }
            }
        }
        else if (shape == ObjectShape.Square)
        {
            foreach (Collider2D collider in Physics2D.OverlapBoxAll(transform.position, squareSize, 0, layerMask))
            {
                if (collider.attachedRigidbody)
                { // calculate direction from other object to this object
                    Vector3 forceDirection = transform.position - collider.transform.position;
                    float distance = forceDirection.magnitude;
                    Bounds bounds = new Bounds(transform.position, squareSize);
                    float multiplier = Vector2.Distance(transform.position, bounds.ClosestPoint(collider.transform.position)) / distance;
                    // apply force on other object towards this object
                    collider.attachedRigidbody.AddForce(forceDirection.normalized * pullForce * multiplier * Time.fixedDeltaTime);
                }
            }
        }
    }
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (!blackHole)
            return;
        if (collision.CompareTag("Player"))
        {
            GameManager.instance.EndGame(false);
        }
        else
            Destroy(collision.gameObject);
    }
    private void OnDrawGizmos()
    {
        if (shape == ObjectShape.Circle)
            Gizmos.DrawWireSphere(transform.position, pullRadius);
        else if (shape == ObjectShape.Square)
            Gizmos.DrawWireCube(transform.position, squareSize);
    }
    Vector3 GetRotationForce(Vector3 currentForce)
    {
        int sign = 1;
        if (rb.rotation < 0)
            sign = -1;
        return Quaternion.Euler(0, 0, 45 * sign) * currentForce * Mathf.Abs(rb.rotation);
    }
}

Files

WebBuild.zip Play in browser
Mar 20, 2022
WindowsBuild.zip 30 MB
Mar 20, 2022
MacBuild.app.zip 39 MB
Mar 20, 2022

Get Planet rider

Download NowName your own price

Comments

Log in with itch.io to leave a comment.

Hello. One question....how do you control the camera? Did you use any asset? Which one? thanks

(1 edit)

No I didn't use any asset. I made this simple script. 

using UnityEngine;
public class CameraFollow : MonoBehaviour
{
    public GameObject player;
    GameObject startTarget;
    public float timeOffset, gameViewSize, zoomSpeed = 1, timeBeforeMoving = 1.5f;
    public Vector3 posOffset = new Vector3(0, 0, -10f);
    Camera cam;
    private Vector3 velocity;
    private void Start()
    {
        cam = GetComponent<Camera>();
        
        if (!startTarget)
            startTarget = GameObject.FindGameObjectWithTag("Finish");
        
        transform.position = startTarget.transform.position + new Vector3(0, 0, posOffset.z);
    }
    void Update()
    {
        if (cam.orthographicSize != gameViewSize)
            cam.orthographicSize = Mathf.Lerp(cam.orthographicSize, gameViewSize, Time.deltaTime * zoomSpeed);
        if (Time.timeSinceLevelLoad > timeBeforeMoving)
            transform.position = Vector3.SmoothDamp(transform.position, player.transform.position + posOffset, ref velocity, timeOffset);
    }
}

Wow!!! and the blur effect on the sides?? Fantastic to know...thanks

That is lens distorsion in post processing with URP.