Massive Planets

Unity is designed for rendering scenes with a walkable scale, like 10km². However, planets are typically much larger than this. For example, Earth has a surface area of 510,000,000km². While you can increase your Camera component's Clipping Planes / Far setting to something massive, and scale objects up to be massive, all scene rendering will begin to break down if your camera actually travels there.

The reason why this happens is because Unity (and most engines) stores and renders everything using 32 bit float values, which lose decimal precision as the value increases. For example, if your scene fits within a 1km area, then your GameObject positions will be accurate to around 0.1mm, which is more than enough for most projects. However, if your scene expands to 1000km (1000x larger), then your GameObject positions toward the boundary of your scene will decrease by 1000x, and will only be accurate to around 10cm. This loss of precision in position values means objects will begin to shake, physics will break down, etc. If you extend this to an Earth sized planet, then nothing nearby will render properly, and the terrain itself will turn into some blocky mess.

To work around this issue, it's a good idea to keep your camera near the scene origin (0,0,0), where position values remain high precision. To do this while allowing your camera to travel around the planet, you need to move the planet around the camera. Planet Forge comes with a system to do this, called the SimpleOriginSystem.

Simple Origin System

As the name implies, the Simple Origin System is a lightweight and simple system that moves the scene origin around the camera. This works by checking the position of the camera, and if it goes out of bounds (by default 1km), then it snaps the position of the camera and all objects back by the same amount.

This system consists of three components:

1

SnappingCamera

Must be added to the MainCamera GameObject in your scene.

2

SnappingObject

Must be added to the root GameObject of all objects in your scene.

3

SnappingEvent

Tells you when the camea position has snapped, and gives you a Vector3 value to send to components that need to compensate for the snapping.

World Space Positions

If you have any components that store world space positions, or render things based on world space positions, you must update those positions when the scene snaps, because those old world space positions will no longer be valid.

For example, if your player is moving toward a world space TargetPosition, then after a change in origin/snap, this TargetPosition will be incorrect. To fix this, you can add a function to your script like:

void AddOffset(Vector3 offset) { TargetPosition += offset; }

You can then add the SnappingEvent component alongside your component, and hook this component's OnSnap event to your new AddOffset function. This will correctly update your TargetPosition every time the scene snaps.

For example, the ocean rendering system in Planet Forge comes with the SgtOceanRays and SgtOceanDebris components. These both render in world space, and therefore look incorrect when the scene snaps. To fix this, you must add the SnappingEvent component aloongside them, and hook the OnSnap event to the AddOffset functions present in both of these components.

Last updated