Huge scale solar system.

Hello!

I need assistance on a problem, I’m playing with huge scale scenes, and in this case a Solar System.

Currently there is 1 planet and 1 yellow star.
The thing is, that due to the floating point limitations, I cannot just move a planet or player over 100000 Unity Units without getting loss in precision.

I’ve been searching, and found this: “You don’t move in the universe, the universe moves around you.”
Also I watched Unite 2013 where KSP dev told the same thing.

The player’s ship has a simple rigidbody and a controller to move it around. But It cannot move up or down in space.

So, I have all GameObject’s (Except the Player) in a parent GameObject, called Universe, now I need to keep the player in the middle of the scene, and make the Universe GameObject move making it look the player would be moving.

First thought is to have triggerboxes all around player, and make universe move to the other direction the triggerbox hit was. But its pretty inaccurate.

Second thought is doing everything in a universe mover script, and make the player reset its position with FixedUpdate function. But how do I get where I am going? The ship controller script is just adding force to the rigidbody when button was pressed.

Third thought is multiple scenes, having an trigger around the edges, and then loading the new scene. Problem is that the planet’s have orbits, and rotations.

I like the Second one most, I know how to keep player in the middle, but what about moving? And what if there are NPC’s or Asteroid moving at high speed, how are they going to look?

Help.

Having the whole universe in one gameobject will result in the same problem after some time. Your universe gameobject would be far away from you and the float calculations will get imprecise. You have to cut down the actual distance. The best approach in terms of performance is to let the player move in a small area around the origin and when he goes beyond a certain limit in one direction you simply move everything so the player is again close to the center.

The best way to move such a universe is to use two gameobjects which are located at the origin. One is empty the other contains everything. When you want to move the univers you simply move the gameobject that contains everything and then move all objects over to the empty gameobject. That way everything is again relative to the origin. You should group things that belong together into intermediate gameobjects so it’s easier to move them and it reduces the relative error due to parenting / unparenting at high distances.

Your can use a UniverseOffset script like this:

// UniverseOffset.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

public class UniverseOffset : MonoBehaviour
{
    public Transform player;
    public Transform universe;
    public int xSector = 0;
    public int zSector = 0;
    public float sectorSize = 1000f;
    private Transform tempUniverse;

    void Awake()
    {
        tempUniverse = new GameObject(universe.name + "_2").transform;
        tempUniverse.position = tempUniverse.eulerAngles = Vector3.zero;
    }
    void Update()
    {
        Vector3 pos = player.position;
        int xMove = 0;
        int zMove = 0;
        if (Mathf.Abs(pos.x) > sectorSize)
            xMove = Mathf.FloorToInt(Mathf.Abs(pos.x) / sectorSize) * ((pos.x > 0) ? 1 : -1);
        if (Mathf.Abs(pos.z) > sectorSize)
            zMove = Mathf.FloorToInt(Mathf.Abs(pos.z) / sectorSize) * ((pos.z > 0) ? 1 : -1);
        if (xMove != 0 || zMove != 0)
        {
            xSector += xMove;
            zSector += zMove;
            Vector3 offset = new Vector3(-xMove * sectorSize, 0, -zMove * sectorSize);

            universe.position += offset;
            Transform tmp = tempUniverse;
            List<Transform> childs = universe.OfType<Transform>().ToList();
            for (int i = 0; i < childs.Count; i++)
            {
                childs*.parent = tmp;*

}
tempUniverse = universe;
universe = tmp;
tempUniverse.position = Vector3.zero;
// only needed when the player is not inside the universe gameobject itself
//player.position += offset;
}
}
}
Keep in mind that all coordinates inside the universe need to be offset by
pos +=new Vector3(xSector, 0, zSector)*sectorSize
to get the actual “absolute” position. However relative distances stay the same.

**Simpler Question? **

Please explain what you are trying to do.

Moving the Universe

If I think I understand from the title why don’t you just add a controller to the GameObject “Universe”

Use the “Serious Sam” approach.

Simulate distance by keeping position the same and modifying scale.