Flying in fixed orbit, could use some pointers!

I’m trying to an Asteroids clone with a twist: instead of moving in 2D, the ships and asteroids will travel in 3D around a fixed point in space, all at a set radius.

I’d like to keep the same sort of trajectory feel from the original game, and I’ve tried a few different approaches to get the physics to work - but I’m really struggling to find a solution.

My latest plan is this: creating a sphere at position 0,0,0 - that’s my fixed point, making my object (let’s say ship) a child of the sphere, at a set height (0,10,0)*.
Now as the ship is a child of the sphere, if I rotate the sphere on it’s y axis, the ship should turn left or right, and if I rotate the sphere along the x axis, the ship will move forwards and backwards.
so y = thrust and x = turn.

Any trajectory that I apply will need be applied relative to the world, i.e. if I thrust, then rotate, the ship needs to carry on with the same velocity in the direction it was facing, not how it is now facing.

Once I’ve figured the ship out, the asteroids/projectiles should be a doddle, just a case of spawning them and having them move in a random rotation (asteroids) or continue on a trajectory(lasers)**.

In my head - this all sort of works, the trouble is I’ve only been programming for a couple of months and I’m not sure how to achieve lofty goals as above.

I know this might seem like a “Hi, please program my game” post but really, I’m only asking that someone point me in the right direction when it comes to applying all this, so all perspectives are welcome!

  • For those curious, the camera will also be a child of the sphere and set at (0,15,0), looking down on the ship.
    ** Yep, you could shoot yourself in the back.

I don’t think there’s a point in actually making the parent object a “sphere”, since it seems entirely abstract for your concept (i.e. there are no colliders used for the spherical space, and it would work exactly the same with an empty object). The only need for a sphere is for visual aid, and I don’t think that one should be the parent of anything.

I think the idea of keeping all objects as children offset from a fixed point (the center of the “sphere”) is a good approach. For each object in the game, you can just rotate its parent object to keep it restricted to the surface of a sphere. Each asteroid and the player would need its own unique parent-- with a Rigidbody-- located at the center for this to work, which is totally fine. To turn the ship, use its local rotation instead of its parent’s rotation.

To allow your ship to have momentum as you described, just use Rigidbody.AddTorque() or Rigidbody.AddForceAtPosition() to torque the parent in the direction the ship is facing. Don’t forget to lock the positional axes of the Rigidbody, and you might also want to change the angular drag to 0 for a space game. You’ll need a simple system to limit the speed of the ship.

Another approach is to use spherical coordinates. This sort of game has pretty simple physics, so you could write simple behaviors in spherical coordinates and transform them to cartesian before applying them each frame. This would probably be less intuitive, though.

Thanks for the guidance, that was super fast and helpful. I’ve had a play around and come up with this for my parent object (the ex-sphere):

        public float Ytorque = 1;
        public float Xtorque = 1;
        public Rigidbody rb;
    
    void Start() {
            rb = GetComponent<Rigidbody>();
        }
    void FixedUpdate() {
        transform.position = new Vector3 (0,0,0); // applied this as my centre object kept moving around, despite locking it in constraints
        float turn = Input.GetAxis("Horizontal");
        float thrust = Input.GetAxis("Vertical");
        rb.AddTorque(transform.up * Ytorque * turn);
        rb.AddTorque(transform.right * Xtorque * thrust);
        }

I like the way the speed ramps up nicely. However, I don’t think I’m 100% there yet - you mentioned that “To turn the ship, use its local rotation instead of its parent’s rotation.”

I’ve tried moving the “Turn” elements to a script on the ship, but Unity doesn’t like that with the necessary Rigidbody. Any thoughts?

Excellent job!

I’m not 100% sure what you mean; I’ll go into a little more detail about what I envisioned.

Both the parent object and ship itself should have a Rigidbody. For the ship itself, you could easily use AddTorque() to spin it around its local up. This way, no matter where it is in play, it can perform simple rotation.

For movement around the center point, you’ll need to rotate the parent in the direction that the ship object is facing. Using AddForceAtPosition() on the parent will probably be easier to do than AddTorque(), because it would be harder to figure out how to calculate the angles needed to apply a torque directly (since the direction of the torque should be forward relative to the ship, which can turn). If you want to do it anyway, it’s just a cross product problem.

This combination of spinning the ship in local space and spinning the parent in the direction the ship is facing should get you where you’re heading. If you can get it working, send .gif’s! Sounds interesting.

Will gladly send .gifs! I’ll bang it up on itch.io when I’m done and share the source code. This is just a “see if I can” sort of project.

To elaborate when I said “Unity doesn’t like that” I mean that when I add a Rigidbody to the ship, it ceases to follow the rotation of the parent. Otherwise, I think you are totally envisioning the same thing I’m envisioning.

I’ve had a read up on AddForceAtPosition() - doesn’t this only transform direction and not rotation? Jamming the example code unity gives and tweaking it didn’t seem to give me much success.

As for moving the turning into the ship, I’ve done as you’ve suggested and I’m happy with that.

I didn’t think of that. All the instances that I’ve used child Rigidbody’s have been when they were kinematic, so I forgot that doing this would make it behave strangely.

You COULD make your ship kinematic, but you would need to write a simple behavior that models torque, angular velocity, and angle. That would actually be really easy, since you only need to do it about one axis.

You could also use a FixedJoint instead of parenting to attach the ship to the central object. This would also allow you to fall back on the physics engine if you want objects to be able to bounce off of each other, rather than manually applying torques to the central objects when radial objects collide.

According the manual, AddForceAtPosition() adds both force and torque. Actually, if it didn’t add torque, it would be exactly the same thing as AddForce()-- there would be no point in specifying a position.

Simulating rotation from torque requires a known center of mass. The manual mentions that the COM is calculated from attached colliders if you don’t explicity specify it. I’m not really sure what you get if you don’t have a definition and no colliders. My assumption is that it would be (0, 0, 0), which is what you would want, but you could try adding a collider just to see.

If AddTorque() is working better, though, then just use that.