64bit precision

Hi all,

Short question. For a large map i have now on the client side used floating point origin to get rid of the 32-bit floats precision problems.

But on my server... what are my options? I can only think of 64 bit precision floats a solution for my problem. I need to query along big distances so shifting origins etc on server not an option.

Any advice?

Before I start providing options I'd like to know what is the world size on the server

@Sima_Havok this problem was already discussed in other places. The worldsize will be at a size we still can use 32bits precision on the server. (max 100km2 probably)

Split the simulation into simulation tiles. Each tile is represented by a separate world & has its own shifted origin that is centered at the tile. Essentially the same way you do it on the client.

Except almost every game will have interactions that can cross tiles. Creating islands is what I was thinking. A bit more involved but in other respects the same.

@Joachim_Ante_1 Is this gonna work in the situation where you need todo a raycast over a 10km to see if a shot can be made from the tank towards the target? Imagine 1 tile would be 1km2 you would need to iterate over 10 tiles for the check (if not more).

You could create a single world of your static colliders for this. Transform everything into a single space. Then when casting filter/exclude by real world position. Only when static things are added/removed would you need to rebuild this world.

For tank movement you might actually be able to do something similar. Single world transform everything to the same space. Filter out what can't interact. I think dynamics has filters for this. I think this works well with a relatively small number of bodies. With your map size what are the chances that things in different world positions would interact in the singular physics space causing performance issues? Likely not an issue but could potentially be.

Kinematic bodies for tanks would be more complex to implement but you could more efficiently exclude interactions.

I was hesitant to mention ad hoc approaches earlier but it can be the best approach. Big picture this is just not a generic problem. That people want it to be doesn't change the reality.

First of all, I would start by asking if doing a raycast across 10km is a reasonable thing to do....

1 If you want to run a simulation over 100*100km with a reasonable simulation density, you need to go with a MMO style simulation approach at that scale for the server. This means splitting the world into tiles and doing simulation only in one tile and having neighboring tiles loaded as read only data. Most likely scaling the simulation across multiple machines.

This is not because of floating point precision but rather because you usually can't fit a whole game world simulation of that scale on one machine in terms of performance & memory consumption.
(I am assuming you are trying to make a game with real world sized objects and lots of detail.)

I would say that building such a game & server simulation tech is complex. There is a lot of pieces to it. DOTS surely makes it simpler but that doesn't make the problem itself just go away. There is a lot of base tech to build to make all this work. If you do not have a good handle on all the pieces that you need to build here, then honestly my best advice is to build a simpler game with simpler technical constraints.

Thanks for sharing the thoughts. It's not an MMO, just a big world with base buildings recourses gathering, exploration. The choice can be made to only do physics colliders server wise for buildings and units and limiting the mapsize to about -30kf - 30kf on x and z axes. Server wise only chunks are loaded in which players have activity. Physics wise there will be no chunking in this case.

The reason why I asked for the world size is because Havok physics engine does some tricks to improve precision and support stable simulation for world sizes up to 100k x 100k units. Issue is that Havok Physics for Unity checks if user changed entity transform each frame and if position in ECS differs more than 0.001 from position in Havok then we treat the body as moved and we internally teleport it.

This means that if body is more than roughly 16k units away from origin the rounding error of float becomes 0.001 so value Havok exports back to ECS data starts having the rounding error which will trigger teleporting even without user changing the position. This leads to both perf hits as well as some jitter.

We have plan to export this threshold so that you can configure it to e.g. 0.004 and be fine with bodies up to 50k units away from the origin.

Queries in Havok use single precision so they get inaccurate by rough 0.004mm at 50k units away from origin. Though, you are checking visibility of tanks and buildings so you should be fine there.

Another thing regarding the scaling. If I understand your correctly you scale the world on the server to -30f to 30f. Important thing is that Havok simulation of bodies that are smaller than 0.01 is not stable. I would expect the similar behavior for Unity.Physics. If you have only vehicles and character controllers which are query based than you should be fine.

Even if you don't have small bodies if you have different scale between client and the server that will lead to different behavior. Same applies if you shift world on the client and you don't shift it on the server (not to big difference but it can diverge over time).

woops that should have been 30k instead of 30.

A bit logic and scaling research can help here a lot to realize your project.

The most important is the floating point angle and not the distance to any object in this case. If you fire rays across your map at any angles, you should test at world size of 100000.0m / 10.0f = means 9999.999 x 9999.999m. The maximum floating point precision is 0.001m between +9999.999m and -9999.999m and > 1000.0m x 1000m.

What should the test archive?
The hit precision relativity. When starting a ray at position x,y = -9999.999f with an angle of 0.001f you test the results where the physics ray hits at distance along x or y axis at 0.0m. You should compare you results by pure math double calculation and the physics precision unity/havok does.

Based on your world objects size, you can downscale your real world objects colliders by perhaps a 10th and do all your calculation in one scaled world. If you have obstacles at a distance of 100km with a width of 0.05m you will hit 1 of 1000 in the same row, because of the floating point quantisation errors.

There are a lot of curious optimizations possible in this case based on your environment. You can use 2d rays on all objects that would be definitely hit, or you recalculate a ray after a predefined distance with new recalculated and enhanced angles.

All depends on your environment and thinking outside of the box.

But anyway I prefer an additional unity 32bit offset register, for transform objects, meshes and shaders. There is not need to enlarge any mesh vertex position storage, send over the north-bridge to the GPU.