Is it a Unity issue, or is it all game engines?

When creating a space sim, the issue of scale is a big one. To create planets and stars in proportion to a ship model requires very large numbers in terms of scaling factors relative to the ship. For example, let’s say a ship that is a 100’ long would have a scale of 1. An Earth-sized planet would, then, have to be roughly 217,000 times as large, and Earth is a smallish planet. The distance from the Earth to the Sun is roughly 23,000 multipled by the radius of the Earth (that’s almost 5 billion game units, if you’re keeping score), and Earth orbits relatively close to the Sun. None of this, of course, would bother me at all if Unity could accurately calculate such large numbers say, for example, when updating positions, but it can’t.

So, what is the solution? How do you mange precision movement, such as that of a spacecraft in a system of objects and distances that use such large numbers that floats can’t accurately calculate updated positions?

It’s common to all game engines. It’s due to floating point imprecision, as the float gets larger, the precision lowers. People doing space sims tend to get around it by moving the whole universe instead of moving the camera/ship. That way the things closest to the area of interest are near 0 and get the most precision. Things that are far away will be subject to error, but hopefully you won’t notice those because they are far away.

Hi Maker16,

IMO there are 2 solutions. First, you could use a smaller scale for the whole game. This, however, requires custom physics as the built-in PhysX-engine needs real sizes. On the other side, if you’re creating a Space-Sim, I don’t think there’s any big sense for using PhysX heayvily.
Second, you could use other Data-types, but this would require some additional conversion bla.

As space hasn’t much to do with our so-called “real-world-physics”, I’d prefer the first solution.

regards,
lunio // attractivenerds

@niosop, I am trying that approach, but still encountering the same issues. However, I think I am implementing it wrong. I was using a gameobject to represent the sector of space the player is in and all bodies in that sector are children of the sector object. That way, I can move the sector object and everything updates (except the player ship, which remains at the world origin). Now I’m thinking this does nothing to solve my problem because the sectors are very large, so object local positions within the sector are prone to being large as well. To reach a star, for example, the sector object would have to shift up to 1000000 units (depending on the star’s position relative to the sector center), so, even though the player may be relatively close to the star, it’s position is still being calculate relative to the sector’s position, relative to the player, resulting in stil very large numbers.

After reading your post, however, something clicked, and I will try a new implementation. Rather than making the sector object an actual object that moves, the sector object wil simply control all bodies within it, which will have global positions, not local ones. This should solve the problem and make your suggestion viable. You are correct in that the farther objects won’t need precision, so here’s hoping. Thanks.

Ahh…The simplest solutions are the hardest to find. I just pass the Vector3 data to a Vector3 class I created using doubles instead of floats. Add the movement values to the DVector3 and convert that back to a Vector3 when updating the positions and voila. Precision movement.

And to clarify for others what problem this actually resolved…It is easy enough to move objects that are, say, 1,000,000 units from the origin when you are moving in values of 1 unit per frame or more. However, if you are only moving .01 units per frame on any axis, the position can’t update because of the precision issues of floats. It will remain at 1,000,000 indefinitely. By using Double values to store the position, and to handle the positional math, you can store the precise position, such as 1000000.01. You update the Double values for position and convert those to a Vector3 that you pass to the transform.position. This way, you can move at fractional speeds per frame and still have planetary objects updating their positions correctly.