2D Orbiting Black Hole

I am trying to create a 2D gravity attractor that orbits objects towards its center as shown in the following image:

Here is the code that I have so far to try and accomplish this. (Its attached to objects I want to “orbit” a chosen object. It only begins to orbit once it enters a trigger collider of the source of the gravity)

[Header ("Faux Grav Props")]
    public float gravityForce = 50;

    private Transform blackHoleCenter;
    private Rigidbody2D rigidbody;
    private bool fauxGravityEnabled = false;

    // Use this for initialization
    void Start () {
        blackHoleCenter = GameObject.FindGameObjectWithTag("Oven").transform;
        rigidbody = this.GetComponent<Rigidbody2D>();
    }

    void FixedUpdate(){
        if (fauxGravityEnabled){
            TransformLookat2D();
            rigidbody.AddForce(transform.forward*gravityForce);
            rigidbody.AddForce(transform.right*gravityForce);
        }
    }

    void OnTriggerEnter2D(Collider2D coll){
        if (coll.gameObject.tag == "Oven"){
            rigidbody.velocity = Vector2.zero;
            fauxGravityEnabled = true;
        }
    }

    void OnTriggerExit2D(Collider2D coll){
        if (coll.gameObject.tag == "Oven"){
            fauxGravityEnabled = false;
        }
    }

    void TransformLookat2D(){
        Vector3 dir = blackHoleCenter.position - transform.position;
        float angle = Mathf.Atan2(dir.y,dir.x) * Mathf.Rad2Deg;
        transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
    }

This code however acts more like the following image, springing the object back and forth but not actually orbiting towards the center:

Any thoughts or ideas on how to do this correctly would be appreciated!

that’s because you made the object approach the chosen object very directly as if it will hit it head to head…
what i suggest is to make it approach it from side …far away from center of gravity…

Yea, ideally I would like to find a way to achieve that affect no matter what angle the object comes at, I guess thats where the real problem is…

Then using physics might not be the best way. It looks like you want more of a whirlpool effect rather than an orbit effect. An orbit doesn’t behave as you describe. The approach vector absolutely matters for an orbit. An object doesn’t enter an orbit if it is already headed directly at a planet. If you sail directly toward a whirlpool, however, you get swept up in the current and move in the sort of path you describe. Creating a whirlpool force with physics sounds pretty tricky. Doing it with tweening should be pretty simple though.

One approach is to parent the object to an empty gameobject that is positioned at the center. Animate that central gameobject to simply rotate. I often use LeanTween for this sort of thing. Here is the code you might use for continuous 360 rotation…
rotateTween = LeanTween.rotateAround(rotator, Vector3.back, 360, 4f).setRepeat(-1).setLoopClamp();

Now when you first parent the object to this rotating empty game object, if you make sure that the x or y axis of the object is pointing at the center of the “planet”, all you have to do is make a second tween that moves the object along that local axis.

There is one tricky part to this approach. The rotation is based on the time per rotation… the code above would make one full rotation in 4 seconds. So a larger orbit will make the object move faster. You probably want the opposite effect. That might be doable with a predetermined number of rotations. Maybe something like this…

rotateTween = LeanTween.rotateAround(rotator, Vector3.back, 1080, 4f)

…And set the easing to one of the ease in variants.

@sleekdigital
Thanks for your thoughts, you are right, I should have described what I want as more of a whirlpool effect. I am starting to lean towards a non physics based approach as well. I think I’ll attempt what you have suggested and disable the rigidbody of the object once its supposed to “whirlpool” and try using tweening. Will let you know how it goes.

Hi,

Gravitational acceleration depends on the (squared) distance from the black hole.
In a very basic way:

void FixedUpdate() {
            Vector3 direction = blackHole.position - transform.position;
            float gForce = blackHoleMass / direction.sqrMagnitude;
            rigidbody.AddForce(direction.normalized * gForce * Time.deltaTime);
        }

That is just normal gravitation that will make your spaceship orbit around the black hole (or slingshot away if you have too much velocity) If you need it to be sucked in like a vortex, all you need to do is add a bit of drag to the Rigidbody. Slowing down will gradually lower it’s orbit which will simultaneously speed it up the closer it gets to the center like in a real vortex.

Yes, but I think you are missing some key points of the discussion. It seems to me, that code is going to result in the same problem as the original post. If an object is already heading for the center of a black hole, no orbiting will happen, it will just fall straight into the black hole. The OP is looking for something more like a whirlpool effect. If an object is heading straight toward the center of a whirlpool, it gets swept up in the current and the movement is more similar to what the OP described.

What Partel said!

Gravity doesn’t behave like that even for black holes. Stars will orbit quite happily around a black hole in a stable orbit unless they get close enough for spaghettification to happen or enter the event horizon (in which case you should simply delete object and maybe increase the gravity and area of effect around the “black hole”.

Why doesn’t anyone actually read the discussion? The OP is looking for the specific motion described, not a realistic black hole simulation

If your comment was directed at me then the first thing I said was

Partel of course mentioned

.

Furthermore Op hasn’t made it clear exactly why (s)he wants this effect. There are two likely answerers:

  1. Op has a valid reason for wanting this effect
  2. Op want this effect because they believe that black holes behave this way.

If it’s number two then educating them about the physics of black holes is a valid response.

@OP
If you want to go from physics to tweening, don’t have to make the rigidbody kinematic, it’s difficult to get a smooth result like that. Instead you can smoothly take control of it’s velocity by

rigidbody.velocity = Vector3.Lerp(rigidbody.velocity, whirpoolVelocity, whirpoolWeight);

whirpoolWeight can be function of the spacecraft’s distance from the black hole.

You can probably get a procedural whirpooling effect with a few lines of code:

Vector3 whirpoolVelocity = Vector3.Cross(transform.position - blackHole.position, Vector3.forward) * rigidbody.velocity.magnitude;
        whirpoolVelocity -= whirpoolVelocity * drag * Time.deltaTime;

The second line should suck the spacecraft in using drag.

In Unity 5 there’s a PointEffector2D that can attract or repel stuff to at least help give you this effect. You can even select different force modes of constant, inverse-linear or inverse-squared as well as specific drag coefficients.

If you were to add a tangent velocity that was scale relative to the distance from the gravity source then it may give you want you require.

How about having the gravityForce increase over time while the body is within the trigger collider rather than adding a drag force? You would still want gravity to be be inversely proportional to the square of distance though, just with an added modifier.

Should give the same effect.

Thanks for the suggestions and ideas everyone. In the end I was looking for a rather specific whirlpool effect without a lot of variance so I ended up using a translation approach rather than physics approach.

When my object enters a “black holes” collider I remove the objects rigidbody2D and then allow the following code to run in Update:

transform.RotateAround(blackHoleCenter.position, Vector3.forward, rotationSpeed * Time.deltaTime );

            Vector3 dir = transform.position - blackHoleCenter.position;

            dir.Normalize();

            transform.Translate(dir * encroachSpeed * Time.deltaTime, Space.World);

Pretty simple solution but it gives me the desired effect I was looking for, im sure it could be improved as well to make the transition from using a physics body, disabling it and then translating better.

Thanks again everyone.

You’re still using physics and as such, you should not be moving static colliders. Just set the rigid-body to be kinematic, it’s far faster and designed to be moved. When you remove the rigid-body, all the colliders attached to it are recreated and attached to the ground-body at the origin. Whenever you move static colliders, they are recreated which gives you bad perforance and doesn’t scale well.

Thanks MelvMay I’ll do that.