Search Unity

How to handle truly open world maps with Unity, due to floating point limitations?

Discussion in 'World Building' started by Marcos-Elias, May 9, 2018.

  1. Marcos-Elias

    Marcos-Elias

    Joined:
    Nov 1, 2014
    Posts:
    159
    Hello guys, I posted this at the feedback website, if you have tried making a large world, you know how hard it is with Unity today:
    https://feedback.unity3d.com/sugges...o-7-digit-limitation-for-floats-on-transforms

    I'm trying for years (!) to see if this works, but it is still hard, there is no solution for this problem... In details:

    I'm trying to make a driving simulator with large routes (20km+), and this is almost impossible in Unity right now. Tiling, loading and unloading scenes work really well (async), but...
    We need a native origin shifter feature to move everything keeping the camera at 0,0,0 when the player moves far than 999 units! (or 9999 in some cases). This is because the floating point used has only 7 digits. After 999 units (1000 to 9999) we get only three decimal digits... Then the camera shakes, shadow blinks, smaller objects appear out of place... That's so bad :(
    In this video I explain all the problems, showing a sample of it working in a game (not mine) made with Unreal Engine:


    The game shown in this video is Fernbus Simulator from TML Studios. I could not find any example of a game like this made with Unity yet, all mobile games have smaller static scenes with boring routes, or divided with loading screen between scenes (which I do not want and I will not make, that's not natural). I want making some real routes from Brazil someday and they must be large, with real scale...
    I heard that 64-bit float is not the right thing to do due to performance problems. But we need at least some API to move everything in an optimized way, where sound and other engine features continue working, like the new Navmesh... It's dynamic but does not work if we move the world with moving agents. I'm almost giving up after some years trying to do this since Unity 3.x, but I don't want switching engine just because of this little step... :( I spent many years learning Unity as an indie, I like its interface, features, services, the company vision etc...
    Is it really almost impossible making open world in this engine?! What would you recommend?
    I'm using a floating origin like this, with some optimizations:
    http://wiki.unity3d.com/index.php?title=Floating_Origin
    In essence: we should not rely on global world coordinates, we should have an API to move the entire world seamlessly, where everything continues working (light, audio, physics, navmesh, etc). I think that it is not that hard making this in Unity, since floating origin almost does it. Almost...
    Without this it is almost impossible making an open world game with Unity, at least a decent one, without many limitations on other features (be it on audio, physics or navmesh, for example...).
    If you have any information about this feature, or other things that I could try, please send me an e-mail:
    marcos@viamep.com
    marquinhosxp@gmail.com
    My game, made with Unity (beta, where the problem exists): https://play.google.com/store/apps/details?id=com.viamep.pbsu
    I love Unity for everything that it has and also I am a Plus subscriber, but this issue is almost killing my project... There are many feature requests related to 64-bit floating point for transforms or origin shifting, but no official position from the devs yet... For years... :(
    Please if you can fix this huge problem, or at least give us some information on how to handle these large maps! The floating origin available at wiki is not perfect.
     
    Last edited: May 14, 2021
    Max-om, skinwalker, llMarty and 3 others like this.
  2. newjerseyrunner

    newjerseyrunner

    Joined:
    Jul 20, 2017
    Posts:
    966
    I'm pretty sure Kerbel Space Program uses a floating origin, and that was definitely made in Unity.

    Switching to doubles (64-bit floats) would not solve this problem. Because of how IEEE floats work, the additional space does not really increase granularity all that much.\

    I found this wiki page in a KSP forum: http://wiki.unity3d.com/index.php?title=Floating_Origin
     
    dadude123 likes this.
  3. Marcos-Elias

    Marcos-Elias

    Joined:
    Nov 1, 2014
    Posts:
    159
    Thanks newjerseyrunner, but I posted it in my text, it works but with lots of drawbacks... I think that the engine itself should have something to help us with this "problem" in a more optimized way. Moving everything in a single frame for some games may cause a little delay in audio running (less than 1 second, but it is annoying for players), navmesh currently does not work, and many other things also still rely on global world coordinates (like static batching...). Open world was never the focus on Unity, I hope that it can get some features to facilitate this development someday...
     
    deus0 likes this.
  4. zenGarden

    zenGarden

    Joined:
    Mar 30, 2013
    Posts:
    4,538
  5. Marcos-Elias

    Marcos-Elias

    Joined:
    Nov 1, 2014
    Posts:
    159
    It’s too complex to setup, I’m doing the same thing but in a simplified way (my scene streamer is working well, this is not the problem).

    Native Unity features that require static positions stil won’t work with World Streamer... This is a move that the engine should take, everything that we can code is limited by its APIs...

    By the way I read there that it supports dynamic navmesh, I’ll give it a try later... (although this is not the perfect solution, this asset changes the way we make the world). I still think/vote/ask for this as a native feature someday hehe
     
    Recon03, awesomedata and antoripa like this.
  6. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,618
    Plus, PhysX does not seem to support doubles either, according to following NVIDIA post from 2015:

    https://devtalk.nvidia.com/default/...-free-version-of-physx-/post/4469496/#4469496
     
    Marcos-Elias likes this.
  7. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,618
    This topic came up a few times in the forum in the past and I remember somebody suggested to put the entire world chunk under a root node and move that root node around.
    rootnode.png

    If you use Unity 2018, you could try to use the C# Job System and the TransformAccess to move those chunks around in a multi-threaded way.

    However, I believe it won't work with static objects. On the other hand, you most likely can't build a big world and mark everything as static object anyway. Unity combines static meshes for example and if your scene has a gazillion static trees for example, you probably run out of memory really fast.

    I guess you want to implement a system that uses a predefined amount of objects and moves them around at runtime, basically reuses the same pool of objects and relocates them depending on the view. This could be implemented via C# Jobs as well. And you probably want to draw them via GPU instancing.

    I don't know how physics behave if you move the root node around though. I imagine physics doesn't really like that, but I never tried, so not sure.
     
    Akshara and Marcos-Elias like this.
  8. Marcos-Elias

    Marcos-Elias

    Joined:
    Nov 1, 2014
    Posts:
    159
    If we move everything in FixedUpdate physics seems not to be a problem... At least for now... It may vary depending on the script execution order for each project. The floating origin (script from wiki) moves things on LateUpdate, this breaks physics since it is not in sync with FixedUpdate. Changing it to FixedUpdate solved lots of problems for me. I think that Unity could create a native way to do it without interfering with user scripts, like moving everything always first, before calculating the next frame...

    Actually I'm already doing this... My project uses blocks of 3km², all objects are positioned as a child of a root game object, and once player passes 999m it moves everything back to 0,0,0 considering the camera position. By getting to the borders other tiles are loaded (async) and most of the time it works really well. By checking the distance the system unloads scenes left far away. Most of the time there is only one or two scenes loaded (plus a manager in a persistent level, to control everything).

    I spent many months making/testing the tiling/level streaming, while I could do the artistic or other parts... Every other person who wants to create something like this must reinvent the wheel...

    This is a feature that ideally the engine should provide us some day. Checking if a scene is already loaded, positioning the gameobject close to the other, etc... It makes the level creation much harder than it should be, it is a very important feature supporting large worlds these days.

    Even after I created the level streaming, the main problem is that many of the engine features does not work well with this kind of games, being the Navmesh one of the most frustrating one... Also I wish a native world streamer and multiple terrain editing (like Unreal), since coding everything from scratch everytime is very hard... It seems that better terrain tools are coming soon, that's good thing, a step in the right direction.

    Of course I'm considering it if Unity wants to be used for more open world projects in the future. Lots of new games could be made if this were integrated with it.

    One last notice about moving everything once a while in FixedUpdate for me, is the sound... Depending on the speed that we are and the amount of objects in the scene, it gets an annoying "sound spike" for less than a second in all my projects. I still don't know how to fix this. For a driving simulator in my tests we need to move everything after 999 meters driven (4 digits after the dot), if we go by 9999 (3 digits after the dot) there are problems with shadows and lower near clip planes. So each 1km driven we get a bad user experience due to this, even if the game is running at more than 90fps it shows a little "stop" in the experience... There must be a better way of doing it.
     
  9. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,618
    What's causing the hitch, according to the Profiler?
     
  10. Marcos-Elias

    Marcos-Elias

    Joined:
    Nov 1, 2014
    Posts:
    159
    Unfortunately I haven't found it yet on the Profiler. It may be the act of moving everything, but apparently floating origin itself does not show high cpu overhead. Sometimes this does not occur, it's strange (but most of the time it appears just in the exact moment that everything is moved). It never happens if we don't move the entire world. I'll try debugging it with Profiler again with more time.
     
  11. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,618
    That would be the first step to make sure to understand what's going on and what's exactly affecting performance. Once you have the results, you can see if it's something you can further optimize or is an engine flaw / missing feature.
     
  12. Marcos-Elias

    Marcos-Elias

    Joined:
    Nov 1, 2014
    Posts:
    159
    I tried it a lot, of course, but there is no visual thing there indicating the problem... It seems related to updating lots of colliders at the same time (moving everything is a bit heavy operation).
    Some audios have the pitch changed in Update/FixedUpdate, first I thought that this was causing the problem due to differences in script execution order (some before, others after Floating Origin)... But even if I completely disable/remove them, and put a simple audio running (a single AudioSource with a looped AudioClip, no script changing it) the problem persists, so it is not any of my scripts that are causing that... Another time I'll try recording a detailed video showing Profiler, or even better, sharing a sample small project where the problem appears.
    The project runs fine at 250+ fps (while on low graphics, but with all simulation code running), but the little audio problem is there.
     
    Last edited: May 12, 2018
  13. zenGarden

    zenGarden

    Joined:
    Mar 30, 2013
    Posts:
    4,538
    Unfortunately i'm not sure you'll see soon some open world features in Unity.
    Each open world game made in Unity uses it's own system and it works pretty good like Pine game for example.
    https://www.twirlbound.com/pine/blog/devblog70_asyncloads_acacias
    This is the only way to make open world instead of waiting and never see the features coming.
     
  14. Akshara

    Akshara

    Joined:
    Apr 9, 2014
    Posts:
    100
    I'm going a bit off topic, yet as an audio guy this comment makes me think of a few things...

    Are the audio files in MP3 format? If so, does a WAV file with the simple audio experiment make the hiccup go away? Secondly, could using Time.unscaledDeltaTime with those specific audio files during the translation operation help? And finally, could adjusting the Audio DSP Buffer Settings slightly up or down help smooth the playback out? This last one is generally not recommended by Unity, yet with other pro audio applications and hardware, adjusting the buffer can sometimes quickly solve audio spikes and loss of sample rate sync.

    These are all shots in the dark, yet might spark an idea and worth looking into.
     
    Marcos-Elias likes this.
  15. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,190
    I'm not aware of any commercial games that don't rely on floating origin. Games like Breath of the Wild, The Elder Scrolls, and so on are all built on engines and frameworks that according to you make it impossible to create a decent open world game.

    It definitely wouldn't solve every problem because it isn't just Unity that is restricted to single precision. Both of the major physics engines on the market - Havok and PhysX - are restricted to and optimized for single precision too.
     
    Last edited: May 12, 2018
  16. Marcos-Elias

    Marcos-Elias

    Joined:
    Nov 1, 2014
    Posts:
    159
    There is a move in this way coming, slowly, but it is happening... Multi scene editing in 5.x (without this it would be much harder making the seamless level borders), Dynamic Navmesh in 2017.x (although it is still not perfect)...

    I'm not waiting, I'm making it with all those drawbacks, but at the same time considering other options... That's the point of my message, there is a huge demand for features like these, soon or later Unity should take some decision if they will embrace or not open world by default, as they do really well for 2D, VR/AR and many other things...
     
  17. Marcos-Elias

    Marcos-Elias

    Joined:
    Nov 1, 2014
    Posts:
    159
    There is UNIGINE that has this feature, but I don't know how much performance it drops by going 64-bit for positions on everything. Would love to see some benchmarks with 32 vs 64-bit on popular desktop GPUs and devices. But paying $10k to discover is not a good option hehe (by the way there is a trial).
     
  18. Marcos-Elias

    Marcos-Elias

    Joined:
    Nov 1, 2014
    Posts:
    159
    Most are wav but there are some mp3, I'll check that later, thanks for the tips!
     
  19. zenGarden

    zenGarden

    Joined:
    Mar 30, 2013
    Posts:
    4,538
    Well open world features are already available in UE4, sometimes it's a matter of choice to pick up the right tool that will allow you to make what you want in a smooth way without needing to re invent yourself the wheel again.
    Anyway good luck at your open world.
     
  20. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    UE4 floating origin support is very limited, doesn't support most of what people on these forums think it does. It's not just flip a switch and navigation and physics just work. The hard problems are still yours to solve.

    Most of the challenges aren't really specific to floating origin. They are rather about what is the most efficient way to move things. Floating origin is simply a context that pushes some things pretty hard. So there is no magic bullet unity can even do here, floating origin 'support' is a misunderstanding of the core problem.

    Yes they could allow setting an origin for things like navmesh. That kind of thing would be nice, but it also wouldn't solve the really hard problems.
     
    Marcos-Elias likes this.
  21. Marcos-Elias

    Marcos-Elias

    Joined:
    Nov 1, 2014
    Posts:
    159
    If they make all engine tools with floating origin in mind, 99%+ of the problems would be solved... That may be not easy for everything, of course, but it’s still relevant.
     
    deus0 likes this.
  22. zenGarden

    zenGarden

    Joined:
    Mar 30, 2013
    Posts:
    4,538
    This is not a priority and necessity, most indies makes mobile games or games that are not open world.
    But perhaps some floating point and open world tools will become available someday.
    Meanwhile you can buy world streamer plugin or you are on your own.
     
  23. Marcos-Elias

    Marcos-Elias

    Joined:
    Nov 1, 2014
    Posts:
    159
    This is just an opinion...
    I personally see it as priority and necessity since it is becoming an amazing general game engine even better each release, not just mobile anymore... We're not on Unity 4 era. There are lots of requests about this and no official word of what we should do... (even at the feedback website, that was designed for this kind of message).
    I would like to get an answer like "we will support" or "we won't support" open world... I never saw Unity teams saying that (yet).
    Unity is growing and getting better graphics after 5.x... High end PC/consoles games with Unity is being possible now. So why not?! They are making many things for high end graphics... I don't see any reason they do not support open world in the future.
    I don't like that specific asset (World Streamer), it makes things more complicated than it should be (for what I saw on docs). The API for scene streaming is working fine for me (at least when we forget about moving the world with everything running). I just wish a native support for floating origin out of the box, with less dependency on global world coordinates for its native features.
     
    deus0 and Akshara like this.
  24. zenGarden

    zenGarden

    Joined:
    Mar 30, 2013
    Posts:
    4,538
    If people would had to wait for Unity new terrain some years ago they would never had done their game LOL
    Same for open world features, you can wait ... or start making your game :rolleyes:
     
  25. Marcos-Elias

    Marcos-Elias

    Joined:
    Nov 1, 2014
    Posts:
    159
    Didn't you read my first post, the one opening the thread? :p I started making my game already about 2 years ago, there is a beta published which already uses a large map and floating origin, scene streaming etc... I'm doing it even with these limitations and I also like everything about Unity (C#, multiplatform made easy, the way it works compared to Unreal, etc). I just cannot use Navmesh and there is a delay when everything is moved, and also on this I'm not just waiting but searching (I bought NAV-AI but it didn't work here, I'm almost buying A* Pathfinding, and so on...).

    I'm not waiting, I'm asking for a better solution, showing demand for that and waiting for some reply of the Unity developers, since most of other threads just debate without showing the hard limitations in practical terms. Other people give up or switch engine too early...

    I really don't want leaving Unity just due to this problem. As an indie dev I started making my project without knowing about it, and learned that it is not well suitable for open worlds when I got the shadows blinking... :p
     
    Last edited: May 14, 2018
    Rond and thinbug like this.
  26. TerraUnity

    TerraUnity

    Joined:
    Aug 3, 2012
    Posts:
    1,255
    We also use an extended version of the script OP mentioned in the wiki:

    https://forum.unity.com/threads/rel...-open-world-environments.532304/#post-3504450

    But one problem we encountered was when cameras moving with animations (in CineMachine) which overrides the offsetting function and finally starts to drift away and messes up everything. However, still didn't find a better solution to this, but it still works in most scenarios.
     
    Marcos-Elias likes this.
  27. awesomedata

    awesomedata

    Joined:
    Oct 8, 2014
    Posts:
    1,419
    This is still a huge issue for some people.

    Was a bug report ever put in for this?


    It kinda disheartened me when MegaCity was released and I realized it was still not addressing the floating origin issue.
     
    deus0 likes this.
  28. bazztard24

    bazztard24

    Joined:
    Jan 17, 2015
    Posts:
    6
    I don't know if this is a solution, but you can scale (all the assets, terrain, etc) so you can fit the max floating point [9999.999]. Yes, you'll be expecting weird behaviours, but whith a lil tweks maybe you can match your desire performance and mechanics.

    I'm starting to use the new terrain system 2019, and trying to enable/disable the terrain neighbors [chunks] on a fly, but i don't know if is better trying to enable/disable or Instantiate/destroy chunks based on the camera position
     
  29. llMarty

    llMarty

    Joined:
    Dec 14, 2014
    Posts:
    33
    Could you please share your "Floating Origin Advanced" script with us? That would be super helpful. :)

    Thank you!
     
  30. TerraUnity

    TerraUnity

    Joined:
    Aug 3, 2012
    Posts:
    1,255
    Actually it is not a bug at all and animations considered to take over transforms with a higher priority, so you have to choose translation being done with direct position set or animations, but i remember one of our customers found a way to get over it, let me know and I'll share his explanations.

    Yes, MegaCity's scene metrics was not huge to even need it and also no general solution from Unity for this.
     
  31. TerraUnity

    TerraUnity

    Joined:
    Aug 3, 2012
    Posts:
    1,255
    That's the worst solution to get over floating point errors because as you said you are opening a lot of other issues no need to mention, unless your project is very specific to ignore lighting, physics, translations and ...

    enable/disable chunks is always better and takes care of memory leak and unnecessary allocations the way object pooling is handled. In our TerraLand package the streaming terrain chunks are being handled exactly as this which a certain amount of chunks getting reused throughout the entire gameplay.
     
  32. TerraUnity

    TerraUnity

    Joined:
    Aug 3, 2012
    Posts:
    1,255
    Not much different from the wiki but here you go:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4.  
    5. public class FloatingOriginAdvanced : MonoBehaviour
    6. {
    7.     public float distance = 100.0f;
    8.     public bool collectObjectsOnce = true;
    9.     public bool checkParticles = true;
    10.     public bool checkPhysics = true;
    11.     public float physicsDistance = 1000.0f;
    12.     public float defaultSleepThreshold = 0.14f;
    13.     public GameObject trailRenderer;
    14.  
    15.     private float distanceSqr;
    16.     private float physicsDistanceSqr;
    17.     private Object[] objects;
    18.     private static List<Object> gameObjects;
    19.     private static List<Object> physicsObjects;
    20.     private static ParticleSystem trailSystem;
    21.     private ParticleSystem.Particle[] particles;
    22.     private ParticleSystem.EmissionModule emissionModule;
    23.  
    24.     [HideInInspector] public Vector3 absolutePosition;
    25.     [HideInInspector] public Vector3 worldOffset;
    26.     [HideInInspector] public bool originChanged = false;
    27.  
    28.  
    29.     void Start()
    30.     {
    31.         distanceSqr = Mathf.Pow(distance, 2f);
    32.         physicsDistanceSqr = Mathf.Pow(physicsDistance, 2f);
    33.  
    34.         if (collectObjectsOnce)
    35.             CollectObjectsOnce();
    36.  
    37.         if(trailRenderer != null)
    38.         {
    39.             trailSystem = trailRenderer.GetComponent<ParticleSystem>();
    40.  
    41.             if (particles == null || particles.Length < trailSystem.main.maxParticles)
    42.                 particles = new ParticleSystem.Particle[trailSystem.main.maxParticles];
    43.  
    44.             emissionModule = trailSystem.emission;
    45.         }
    46.  
    47.         absolutePosition = transform.position;
    48.     }
    49.  
    50.     void LateUpdate()
    51.     {
    52.         ManageFloatingOrigin();
    53.     }
    54.  
    55.     public void CollectObjectsOnce()
    56.     {
    57.         gameObjects = new List<Object>();
    58.         gameObjects = FindObjectsOfType(typeof(Transform)).ToList();
    59.  
    60.         if (checkPhysics)
    61.         {
    62.             physicsObjects = new List<Object>();
    63.             physicsObjects = FindObjectsOfType(typeof(Rigidbody)).ToList();
    64.         }
    65.     }
    66.  
    67.     private void ManageFloatingOrigin()
    68.     {
    69.         originChanged = false;
    70.         Vector3 cameraPosition = transform.position;
    71.         absolutePosition = transform.position + worldOffset;
    72.  
    73.         if (cameraPosition.sqrMagnitude > distanceSqr)
    74.         {
    75.             worldOffset += transform.position;
    76.             originChanged = true;
    77.  
    78.             if (collectObjectsOnce)
    79.             {
    80.                 foreach (Object o in gameObjects)
    81.                 {
    82.                     Transform t = (Transform)o;
    83.  
    84.                     if (t.parent == null)
    85.                         t.position -= cameraPosition;
    86.                 }
    87.             }
    88.             else
    89.             {
    90.                 objects = FindObjectsOfType(typeof(Transform));
    91.  
    92.                 foreach (Object o in objects)
    93.                 {
    94.                     Transform t = (Transform)o;
    95.  
    96.                     if (t.parent == null)
    97.                         t.position -= cameraPosition;
    98.                 }
    99.             }
    100.  
    101.             if (checkParticles && trailRenderer != null)
    102.             {
    103.                 //emissionModule.enabled = false;
    104.  
    105.                 int liveParticles = trailSystem.GetParticles(particles);
    106.  
    107.                 for (int i = 0; i < liveParticles; i++)
    108.                     particles[i].position -= cameraPosition;
    109.  
    110.                 trailSystem.SetParticles(particles, liveParticles);
    111.  
    112.                 //emissionModule.enabled = true;
    113.             }
    114.  
    115.             if (checkPhysics && physicsDistance > 0f)
    116.             {
    117.                 if (collectObjectsOnce)
    118.                 {
    119.                     foreach (Object o in physicsObjects)
    120.                     {
    121.                         Rigidbody r = (Rigidbody)o;
    122.  
    123.                         if (r.gameObject.transform.position.sqrMagnitude > physicsDistanceSqr)
    124.                             r.sleepThreshold = float.MaxValue;
    125.                         else
    126.                             r.sleepThreshold = defaultSleepThreshold;
    127.                     }
    128.                 }
    129.                 else
    130.                 {
    131.                     objects = FindObjectsOfType(typeof(Rigidbody));
    132.  
    133.                     foreach (Object o in objects)
    134.                     {
    135.                         Rigidbody r = (Rigidbody)o;
    136.  
    137.                         if (r.gameObject.transform.position.sqrMagnitude > physicsDistanceSqr)
    138.                             r.sleepThreshold = float.MaxValue;
    139.                         else
    140.                             r.sleepThreshold = defaultSleepThreshold;
    141.                     }
    142.                 }
    143.             }
    144.         }
    145.     }
    146. }
    147.  
    148.  

    Additions are:
    • Trail Renderer support (only one for this script)
    • Collecting objects once at start suitable if there are no procedurally generated content in scene
    • Absolute Position as a Vector3 to preserve unoffset position translation
    • Origin Changed as a boolean to callback whenever the world has been offset
     
  33. llMarty

    llMarty

    Joined:
    Dec 14, 2014
    Posts:
    33
    Thank you for sharing this, it really helps!
     
    TerraUnity likes this.
  34. awesomedata

    awesomedata

    Joined:
    Oct 8, 2014
    Posts:
    1,419
    I've been preaching this for nearly a year or more.


    I mentioned this to @willgoldstone at one point. He responded rather clearly that Unity aims to support large worlds in 2020, though I don't know specifically what "large" means to Unity in terms of editor tool support since I've heard no concrete plans for "floating origin" support in the editor, and none of the SceneVis team (for example) seem to think in-editor visibility of far away areas of a huge world is a critical task to be discussed.

    I beg to differ.

    We have the mysterious new "Environment" system upcoming that has a "layers" concept, but as far as I understand it, this is still just heightmaps (which is still just INSANE in 2020, I might add). No ability to setup an array of tiles, sculpt them as a mesh in something like Blender/Zbrush (i.e. holes/caves overhangs), reimport it, then having the new mesh sit firmly planted at a 10000-15000 meter position in the world. Without jitters/artifacts from lighting/animation. Then, using editor tooling, sculpting slabs of geometry for very distant buildings or other landscape details via Probuilder (or other assets) at a 5000+ meter distance using an asset like Snapcam to zip around the world instantly to tweak it by hand, having the floating origin be taken care of for me by the Editor itself -- something akin to how it's being done with Virtual Texturing, except I don't think anyone is currently thinking through the whole workflow situation quite this deeply.

    The editor coordinates themselves being a pivot point for multi-departmental tools (and future toolsets) is kind of a new road -- However, it is also essential and critical to get this right from the outset. For example, it's already a bad start when I know SceneVis isn't doing anything to mitigate the inevitable visibility issues that will arise with huge coordinates for object/entity locations in open worlds, even with the task of gameobject/scene "visibility" as their core principle. The new Blender-like "Collections" system they're working on happens to be about visibility, but it overlooks the basics of what that "visibility" needs to look like in a 2020.x release focusing on large worlds. Because of this, I'm not convinced the design work has been laid out across the departments at Unity to take on a feature of this magnitude (and the implications it has) -- though I could be wrong. I would love to be wrong. @Unity, please tell me I'm wrong?
     
    Last edited: Jan 6, 2020
    NotaNaN likes this.
  35. awesomedata

    awesomedata

    Joined:
    Oct 8, 2014
    Posts:
    1,419
    Also, some highlights of this thread (in case anyone at @Unity wants to take a peek) since they sum up our open world issues nicely:



    These quotes essentially sum up the major hurdles I face everyday.
     
    NotaNaN and Marcos-Elias like this.
  36. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    As this topic has been bumped, it's probably best to just make a game like this in ECS/DOTS because it's a trivial few lines of code to teleport the entire universe at very little cost for origin shifting. It makes everything even easier and higher performing. Plus there are no parts of DOTS which would get in the way.

    In regular Unity you have many more problems because there is a significant performance cost. When dealing with these scales you would want DOTS by default anyway. Who would be silly enough to attempt it with regular mono?
     
    Marcos-Elias likes this.
  37. Marcos-Elias

    Marcos-Elias

    Joined:
    Nov 1, 2014
    Posts:
    159
    The "problem" is that DOTS is a radical change, lots of new things must be learned, there are no course or high detailed documentation about everything yet... DOTS is almost a completely new engine.

    And it is changing at every update, for the better, of course. But it's still immature, work in progress technology. Also most of the current engine features do not work well with it, we will see a change over the next two to five years, not right now...

    I think that it could be simpler exposing the shfitOrigin function from PhysX like Unreal did :p
    Just move normal gameObjects by setting their transforms positions, and physics objects (those with colliders) with shiftOrigin. This should not be that difficult to do in the engine source code, but Unity devs seems to completely ignore this ready to go approach :(
     
    halley, recon0303 and Leniaal like this.
  38. awesomedata

    awesomedata

    Joined:
    Oct 8, 2014
    Posts:
    1,419
    This is interesting, and it is something I've considered theoretically, but my question always ends up being about the things we can't easily touch -- i.e. What about the physics-world/gameplay-colliders/lightmapping-baking/occlusion-culling?

    Unless I've missed something, there really are no examples out there (that I know of) dealing with these issues in DOTS.


    I agree with you about wanting to use DOTS for this kind of thing, but what would shifting all the gameobjects at once look like in a DOTS-based world with physics/culling/lightmapping/etc.? -- It's been a while since I've brushed-up on my DOTS scripting since I've been focusing on World Building, so a refresher might be in order. I've looked extensively at the demo for MegaCity and its "subscenes", so I'm not totally out of the loop. However I've not been able to make the leap to shifting the world around from what I saw there. Any ideas or hints?
     
    NotaNaN likes this.
  39. recon0303

    recon0303

    Joined:
    Apr 20, 2014
    Posts:
    1,634

    old post, but this is something I have asked for , for many years now...I worked in many engines over the last few decades, and this I feel is not to much to ask....expose this.... I know in UE, it takes me under 20 mins to handle all of these problems...... Uningine now free, but the floating point is not, but even then coding it, is so easy, my grandma can program it..... in the free version....

    Unity should just expose this, it won't fix all issues, but it would help a lot... I have programmed floating point issues , among others.... not to bad for experienced users, but not everyone can do this and I get atleast once a week someone wanting to know how, or struggling... So Unity just expose this, so it helps users, prolly the easiest thing to do...
     
  40. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,295
    I guess it'll all come with the new environment system which won't happen before Unity 2021.
     
  41. awesomedata

    awesomedata

    Joined:
    Oct 8, 2014
    Posts:
    1,419
    I'm not sure this is the case.

    From everyone I've talked to at Unity about this (and I have been adamant about it), the new "environment system" is simply a "layer-based" (erg.. heightmap) system that combines terrain tools/toolbox into it. -- That's it.

    That being said, @Joachim_Ante has mentioned once or twice that Unity plans on doing something with floating point (by "making it easier to handle floating origins" were what I remember off the top of my head as his words).


    He, however, did not mention the floating origin in relation to dynamic HLOD (i.e. MegaCity), Imposters, or LOD (in general), and he did not specify the environment system as the "home" for such an improvement.

    Honestly, a legit "environment system" should include things like these -- and not limit the concept of "environment" to heightmap-based meshes. After all, a topdown game would not need such a limitation, as it doesn't do draw distance, and height data would be (mostly) irrelevant. The streaming concept, however, would remain as such.


    I suggested an "S(M)RP" pipeline in the Workflow Study thread -- This would allow you to integrate scriptable LOD, HLOD (and potentially account for floating origin) in the RENDERING portion of the pipeline -- instead of having to rely on the ('dumb') mesh-renderer component. This would allow for fancy shading/fading-in/out between LOD levels, possibly a better "stacked" camera workflow, visibility controls for mesh rendering, etc. -- not to mention handling complex HLOD setups (such as floating-point and streaming mesh-based worlds -- not limiting them to heightmaps).


    Any new information from @Unity about the size/scope of the "environment system" would be quite welcome.

    But as of right now, I've gotta bust my own solution for all of this (fairly basic stuff in other engines) myself. However, I'm not knocking Unity for trying to be more flexible -- but taking my considerations here (and my offer to be involved in the details of an implementation like this, including UX/UI), would really benefit them (both company and engine) in a LOT of ways (imo).
     
  42. AndreiMarian

    AndreiMarian

    Joined:
    Jun 9, 2015
    Posts:
    77
    Who would prefer a workaround over a solution?

    Floating point problem:
    Game engines are all made with an absolute coordinates system in mind. But maybe it doesn't need to be like that. I'm not arguing that it has to be a relative one. Because other issues arise from this, like calculating the relative position between two unrelated objects means calculating vectors relative to other mediating objects, which is bad again.

    What I do argue is: did you ever think about floating point being bad for game engine worlds in the first place? Why is it even used?
    It's a type conceived to be suited for low values high precision case or for large values (low precision) case. Notice the "or". Using it simultaneously for both cases is plainly wrong. 10 decimal precision near origin is a terrible waste when you only need 2. Only to suffer at longer range.
    Why again isn't a fixed precision type used? I say it's the headache free, even computationally faster, solution. You need 2 decimal places? Treat the unit as cm instead of m. There, done. You need to account for rounding errors? Use the int scale corresponding to additional 2, or 4 or whatever decimal places fixed point. Your choice plus it's consistent throughout the world. Plus it gives you a larger world, as you'll see below.

    A float can represent integers exactly in an interval of
    33,554,432‬ (± 16,777,216) whereas an int gives you for the same 32 bits 4,294,967,295 (-2,147,483,648 to +2,147,483,647).

    Using double instead of float to extend the unbuggy range would get you to ± 9,007,199,254,740,992. But then why not using long (64 bit int) which gives you ± 9,223,372,036,854,775,807 (~1000 times more real estate)? Again, with an easier burden on the cpu bonus.

    Well, ideally you'd want to allocate an arbitrary number of bits for the type but until there we can simply work with int.
     
  43. awesomedata

    awesomedata

    Joined:
    Oct 8, 2014
    Posts:
    1,419
    I like where you're going with this. Sadly, I think Unity's problem is the fact that its internal architecture simply isn't built to handle memory referencing and positioning in any sort of efficient way. This would likely need a little breakdown moment at the start of each frame -- and whether that affects graphics and positioning independently or simultaneously is the big problem (and should probably be better determined on a per-game basis -- rather than as a general, global, rule for all of our game projects).

    A "real" position and a "relative" position really should exist for all objects, updated once per frame, with the most "accurate" position being the "relative" one. Hell, Sonic the Hedgehog did this kind of positioning calculation way back on the Sega Genesis for its 360 degree math on 16 bit hardware to determine the exact pixel it was on using a resolution of 4x4 pixel space for collisions, on 8x8 tiles, combined into 32x32 (and variations of that -- i.e. 32x64 tiles, or any arbitrary size above that), based solely on powers of two.
    The fact that Unity cant (or doesn't) bother to do "relativity" this way is a bit of a lack of foresight imo. :(



    Handling terrain automatic LOD generation this way (based on tiled values) would also be of a HUGE benefit to people who simply can't afford to calculate and build general-purpose LOD systems for open-world games on their own.
     
    AndreiMarian likes this.
  44. AndreiMarian

    AndreiMarian

    Joined:
    Jun 9, 2015
    Posts:
    77
    Apart from the math methods having to be "ported" from float / double to int / long I don't think there would be anything else to do. I'm not sure about CPU to GPU communication though.
    This would have the potential of supporting really infinite worlds, for those who would need something larger than a light-year.
    Totally agreed.
     
    Last edited: Dec 31, 2020
    awesomedata and amisner2k like this.
  45. amisner2k

    amisner2k

    Joined:
    Jan 9, 2017
    Posts:
    43
    Yeah, I have a feeling this would be one of the biggest challenges to this approach, likely requiring significant changes to the engine internals to accomplish.

    I loved where you were going with this because it'd be awesome, but this would likely require a brand new 3D engine developed from the ground up to be feasible....trying to change from floats to ints in an already well-established engine like Unity seems highly unlikely.

    I know it's not a simple matter of just changing the data types. Two of the major data structures I know of that go into getting pixels on screen involve floats: matrices and vectors and I don't know how big of a lift it would be to convert those into using ints as their underlying types, but I imagine it's a big one. I don't even want to think about how they'd make passing in data to shaders (vertex positions for example) work. :p

    There could even be limitations in the various graphics APIs such as DirectX, OpenGL, and Vulkan that preclude any of this.

    Anyway, I'm glad you brought this idea up because it's a good thought experiment and worthy of exploration. Will likely need somebody to try out a prototype engine to see if this could even work at all. ¯\_(ツ)_/¯
     
  46. deus0

    deus0

    Joined:
    May 12, 2015
    Posts:
    256
    Hey, I'm not sure if going purely to doubles will fix it. It will certainly increase the resolution. I also get jittery camera once i go past the 999 point, and gets worse at 9999ish point. I kept thinking it was my codes fault hah, until i started to try solve it again. I'm making a voxel game so it's kinda big deal to fix it.

    A good video about it. Flipping everything around the origin might be the best solution. Surely annoying to do but it's about precision and the matrix and yeah. Check out that video all.
     
    AntonioModer and PutridEx like this.
  47. cosmochristo

    cosmochristo

    Joined:
    Sep 24, 2018
    Posts:
    250
    Hi @Marcos-Elias, you have posed the question as either origin-shift floating origin or double precision.
    I fully understand that you would be frustrated after trying for years - as I was in the later 90s-early 2000s.

    Floating point issues nagged at me so much I had to solve it and eventually did my PhD on it. So, there is a third option and that is continuous floating origin (camera stays at the origin) and some co-techniques and optimisations. Despite a great deal of misunderstanding about performance, physics and precision, this works efficiently and with good performance. And an example of collision physics with a stationary spacecraft "flying" over terrain is at the beginning of the video linked below.

    Origin-shift is not a general solution because it does not scale in speed and it was always a hack because when you try to scale it in distance (and speed) you have to pick a threshold which suits one situation and then find it is too big for another. If you increase the threshold you get more jitter and if you decrease threshold it fails at a lower speed.

    Double precision helps but does not solve the general problem either: it allows greater scale but does not minimise jitter.
    I tried pushing continuous floating origin as far as I could go and made a continuously navigable space from Earth to Pluto. In that particular case I went the unnecessary extra step of using nothing but single precision partly because so many people believe it can't be done, and have told me I can't do it, and partly to fully stress test the design and algorithms.

    The video of CFO, Earth-Pluto is linked below. The only thing the "gates" do is adjust speed and orientation, there is no portalling/jumps like in Outer Wilds and other games.

    I have a unity asset - a framework - for this if you are interested.

     
  48. cosmochristo

    cosmochristo

    Joined:
    Sep 24, 2018
    Posts:
    250
    I'd like to see a good writeup of how this can be designed in DOTS, is there one?

    I found this performance cost meme to be a myth. continuous floating origin performs very well in standard unity/URP - for 2018 at least. The only case where I agree with you is the cost of implementing the threshold based origin shifting and those implementations that loop through all objects and physics each shift. I mean, why do that when you can just move a transform(or few) above them?
     
    Marcos-Elias likes this.
  49. Well, that's true as long as you have a basically empty world as in the video above. This "continuous" technique won't work in a busy land-based case.

    Here is a skeleton of a Job-based movement script. It isn't working, but close, just fill up with data and check if it is working for you.
    Code (CSharp):
    1. using Unity.Collections;
    2. using Unity.Jobs;
    3. using Unity.Mathematics;
    4. using UnityEngine;
    5. using UnityEngine.Jobs;
    6. using Random = UnityEngine.Random;
    7.  
    8. public class FloatingOriginJob : MonoBehaviour
    9. {
    10.     // -----------------------------------------
    11.     public int Count = 6000;    // How many spheres you want to spawn
    12.     public int SpawnRange = 5000; // The range from -SpawnRange to SpawnRange
    13.     private Transform[] _transforms;
    14.     private Vector3[] _targets;
    15.     // -----------------------------------------
    16.  
    17.     private TransformAccessArray transAccArr;
    18.     private NativeArray<Vector3> nativeTargets;
    19.  
    20.     private JobHandle jobHandle;
    21.     private Camera mainCamera;
    22.     private float3 tempVector3;
    23.    
    24.     private float3 scale = new float3(10f, 10f, 10f);
    25.  
    26.     public struct MoveToTargetJob : IJobParallelForTransform {
    27.         public NativeArray<Vector3> Targets;
    28.         public float3 moveBy;
    29.         private float3 _tempFloat3;
    30.         public void Execute(int index, TransformAccess transform)
    31.         {
    32.             _tempFloat3 = transform.position;
    33.             _tempFloat3 -= moveBy;
    34.             transform.position = _tempFloat3;
    35.         }
    36.     }
    37.  
    38.     public void Start() {
    39.         mainCamera = Camera.main;
    40.  
    41.         transAccArr = new TransformAccessArray(Count);
    42.         nativeTargets = new NativeArray<Vector3>(Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
    43.  
    44.         _transforms = new Transform[Count];
    45.         for (var i = 0; i < Count; i++) {
    46.             var obj = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    47.             obj.transform.localScale = scale;
    48.             obj.transform.position = new Vector3(Random.Range(-SpawnRange, SpawnRange), Random.Range(-SpawnRange, SpawnRange), Random.Range(-SpawnRange, SpawnRange));
    49.             obj.GetComponent<MeshRenderer>().material.color = Color.red;
    50.             _transforms[i] = obj.transform;
    51.         }
    52.         _targets = new Vector3[_transforms.Length];
    53.         for (var i = 0; i < _targets.Length; i++) {
    54.             _targets[i] = new Vector3(Random.Range(-SpawnRange, SpawnRange), Random.Range(-SpawnRange, SpawnRange), Random.Range(-SpawnRange, SpawnRange));
    55.         }
    56.     }
    57.  
    58.  
    59.     public void Update()
    60.     {
    61.         var mainCameraTransform = mainCamera.transform;
    62.  
    63.         // here move the Camera/Player
    64.         // Calculate the distance to move the objects
    65.         // feed it into the job
    66.        
    67.         transAccArr.SetTransforms(_transforms);
    68.         nativeTargets.CopyFrom(_targets);
    69.  
    70.         var job = new MoveToTargetJob
    71.         {
    72.                 DeltaTime = Time.deltaTime,
    73.                 Targets = nativeTargets,
    74.                 moveBy = tempVector3
    75.         };
    76.         jobHandle = job.Schedule(transAccArr);
    77.     }
    78.  
    79.     private void LateUpdate() => jobHandle.Complete();
    80.  
    81.     private void OnDestroy()
    82.     {
    83.         transAccArr.Dispose();
    84.         nativeTargets.Dispose();
    85.     }
    86. }
     
    Marcos-Elias likes this.
  50. Marcos-Elias

    Marcos-Elias

    Joined:
    Nov 1, 2014
    Posts:
    159
    That would be awesome! Could you share it with the community, or is it private or paid?
    I don't want to be negative, but I am afraid that this solution won't work for larger landscapes like a city with a lot of roads and moving vehicles and people... At least not if we rely on PhysX. To make it work probably a custom physics engine would be necessary. After 10km objects will lose precision in PhysX, the default solution for physics in Unity.

    This is why I ask for Unity to expose the shiftOrigin function, it is already there but they completely ignore it. :(

    Code (CSharp):
    1. PxScene::shiftOrigin(const PxVec3& shift)
    https://docs.nvidia.com/gameworks/content/gameworkslibrary/physx/guide/Manual/OriginShift.html

    It seems the best workaround for most games, Unreal uses it and it works well for most situations.

    IMHO the complete migration to DOTS and Unity Physics seems to be something for the future, not completely safe for now. It misses tutorials, templates and stability sometimes. We don't have a huge amount of third party tools or assets already to work with that, like the awesome Vehicle Physics Pro.
     
    Last edited: May 14, 2021