osmosisch Posted January 29, 2016 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
Travis Posted January 30, 2016 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
osmosisch Posted January 30, 2016 Oh, I assumed Gravity was a scalar, not a vector. Share this post Link to post Share on other sites
iax Posted January 30, 2016 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
osmosisch Posted January 30, 2016 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
Dinosaursssssss Posted February 1, 2016 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. 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
osmosisch Posted February 1, 2016 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
Dinosaursssssss Posted February 1, 2016 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
dibs Posted February 1, 2016 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
Dinosaursssssss Posted February 2, 2016 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. 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. 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) 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
osmosisch Posted February 2, 2016 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
Jutranjo Posted February 2, 2016 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
Dinosaursssssss Posted February 2, 2016 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
osmosisch Posted February 2, 2016 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
Dinosaursssssss Posted February 2, 2016 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
eot Posted February 2, 2016 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
Jutranjo Posted February 2, 2016 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
Dinosaursssssss Posted February 3, 2016 After taking another stab at implementing osmosisch's fix, I believe he has nailed it. Thanks again everyone! Share this post Link to post Share on other sites
osmosisch Posted February 3, 2016 I'm so glad! Guess my PhD was good for something after all Always happy to help! Share this post Link to post Share on other sites
eot Posted February 3, 2016 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
Jutranjo Posted February 3, 2016 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
osmosisch Posted February 3, 2016 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
Jutranjo Posted February 3, 2016 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
osmosisch Posted February 3, 2016 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
Jutranjo Posted February 3, 2016 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