Hello, I'm making a space game and needed higher precision than Vector3 to represent the vasty nothingness of space so decompiled Unity Vector3, Vector2 and Mathf and converted them to double precision. Most methods were relatively straightforward to convert (they were converting floats to doubles internally to do the math). There's a few cases where the method called an internal Unity function, in those cases I've wrapped the original function. I checked with Unity if it was okay to distribute this and they said it was, so if you need higher precision you can grab the files from here: https://github.com/kohlditz/vector3d
How do I go about incorperating these files into unity? Also, does it circumvent the float precision problem in the inspector?
Make new scripts in Unity, then copy and paste. No, since these are custom structs and therefore can't be used in the inspector. --Eric
Hey, this is a very big interessing script. But now, I don't know where I need to add the script. I've tested in camera (also tried the moving part), and it say "Can't add script behaviour Vector3d. The script needs to derive from MonoBehaviour !". So, I guess it's because of "using System". But what now ? :s. Thanks in advance. :=)
Thanks. Where I can see the changes ? (And same problem ingame) http://img95.xooimage.com/files/f/4/b/sans-titre-421a7a8.jpg
Ah okay thanks. I understand now. (Sorry, I'm french. :3) And now I see Vector3d I didn't see it before, I know now.
Thanks for making that publicly available. However I'm curious - How do you plan to get around the problem of physics precision in your game?
curious: what's the point? (if you'll excuse the pun won't the resulting calcs be cast back to float in the bowels of the engine anyway? until UT uses doubles internally, this will always be an issue AFAIK..
Awesome, thank you. Do you have a suggestion on approach for implementation? I.e. Referencing the double precision coordinates to the float precision that Unity Supports? So when getting to x, switch to a local precision?
Man, you're great! Double math it is what I need! Now I'm learning Unity and C# (very basicaly, started few days ago), but far away I have planning to create space sim. It will help me a lot, I hope
Just one more thing though. What about rotations? Quaternion doesn't seem to be working with doubles, while conversing from double to float just to make a rotation wit Q. doesn't sound great either. Any thoughts?
So I just need to replace Vector3 , with Vector3d ? Could you post some example scene ? ( Even simple moving Cube ) Sorry , I am graphics designer , not programmer .
It's really only of use to programmers. You can't just replace Vector3 with Vector3d since everything in Unity itself uses Vector3 and that can't be changed. Only your own code can use Vector3d. --Eric
One example would be giving your GameObjects something like a "dpTransform" which stores the position with double precision. Now, instead of manipulating the transform directly, you would always manipulate the dpTransform which, after it gets manipulated, updates the transform. That way you'd prevent data-loss when something happens very far away. Sure, the engine would still give you problems, but your logic would stay reliable. The dpTransform would store where the GameObject is supposed to be. Example situation where this would come handy: Spoiler Simulation very far away: Move GameObject x 10 cm to the right. Problem: You're so far away that movement happens in 1 m jumps. Solution: Whenever the player moves too far away from the center of the map, everything is moved so that the player is at the center again. Say you go forward, when going over a "border" everything is moved backwards so the stuff behind you looses precision, while the stuff in front you has its precision increased. How can this work? Our dpTransform stores the accurate data which is used to restore the transforms. If there was no dpTransform we wouldn't have been able to store the information that the GameObject is now 10 cm more to the right.
In my case,i have a transform.position for a game object.I am not able to use transform.position as it supports only Vecotr3 due to which i get an error.How do i rectify this?
You don't; Unity only uses single-precision floats for Vector3 and this can't be changed. Transform.position only uses Vector3 and that can't be changed either. There seems to be some repeated confusion in this thread: the double-precision Vector3 is a custom struct and can't just be plugged into Unity as a substitute for the standard Vector3. See TheSniperFan's post for an example of how you might actually use it. --Eric
If only I could actually replace the original vector3 with this... I'm struggling with precision errors for my f16 sim. I have the camera inside the cockpit, but when I fly a few thousand meters, it starts shaking like hell due to precision errors
Use this instead: http://wiki.unity3d.com/index.php?title=Floating_Origin We use a modified version of this and move over a 100,000 units with it.
Im afraid you need to write your own Vector3D (double) physics engine . It is not that difficult , thou but in order to get any decent framerate it needs to be coded natively on the target platform. It took us best part of a year ! Indeed , our physics plugin enables physics on Float , doubles , or even quad_precision. In www.space-simulator.com we do have actual planetary distances with a sub-milimeter accuracy . and running decently on iOS
In my opinion, there seems to be a lot of misunderstandings in this thread. Just as with any physical medium, you will always be limited to what that that medium can actually represent, be it printers, monitors or unity3d. You might be able to minimize float creep, but you will never be able to get rid of it completely because as soon as you go to set a position or check a boundary or work with audio with your nice precise calculations, your double will get downcast to a float, losing whatever precision you gained. If unity3d used doubles natively internally, you'd ultimately still have issues since the other physical limitations would eventually kick in. IE: how floating points are handled by the different OS's, platforms, processors, graphics cards, monitors, DSP's etc etc. Cast this to a float: 0.56622885888511233135576443 For graphics, it will ultimately come down to rounding rules since the smallest unit of measure will be a single pixel, which is an int. You can't draw 0.52245654 of a pixel. It's either on to some value or off to a value. And even if you COULD get the card to take it, the monitor would never be able to display it properly, at least not with today's technology. Sure, there are lots of hacks and approximations, AA is one of them. Trilinear, bilinear filters are examples of others. Now, that all said, WOULD using doubles internally increase precision? Sure. It would lessen the float creep considerably, but even with doubles, you eventually end up at the same spot, if you'll excuse the pun. Just to drive the point home (ha!), Google how floats are stored, represented and processed just in the different languages, C++ vs .net.
Thanks for this - I was about to write my one (didn't think about decompiling it) so you saved me a ton of time. I also added this in to the bottom, fimple code, but could save others that don't know about casting some time. public static implicit operator Vector3d(Vector3 v) { return new Vector3d(v.x, v.y, v.z); } I didn't read everything, so maybe you covered this - but people have been questioning the value of this - You don't need precision for display, but you do need it for calculations. For example I am using it to calculate real world gravitational rotations of planets around a sun using relativity, - then during LateUpdate I move the model to correspond a point that is 10% of the actual value (models are also not to scale). You can't do this with a float because the outer-solar system is to vast - a double can easily do this and with much more precision.
Also, the const values at the top of Mathd should be updated to double point precision: public const double PI = 3.14159265358979; public const double Infinity = double.PositiveInfinity; public const double NegativeInfinity = double.NegativeInfinity; public const double Deg2Rad = Mathd.PI / 180.0; public const double Rad2Deg = 180.0 / Mathd.PI; public const double Epsilon = double.Epsilon; the kEpsilon value at the top of the Vector2/3d should probably be updated too but I am not sure what those values would be.
no example project is needed, this isnt replacing the Vector3 unity already has. Its just a Vector3 stuct with double precision. You can use this if you need your own logic to run in double precision, just remember it will need to be cast down to float precision when used with unity. It mirrors the usage of the build in Vector3 and Vector2, just using Vector3d and Vector2D, and MathD instead of MathF. Also a lot of what is on the Mathd class overlaps the float math stuff that is already part of .net in System.Math
This whole system is tricky to program with floating point ect., but for huge open worlds it works pretty well. If you are using Unitys pathfinding system you might be better off making a scaled down version of your map so your AI finds its way across the map, but use a custom local avoidence instead. All the Physics you need is some collision check and raycasting system using doubles. At least thats how I implemented it.
@sniperfan Great post! So would the dpTransform actually do the moving of the object to double precision when the object is in front of the camera, or would it send the double-precision location to somewhere else and that would do the moving? If the latter case is true, then wouldn't you lose the double-precision when trying to update the transform's position? I'm sorry if these are stupid questions, I guess I'm not used to using anything but Vector3s and transform.position to move an object.
Necropost here; This was built to handle an internal model of world state, so this is purely for data structures internal to the world state. The mirroring of vector3 etc is for convenience, the expectation is you manipulate the model at double precision; and then can easily cast to single precision to generate the scene to render. Some of the functions are dodgy because a) I didn't need them, b) I didn't understand the math well enough and c) c# is not a language I particularly know or use This is just a decompile of the unity library with some cleanup, it's in the public domain so use how you see fit. And to echo some comments above, for it to be useful; you'd typically use a floating origin and then scale things to a sensible size so you can leverage the z-buffer. For an example of what this is attempting to solve see these youtube videos. a) Two moons orbiting Jupiter at scale using single precision floats. Notice the jitter. b) Basically the same scene with double precision, the orbits are much smoother. c) Technique ported to Unity, all objects are represented at 1:1 scale internally
Thanks for posting this kohlditz. I would like to do something like this and modify to use continuous floating origin so I can make some comparisons (accuracy and performance).
Working on the same stuff for a VR game. Done a lot of orbital mechanics on this one and the complexity is still unfolding.. wooo heed the KRAKEN!
For a different perspective on precision, this full scale example traverses a region from z= < +10^7 to z= > -10^11, all in single precision. As @kohlditz says, floating origin is required for very large spaces and full scale. However, it is not always necessary to use double precision.
Because of point 1i of the code of conduct of this forum. Necro-posting isn't really welcome in the majority of forums on the internet. In rare cases a necro-post may be justified when actual new information is added. However in most cases the poster usually violates point "1g" of the code of conduct as they try to hijack the thread. ps: @MelvMay I noticed the code of conduct still has a link to Unity Answers at the very bottom. I think it's time to replace that link.
Forum necroposting is frowned upon due to most forum software pushing an updated thread to the top of the first page. An exception is made if the post is adding content of value but in most cases (like this one) nothing of value has been added and now everyone who visits this section has to process that the thread isn't actually recent. To work around this problem many forums have some way of leaving an indication that the content was helpful to you. Ours is a simple "Like" that you can click and it will inform the person who created that specific post that you liked their response.