I’m playing around with simulated gravity and I’d like to display the projected path of a player. My current implementation is a bit off, and I suspect it’s probably because of floating point error in the Vector3’s I’m using, but I’d love to know if I’m missing something.
When I get a stable orbit, I’d expect a circular orbit to form, but I get this instead:
This code I’m using to move the player (dot) and draw the path looks like this:
I’m thinking it’s either floating point mischief or that it has something to do with the timing for physics, but I really don’t know where to start. The problem seems pretty much the same if I update the path in FixedUpdate or Update (gravity updates in FixedUpdate).
If it’s just floating points, should I just leave it for now or is there a an obvious path I’m not aware of? I really hope I just made a mistake somewhere
Floating point imprecision comes from very large numbers. Are you using very large numbers? (they technically are not floating point “errors”, it is just a lack of precision)
It does but it can also creep into calculations when there are lots of iterations in a simulation. You could do a simple test to see if this is the case by decreasing the time step of the system e.g. what happens if you slow it down 10x you should get very similar results just at higher resolution or do you get more wobble/error.
Another quick test would be to do all the calculations using doubles with only the visual outputs/transform being updated using floats.
I haven’t checked your code, but I am wondering why you would expect a circular orbit? After all, we are orbiting the Sun in an ellipse. A circle is a particular and unlikely scenario.
Are you sure your code isn’t just physically accurate?
I had the same reaction, as my good old high school science class taught me 25 years ago that circular orbits were near impossible Maybe the science has changed, but I doubt it. Nothing with a stable orbit in our solar system is in a perfectly circular orbit.
I’m not using any large numbers, but I was thinking the imprecision might show up anyway, with many iterations. I’ll try the tests Arowx is suggesting, thanks!
Oh, yea, sorry, I didn’t mean perfectly circular orbits, I meant to say I would expect the stable orbit that I’m simulating to be matched by the path I’m rendering. I’m pretty sure my code is accurate enough in simulating one-body orbit. The problem is the rendered path, which doesn’t match the orbit and does that weird wobble, not that I don’t get a perfectly circular orbit
It doesn’t seem like changing the time factor or physics solver iterations does much, but I think the problem might lie in how the force is applied and the timing of my path calculation… The force is applied as Acceleration on every fixed update and I’m calculating each step of the path without taking into account the “continuous” nature of acceleration… I think… I’m not really sure how to solve this but I think I’m on the right track
Aaaah! Fixed it! Time was the factor I didn’t account for, just needed to only update my gravity force based on fixed delta time and use fixed delta time for each step of the path
This is what I wanted it to do, and even though it’s still a bit off, at least I won’t be annoyed by it. This actually makes sense
After I fixed my error and got a better approximation of the simulation, I actually found that decreasing the timestep improved the precision. Next step would be working with doubles, but I’ll hold off with that for now and see if what I got is good enough. Thanks for the insight though!
Wait, don’t you still have the same issue and it’s just decreased in magnitude now? The calculated orbit is still drifting, which I would have thought still represents a problem.
Isn’t the problem that at each calculation step you’re calculating movement along roughly a tangent from your orbit path, and that your body then moves in a straight line along that calculated tangent until the next step? In doing so it moves slightly further away from your orbital pivot, which then changes the variables used to calculate the next step, giving you slightly different results.
I’m not enough of a math person to figure out how to get those calculations to be stable over many iterations. So personally, I’d calculate the whole path at the start, and then move the body by simply following that path. Anything that might change the orbit re-calculates the whole path. Avoiding recalculations while in transit will avoid calculation drift without making the math more complicated, and allows you to use the same math and data for both the rendered path and the body’s motion.
That seems like the best solution if the system is required to be completely deterministic. Also a formula could be used to calculate where on that path the object is at the current time - This paper gives the solution for a single planet around a single star as :
“where r is a vector indicating the position of the body A with respect to a fixed point O at time t”.
Yea, the problem is still there but what I have now is decent for the current stage. I’m thinking I’d rather work on fleshing out some of the gameplay stuff before I tackle the minor drift issues.
But what you’re saying about doing a deterministic path makes a lot of sense. I’m already calculating projected gravity for the whole path (GetGravity on ln 24 uses a projected placement of the planets etc), but the projection isn’t completely accurate which results in some odd behaviour. I was thinking I’d rework my use of Vector3’s to use double based Vector3d’s (from here), and in that process I’ll look into a deterministic model for my physics. Right now though, I’m sticking with Rigidbodies and Unity forces Also, I’m not sure I need that level of precision anyway, some pretty fun consequences has started to emerge and I want to play around with it a bit.
That is an awesome paper, I’ll have to delve into it at some point. The math is a bit advanced for me though, but I’m sure I’d need to tackle some of it anyway For now, I’m using fixed circular, unrealistic, orbits for the planets and using the formula in my example code for gravity on the players ship, which works fine for my efforts so far. I even get a fun effect on the projected path, which kind of resembles the example of observed motion of planets (this is sped up and looks super erratic, but whatever):
Obviously, this is not deterministic and highly unreliable if you wanna be able to do kerbal-level orbits, but it might work with just smaller improvements. I’m thinking the game might not require planning and setting a perfect route, but instead you eyeball a rough estimate and continually make adjustments as needed. I’m really not looking to do a perfect simulation if I can avoid it, especially if not doing it could afford some interesting gameplay!
Regardless, I’ll look into both how gravity works and improving my simulation with doubles and maybe a more deterministic model. I also wanna add other stuff though!
There are a number of problems dealing with gravity simulations. The floating point errors are probably the least of them. The biggest would be that almost all physics simulations use discrete math. It calculates a frame, moves everything, next frame, moves everything, next frame… and it’s as though the time between those frames doesn’t exist (it doesn’t.) Gravity doesn’t work that way, both Newtonian gravity and GR operates on an infinitely dividable timeline. \
Anything that’s accelerating will not behave correctly receiving it’s acceleration in chunks like that. The obvious solution is to simply increase the number of iterations, but this may actually get you even further from what would actually happen. Instead, you’re going to have to do a perturbation to deal with the acceleration that happened in between the discrete time chunks.
Oh, and anything more than 2 bodies, and the equation becomes indeterminate. There exists symmetries that have be broken and which direction they break is essentially random. There is a common misconception that just because there is an exact equation for something that it’ll have one outcome, and that’s very wrong. Even simple quadratics don’t have one answer.
I wouldn’t bother with switching to double precision. Yes, it’ll be “more accurate”, but the difference in accuracy is mostly apparent when you need to use numbers which are several orders of magnitude different to one another.
For us doing stuff that mostly has to map back to pixels on a screen a floating point numbers is usually more than accurate enough. The main area where we hit issues is when simulating objects far from the origin of our scene. Assuming that 1 unit = 1 meter, issues tend to start in the vicinity of ~10km from the origin. Though I’ve gone much further without problems, it really depends on what you’re doing.