Lork

The Math Thread

Recommended Posts

Well, I spent most of tonight waiting for unity and visual studio to install, but I got at least a first attempt working. Note: this won't work if you're aiming dead-on at the planet's centre. Still need to figure out whether a manual cross-product or using orthonormalise cleverly will fix that.

I'm basically saying that as long as you're not at the desired orbital height, you get a force added in the direction of the orbital height, and then there's also always a lateral component in the direction of your velocity vector's projection on the planet's surface.

        float desiredOrbitalHeight = 5;
        Transform sphereTransform = sphere.transform;
        Rigidbody body = GetComponent<Rigidbody>();

        Vector3 towardsVector = sphereTransform.position - body.position;
        float dist = towardsVector.magnitude;
        Vector3 perpendicular = Vector3.ProjectOnPlane(body.velocity, towardsVector).normalized;
        body.AddForce(towardsVector.normalized * (dist - desiredOrbitalHeight) + perpendicular);

Share this post


Link to post
Share on other sites

Which is then applied to the players body (Gravity is an arbitrary value for setting the orbit speed)

target.Body.AddForce((downwardVector + orbitVector) * Gravity);

 

At first glance, this is the part that sticks out to me.. You say Gravity is an arbitrary value, but shouldn't it be constantly changing to be aligned with the ship's position? 

 

I'm probably missing something in the unseen weeds there, but seems like that could cause your ship to always align with the same orbit if the Gravity vector remains constant for a planetoid.

Share this post


Link to post
Share on other sites

What's the purpose of this line?

Vector3 orbitVector = Vector3.Cross(downwardVector, orbitDirection).normalized;

Why are you creating a vector that is perpendicular to the direction you want to go? I think you should just use orbitDirection in the next step. But maybe I'm just confused.

 

Anyway, I'm not sure what effect you're trying to achieve exactly (that's a game design question), but for simple orbiting I would just exploit the fact that every body will automatically get on an elliptical orbit if it's only affected by the gravitational force of the planet. Of course depending on it's starting velocity it can crash into the planet (if the ellipse intersects the planet or the starting velocity is zero and the ellipse collapses into a line segment), also it can get a little bit more complicated if you actually vary the gravitational force depending on the distance.

 

To turn this ellipse into a circle I'd either set some desired distance to the planet and apply a force towards/from the planet if the body is getting too far/close or have a desired orbital velocity and brake/accelerate depending on the current speed. I think the body should stabilize into a circular orbit after a short while in both cases. This should also work under certain circumstances even if the gravitational force varies with distance. Note I haven't actually done this so maybe there's a catch.

Share this post


Link to post
Share on other sites

What's the purpose of this line?

Vector3 orbitVector = Vector3.Cross(downwardVector, orbitDirection).normalized;
Why are you creating a vector that is perpendicular to the direction you want to go? I think you should just use orbitDirection in the next step. But maybe I'm just confused.

 

Anyway, I'm not sure what effect you're trying to achieve exactly (that's a game design question), but for simple orbiting I would just exploit the fact that every body will automatically get on an elliptical orbit if it's only affected by the gravitational force of the planet. Of course depending on it's starting velocity it can crash into the planet (if the ellipse intersects the planet or the starting velocity is zero and the ellipse collapses into a line segment), also it can get a little bit more complicated if you actually vary the gravitational force depending on the distance.

 

To turn this ellipse into a circle I'd either set some desired distance to the planet and apply a force towards/from the planet if the body is getting too far/close or have a desired orbital velocity and brake/accelerate depending on the current speed. I think the body should stabilize into a circular orbit after a short while in both cases. This should also work under certain circumstances even if the gravitational force varies with distance. Note I haven't actually done this so maybe there's a catch.

Yeah, this is sport of the approach I was going for.

Share this post


Link to post
Share on other sites

alright sorry, I've been doing Global Game Jam so I haven't been around this weekend. Thank you everyone for taking the time to try and help out :)

 

What's the purpose of this line?

Vector3 orbitVector = Vector3.Cross(downwardVector, orbitDirection).normalized;

Why are you creating a vector that is perpendicular to the direction you want to go? I think you should just use orbitDirection in the next step. But maybe I'm just confused.

 

Anyway, I'm not sure what effect you're trying to achieve exactly (that's a game design question), but for simple orbiting I would just exploit the fact that every body will automatically get on an elliptical orbit if it's only affected by the gravitational force of the planet. 

 I would have thought the same thing about using only the orbitDirection, but that wasn't working at all. The code I have has worked well for approximating an orbit, although at this point I can barely remember how it came together.

 

I tested the code osmosmich posted and to me it seemed to just hold me in space near the planet; I'm exhausted, but I'll poke at it more tomorrow probably.

 

In the mean time, I feel like that my explanations and that code snippet aren't explaining my predicament clearly, so here's an animated gif showing the current (incorrect but close) behavior, and a small Unity project (attached) to demonstrate. I'd appreciate folks not sharing/distributing this code. Note that the relevant maths are in PlanetGravity.cs in the CalculateOrbitDirection and ApplyOrbit methods.

 

7KMsOsn.gif

 

As you can see, despite having different velocities, the two objects both enter an identical orbit. Which seems weird to me.

gravity-wolf-phys-test.zip

Share this post


Link to post
Share on other sites

My first question is how to get that nice perspective instead of the player-camera, haha. I know very little about Unity as regards camera/scene stuff. Anyway, I think at least a part of your issues stem from the fact you're trying to calculate a fixed circle for each object to adhere to, rather than setting only a desired distance from the planet's core. That way the orbit's angle would be unstable but the distance wouldn't - unlesss that creates design issues it will result in a much simpler implementation, similar to what I posted earlier.

Share this post


Link to post
Share on other sites

My first question is how to get that nice perspective instead of the player-camera, haha. I know very little about Unity as regards camera/scene stuff. Anyway, I think at least a part of your issues stem from the fact you're trying to calculate a fixed circle for each object to adhere to, rather than setting only a desired distance from the planet's core. That way the orbit's angle would be unstable but the distance wouldn't - unlesss that creates design issues it will result in a much simpler implementation, similar to what I posted earlier.

 

My gut is that just enforcing the distance from the planet would mean that the velocity while you're in orbit wouldn't be consistent? I do want you to move in those nice big ellipses (assuming you don't add any extra velocity). What do you mean by 'the orbit's angle would be unstable'?

 

Also, to get that view I was just looking in the Scene view, not the Game. To see it hit Ctrl-1 or go Window -> Scene, and make sure that in the Game window the 'Maximize on Play' button isn't toggled on.

Share this post


Link to post
Share on other sites

Sorry dino for not helping, but i'm a little lost about what you are trying to do still!

 

If something is in a natural orbit then it has a specific velocity. You are breaking all sorts of rules, so you velocity doesn't have to be consistant. If i were you, i would just work out the plane that you want the orbit on, and then rubber band your satellite onto a circle on that plane. If the object is knocked away, then bring it back into that line. Is that what you want?

Share this post


Link to post
Share on other sites

alright I tried to make some diagrams to be more specific. I don't know if they will actually help. Also for some reason they all became different sizes when I resized them to 50% despite having the same size to start.

 

In this image we see bodies with a starting velocity that have no additional force added. They move in an orbit defined by their original velocity around the planetary body.

 

u8HKc5t.png

 

In the following images we see the effect of force on the body. A physics impulse that pushes the body to the right (deeper into the Z axis of the screen) rotates the orbit around the planet.

 

65MwtSB.png

 

Here we see a similar behavior when the player applies a force using their controls to push the body in the same direction (the 'pressing D to move right' assumes they are looking along their orbit vector)

 

qgZ14XU.png

 

if these are useless let me know why and I will try to clarify again, or maybe I'll just force someone to get on skype with me and I'll make my fists orbit each other to explain, and then that person can translate that into a real math question.

Share this post


Link to post
Share on other sites

So, once you're in one of these enforced circular orbits you can't escape anymore? All that can change is the angle of the circle relative to the absolute axes?<br /><br />This is so un-physics-y I'm starting to think you'd be better off just using direct velocity setters and ignoring the whole force system.

Share this post


Link to post
Share on other sites

You could still do forces while having the body be trapped at a specific distance away from the planet. You'd just project all the forces that affect the body onto 2 vectors (body's speed direction and the cross product of the speed and the ship-planet line). Then it would bounce around in a 2D sphere surface.

Share this post


Link to post
Share on other sites

While orbiting you can move freely with WASD and your orbit should adjust to match your new velocity. If you move outside of the planets range, you will stop orbiting and float in space.

Share this post


Link to post
Share on other sites

OK, so there's a certain force keeping you at the orbital distance after all, which van be overcome by thrust or other forces - in that case I think you're at my original solution again :)

Share this post


Link to post
Share on other sites

hm, I'll have to take another whack at implementing it; last time I was basically sleepwalking after GGJ :)

 

Thanks again everyone for suffering through my terrible explanations and trying to help out <3

Share this post


Link to post
Share on other sites

I'm not sure if I can help but I'll give it a shot.

First of all, going through your code snippet it's not clear at all how that is supposed to get you into an orbit. You say yourself that you don't know why it works, that's a bad starting point! We can spend some time here concluding why it doesn't work the way you'd expect (which can be instructive), but I think you'll have to re-write it from scratch regardless.

The gist of what I'm trying to do is have players able to orbit around planetoids. I have that working, more or less, by way of applying force both downward toward the center of the planet, and forward in the direction of the players velocity, adjusted to be at the same radius as the players current position.

You're not doing that. You're appling force downward, and to the side. You could try simply removing the cross product and using orbitDirection instead (not sure if that would work tbh, but you can try it).

Okay, so in steady state your spaceships end up in the same orbital plane. Without going through the details I'm immediately going to posit that your cross product tends towards zero, because that is the only part where a lateral force enters. Gimbal lock comes from using rotation matrices, not simple vector addition/multiplication. I would suggest making a graph in your program and plotting the magnitude of the vectors in real time, that would help you with debugging. Now, actually looking at your code it's not clear how this cross product would actually become zero, especially since you normalize it (it would have to be indentically zero then).

What could be happening instead is that there's something funky going on with the AddForce method. I haven't used Unity's rigid body simulation myself, but I looked up the command and it has a second argument that I think has a default value of ForceMode.Force which according to this means the force is applied continuously. You know Unity better than I so maybe you're calling it right (also note though that gravity is an acceleration, not a force, so you actually want use a second argument that ignores the mass of your object when appling gravity). Also, when you calculate nextOrbitPt the first time, don't you want to take the timestep into account?

I don't actually believe either of these two explanations, so maybe the answer is in the code you attached (haven't had time to look at that yet). I'm a bit curious to figure this out myself though because it doesn't make sense based on the first code snippet.

Share this post


Link to post
Share on other sites

Maybe at a big force that'll shove/attract the ship to a certain altitude no matter what?

 

ForceDir = (Ship.Coord - Planet.Coord).normalize

 

ForceonShip = ForceDir * (+- not sure)(idealHeight - Current Height) ^(big odd number)

Share this post


Link to post
Share on other sites

Well, I spent most of tonight waiting for unity and visual studio to install, but I got at least a first attempt working. Note: this won't work if you're aiming dead-on at the planet's centre. Still need to figure out whether a manual cross-product or using orthonormalise cleverly will fix that.

I'm basically saying that as long as you're not at the desired orbital height, you get a force added in the direction of the orbital height, and then there's also always a lateral component in the direction of your velocity vector's projection on the planet's surface.

        float desiredOrbitalHeight = 5;
        Transform sphereTransform = sphere.transform;
        Rigidbody body = GetComponent<Rigidbody>();

        Vector3 towardsVector = sphereTransform.position - body.position;
        float dist = towardsVector.magnitude;
        Vector3 perpendicular = Vector3.ProjectOnPlane(body.velocity, towardsVector).normalized;
        body.AddForce(towardsVector.normalized * (dist - desiredOrbitalHeight) + perpendicular);

Apparently this works, but I think it's weird that you're constantly adding that 'perpendicular' vector. I mean, if you're in the correct orbit that vector will be parallel to your velocity, so it will move you off your orbit, at which point towardsVector gets applied again. A proper orbit should be the opposite, you apply only the downward force in steady state. Maybe I'm misunderstanding what it's doing.

Share this post


Link to post
Share on other sites

Apparently this works, but I think it's weird that you're constantly adding that 'perpendicular' vector. I mean, if you're in the correct orbit that vector will be parallel to your velocity, so it will move you off your orbit, at which point towardsVector gets applied again. A proper orbit should be the opposite, you apply only the downward force in steady state. Maybe I'm misunderstanding what it's doing.

 

I'm not 100% sure but I think the perpendicular vector needs to be there for the ship to move at all. Does it still work if you change the desiredOrbitalHeight to very small or very large numbers?

Share this post


Link to post
Share on other sites

Apparently this works, but I think it's weird that you're constantly adding that 'perpendicular' vector. I mean, if you're in the correct orbit that vector will be parallel to your velocity, so it will move you off your orbit, at which point towardsVector gets applied again. A proper orbit should be the opposite, you apply only the downward force in steady state. Maybe I'm misunderstanding what it's doing.

Well, the perpendicularvector is not quite the right name - it's the projection of the current velocity on to the surface of the planet. So, that gives you the orbit direction. Then, that orbit direction is added to the current force. I expect there's a bunch more scalars in there in the final implementation to make everything feel right relative to one another, this was just my quick attempt at getting something working.

Share this post


Link to post
Share on other sites

Well, the perpendicularvector is not quite the right name - it's the projection of the current velocity on to the surface of the planet. So, that gives you the orbit direction. Then, that orbit direction is added to the current force. I expect there's a bunch more scalars in there in the final implementation to make everything feel right relative to one another, this was just my quick attempt at getting something working.

 

I thought about it a bit more, won't this solution, as is, keep accelerating the ships until something bugs out? It's a small acceleration so maybe it won't matter. Does this work if you replace

 

 

body.AddForce(towardsVector.normalized * (dist - desiredOrbitalHeight) + perpendicular);

with 

body.AddForce(towardsVector.normalized * (dist - desiredOrbitalHeight));

Share this post


Link to post
Share on other sites

I think that might work in the case of a frictionless simulation, but I wanted to make sure to add some force in the direction of the orbital circle the object should end up in.

I added some drag to the object's rigidbody settings to counterbalance the constant acceleration. But besides that, as the object rotates around the planet, as long as it's in the same plane the net 'perpendicular' force should be zero because there's a negative version of the force added when the object's reached the opposite side of the planet.

Share this post


Link to post
Share on other sites

If there's friction then it should be fine, it'll be capped at some max speed.

 

But if you're applying a force that's parallel to the direction of movement, you're performing work/adding energy. The force won't be cancelled out by itself at the other end of the orbit because at that point the body is moving in the opposite direction. The force of gravity from the planet is always perpendicular in a circular orbit, so that won't add any energy to the movement of the body.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now