Search Unity

Official Unity.Mathematics available on github

Discussion in 'Entity Component System' started by xoofx, Apr 10, 2018.

Thread Status:
Not open for further replies.
  1. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    838
    Its not compatible at all, its not the same language.
     
    dadude123 likes this.
  2. tspk91

    tspk91

    Joined:
    Nov 19, 2014
    Posts:
    131
    Is there any performance benefit to using Unity.Mathematics in "normal" main thread code? I guess the SIMD optimizations only work with the burst compiler which requires jobified code, but maybe it is still faster than Mathf?
     
  3. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    IL2CPP in some cases also generates better code using Unity.Mathematics, but primarily the library exists for two reasons:
    1) More consistent math library allowing for cleaner code
    2) Optimizations possible with burst compiler
     
    LogicFlow and Cynicat like this.
  4. ChrisJohnson

    ChrisJohnson

    Joined:
    Feb 20, 2013
    Posts:
    64
    I’m wondering if you are going to add a way to do implicit conversions between
    Vector2Int, Vector3Int and int2, int3. This would make it easier to use the new math library with some existing components. For example the Grid component takes in a Vector3Int in the CellToWorld Method.

    Right now math_unity_conversion.cs has a way to do this with floats and Vectors, but not ints and Vectors.
     
  5. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    Well, `asint` appears to be not a special case of `asin` but rather “as int”. And instead of C# `AsInt`, or Java(Script) `asInt`, or C++ `as_int`, they chose HLSL (?) `asint`. But not everywhere, since `lengthSquared` is still in JavaScript convention. Oh, `smoothstep` is not. `lessThanEqual` again... `unpackhi`... Wow, `fold_to_uint`!

    I see no consistency here. Looks very ugly and unprofessional. I'd rather stick to System.Numerics.

    Keep calm & avoid Unity APIs.
     
    Last edited: Aug 8, 2018
  6. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    I'm happy that @mike_acton was happy. Just a bit unusual that priority in usability of API is not for actual users but rather for person who is porting code, so he could just do copypasting instead of actual porting.
     
  7. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,778
    I must agree on that part, that lack of consistency is mind boggling in Unity API. But not something can be avoided easily. Surly Unity can imply naming convention to their employees. Or are this naming simply copied from x party sources?
     
  8. CDF

    CDF

    Joined:
    Sep 14, 2013
    Posts:
    1,311
    Is the noise library ready to use here? I get the error "Unable to convert bool4 to float4" in "common":

    Code (CSharp):
    1. static float4 grad4(float j, float4 ip)
    2. {
    3.     float4 ones = float4(1.0f, 1.0f, 1.0f, -1.0f);
    4.     float3 pxyz = floor(fract(float3(j) * ip.xyz) * 7.0f) * ip.z - 1.0f;
    5.     float  pw   = 1.5f - dot(abs(pxyz), ones.xyz);
    6.     float4 p = float4(pxyz, pw);
    7.     float4 s = float4(lessThan(p, float4(0.0f))); //Unable to convert bool4 to float4
    8.     p.xyz = p.xyz + (s.xyz*2.0f - 1.0f) * s.www;
    9.     return p;
    10. }
    I assume that converting a bool to float would just be true = 1, false = 0
    Maybe float4 missing a bool constructor?
     
  9. stubbesaurus

    stubbesaurus

    Unity Technologies

    Joined:
    Oct 7, 2016
    Posts:
    3
    You are absolutely right. Somehow until now the Noise library has not been part of our testing procedure. This particular issue has been fixed locally and will be rolled out as part of one of the coming releases.

    To work around the issue you can replace the line with something like this for now:
    Code (CSharp):
    1. float4 s = select(float4(0.0f), float4(1.0f), p < float4(0.0f));
     
    CDF likes this.
  10. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    So what's the deal with the change of quaternion to Quaternion? I'm guessing/hoping this was just a localized bad decision that will get corrected. Given the number of potential conflicts that can happen when mixing old/new in the same files, makes this an area where just changing on a whim can have significant consequences. And the correct fix in user code depends a lot on whether this is a trend or just a mistake.
     
  11. slime73

    slime73

    Joined:
    May 14, 2017
    Posts:
    107
    I might be wrong, but it's probably because float2/3/etc are supposed to be fundamental base types, whereas Quaternion is a structure containing values that are base types but isn't one itself. That reasoning makes sense to me at least.
     
    LogicFlow and laurentlavigne like this.
  12. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Correct. That was our logic.
     
    LogicFlow and laurentlavigne like this.
  13. Sarah_Lee

    Sarah_Lee

    Joined:
    Jul 30, 2015
    Posts:
    6
    So, if that's the logic, why are the matrices (int4x4) low cases? They contain 'fundamental base type', no?

    If you guys already decided to be weird with this math lib, why not complete the 'total-a**' journey ( respectfully:) ) and call it 'quat' to fit with all the other weird ones.

    At least, with all math types in Non-C# styling, they will give people hint that those are 'special'.
    For example, there will a bit of method call overhead when run outside Burst/Job (ex: under Editor, debug mode).

    Also, if you take a look at (Unity.Mathematics.RigidTransform). Doesn't it looks like being implemented using two different Math frameworks? And that's how our code will look like also ...

    public struct RigidTransform
    {
    public Quaternion rot;
    public float3 pos;
     
    laurentlavigne, alexzzzz and RaL like this.
  14. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Fundamental base type isn't even a thing. This makes no sense.
     
    Nyarlathothep and Qbit86 like this.
  15. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    I'm going to make the argument that naming conventions are there largely to add consistency at the language level, not the library level. float3 is just another custom value type, it's no different then quaternion when you take it out of the context of the math library.

    This new direction seems a lot like the old one in terms of the higher level logic used. You are going for consistency within the context of Unity only. I think long term that's going to come back and bite you in unexpected ways.
     
    Qbit86 and alexzzzz like this.
  16. Usually I stand by Unity's decisions because usually they make sense.

    This one does not make sense. I really don't care about consistency, I don't care how the code look like, I have enough experience that I can read pretty much any code with relatively low effort.

    But, quaternion is just another base type in the sense float3 is. Either you sign that a value is base type in the sense of programming language (like int, float, etc) or base type on the logical sense (like float3 - one point in 3D space or quaternion - a rotation on a surface, of course in reality neither the float3 is just a position in space and the quaternions arent exactly rotations, but we use them here that way).
     
    laurentlavigne likes this.
  17. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,778
    I agree with @LurkingNinjaDev, since quaternions are just group/array of floats. just similar way, as float3, or float4. Nothing special about it. How the data store differ otherwise?
     
  18. slime73

    slime73

    Joined:
    May 14, 2017
    Posts:
    107
    My understanding is that float2/3/4 are not specifically vectors, they're SIMD types (which can easily represent vectors and quaternions, among other things). They aren't really the same as an array of floats.
     
  19. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Do you suggest quaternion should be lower case and things like RigidTransform, Bounds, Rect etc should be upper case?
     
    laurentlavigne likes this.
  20. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,778
    This would be my suggestion indeed.
    Also, as previously mentioned, while I haven't touched much of shaders, apparently quaternions there are in small cases.(?)

    As I said somewhere before, I like Quaternion in classic OOP with big Q, but perhaps I get use to. Similarly Vector.
    But in ECS, Vector is gone as such, taking place by float2/3/4. so for me, it would make sense, having quaternion small cased as well.

    At this point is hard for me to argue (not enough expertise), whether Quaternion (OOP) and quaternion (ECS), or Quaternion (OOP) and Quaternion (ECS) would have any great impact, or cause confusions. I think however, it is safer to decouple quaternion from OOP, by lowering case and avoid any potential collisions, when mixing ECS with OOP. For example in Hybrid ECS etc.
     
    laurentlavigne likes this.
  21. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    The fact that we have two math libraries is a temporary thing, or at least I would think it should be. So decisions on what is the right approach here should not really take that into account IMO.

    IMO having custom types that simply add to the names of built in types is kind of the root of the problem. We have proper names for those structures. Vector, Matrix, etc... I think it's shader languages that got this wrong not the rest of the programming world where linear algebra libraries have not taken the same route.
     
  22. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Hmm so actually it looks like shader languages do use vector and matrix, is the floatx just a unity thing in the shaders? Sorry not a shader expert here but glancing at HLSL and GLSL it seems they use vector and matrix.

    Edit. Ok so it seems HLSL does use floatx. Is that convention really of MS origin? Curious.
     
  23. Sarah_Lee

    Sarah_Lee

    Joined:
    Jul 30, 2015
    Posts:
    6
    First of all (sorry randomizing), 'RigidTransform' appears to be out of context under 'Unity.Mathmatics'.
    Isn't it Physics? --> Higher level context --> more friendly naming standard :)

    But, I do get your point. And here's my biased view.

    As Quaternion are heavy in IK/Bone anim (an core element of what people see on screen), my assumption is that
    Burst will optimize it to the same level as 'float4'. And that, the syntax "struct Quaternion { float4 value }"
    is primary to keep JIT world happy. Is that not the case? Is Burst optimization goal for Quaternion, the same level
    as RigidTransform? :-(

    In that, if we (external customer) implemented 'Quaternion' ourselves (using 'float4' running under Job+Burst), do we get the same performance as Unity's? Maybe unreasonable, but we would expect Unity's to be faster (closer to Burst)

    My biased view is that, it will be great for the framework to 'hint' us on data types are from
    the 'special Burst family'. And that, in turn, justifies the weird naming style you guys persist to have.
     
  24. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    What is right or wrong? I think for me it's natural and right to use Vector, Quaternion and I have done so in libraries that are not unity, so that is very common for me. I would simply use using correctly in the source and use namespaces.

    It's Unity's compiler, and there is a fantastic relationship with ms with visual studio, I have no concerns about confusing the two things. Any programmer... knows what namespaces are, and if they don't they will learn in a couple of minutes.

    So do the right thing, ignore history. If you don't do the right thing now, whatever that might be, you only delay the problem.

    I want performance by default not problems delayed! (I am jesting with that last line)
     
  25. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Burst knows what int1234, float1234 is. All methods dealing with floatN or intN on math are intrinsics that burst natively understands it and can do optimizations with that knowledge. From a compiler perspective they are truly native.

    Quaternion is not native, neither in HLSL nor in Burst. Currently floatNxN are also not native they are simply using floatN intrinsic functions. (Not aware of perf gains we would get by making them intrinsics)

    Quaternion is imply a struct containing float4, its internally implemented ontop of float4 API's. (Not aware of perf gains we would get by making them intrinsics)

    RigidTransform is Quaternion + Position

    Thats simply because its a very common concept and useful to have a common struct to pass that around. It has nothing to do with rigid bodies.


    Naturally, what is intrinsics or not in the burst compiler shouldn't drive what the naming conventions are. The naming conventions were chosen because it makes it more compatible with HLSL code. It means you can copy paste code between HLSL / C# and easily convert it. And because to me int1234 / float1234 feels like builtin types.

    The general conventions for how math library was chosen was based on HLSL generally because we found it to be a very good consistent easy to understand math library.
     
  26. pavelkouril

    pavelkouril

    Joined:
    Jul 22, 2016
    Posts:
    129
    As I said before; I don't mind float1234 or int1234 being lowercased, since it is consistent with "float" etc. (and is basically a data structure first and foremost, without any specific meaning; AFAIK float3 and others don't have stuff like length etc. defined on themselves anymore, right?); the same with floatXnX.

    As for quaternion, I feel it should be uppercased probably, since it isn't "just" a data structure, but has a specific "domain" meaning, if that makes sense. As for the inconsistency in the following case - it may look weird in the isolated use cases, but isn't that much different when you mix normal float and Vector3/custom struct already in the old Unity code anyways.

    Code (csharp):
    1.  
    2. struct Foo
    3. {
    4.    private float3 Position;
    5.    private Quaternion Rotation;
    6. }
    7.  

    What I do mind are the math functions; min/max/abs/etc. being lowercased, when it IMHO doesn't make any sense for them to be like that, since it breaks all the conventions C# has. :/
     
  27. rz_0lento

    rz_0lento

    Joined:
    Oct 8, 2013
    Posts:
    2,361
    What does the Rigid stand for in this context? When I noticed RigidTransforms I was puzzled why it had Rigid prefix if it's just a transform. I do get that you want to differentiate transform that solely exists in the math lib and transform that is moving objects in the scene but Rigid seems weird prefix for that (what exactly is rigid about it?)
     
  28. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,791
    I'm guessing it's the transform of the rigidbody.
     
  29. recursive

    recursive

    Joined:
    Jul 12, 2012
    Posts:
    669
    It's more likely derived from Rigid Transformation: https://en.wikipedia.org/wiki/Rigid_transformation. It's related to the concept of rigid body.
     
    rz_0lento likes this.
  30. Sarah_Lee

    Sarah_Lee

    Joined:
    Jul 30, 2015
    Posts:
    6
    Though I disagree with your naming philosophy, your hard works are very much appreciated.
    And thanks for responding to these annoying cosmetic push backs :)
     
  31. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    Fundamental types in .NET are named in PascalCase: `System.Int32`, `System.UInt64`, `System.Single`, `System.Double`, etc. And methods also use this notation: `Convert.ToInt32()`, `Convert.ToSingle()`.

    `float` and `int` are just aliases in some of .NET languages.

    And this logic was incorrect.
     
    Last edited: Aug 20, 2018
    BrokawayGames and Nyarlathothep like this.
  32. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    laurentlavigne likes this.
  33. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    Makes no sense to me:
    Code (CSharp):
    1. Console.WriteLine(typeof(ulong));                    // System.UInt64
    2. Console.WriteLine(typeof(float));                    // System.Single
    3. Console.WriteLine(typeof(Unity.Mathematics.float3)); // Unity.Mathematics.float3
    4.                                                      //                   ^ Why?
     
    Last edited: Aug 20, 2018
  34. korzen303

    korzen303

    Joined:
    Oct 2, 2012
    Posts:
    223
    Quick workaround
    Code (CSharp):
    1.  
    2. using quaternion = Unity.Mathematics.Quaternion;
    3. using Quaternion = UnityEngine.Quaternion;
    4.  
     
  35. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    Don't forget about System.Numerics.Quaternion
    :)
     
    Last edited: Aug 20, 2018
  36. recursive

    recursive

    Joined:
    Jul 12, 2012
    Posts:
    669
    The real solution to everyone's problems to simply get Microsoft add typedefs to C#. That way, burst-enabled types and Unity Engineers with C++/HLSL backgrounds can be happy, and .NET naming convention aficionados can have their cake and eat it too. Nothing could possibly go wrong, ever.

    Code (CSharp):
    1. typedef int4 Int32x4; // I am a genius.
    2.  
    3. typedef MonoBehaviour MB; // oh no!
     
  37. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,778
  38. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    We have discussed the naming of Unity.Mathematics internally and have decided the following:

    Unity.Mathematics package will be a small library made of intrinsic functions we use lower case convention there. It is the only place in Unity where we will do this. Unity.Mathematics will be focused on just the core functions.

    floatN, intN, floatNxN, , quaternion and math class with intrinsic functions. Those are lower case, matching HLSL conventions and generally how math looks looks like. eg. you can do this
    Code (CSharp):
    1.  
    2. using static Unity.Mathematics.math;
    3. value = sin(value);
    4.  
    We will remove Random, Noise, RigidTransform functions etc from the Unity.Mathematics and move it into the ecs package for now where we will start to build up useful higher level functionality like Plane, RigidTransform, intersection, geometry etc. That functionality will follow normal .NET coding conventions, just like ECS already does.

    This makes it so that we can get the Unity.Mathematics package to 100% complete faster, and it is better for us to iterate on higher level game code functionality in the Entity Component System repo / package. So they can't go out of sync.

    Apologies for the mis-step with quaternion.
     
  39. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    1) Doesn't matter, this is about CLS/CTS compliance, if you are concerned about accuracy of the wording.
    2) Whatever you call it, “float3 mimicing float” is inconsistent even within their own “Not-.Net”, since there is no “float” there anyway.
    3) HLSL/Python/Haskell/you-name-it conventions for types in .NET violate Principle of least astonishment.
     
  40. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
  41. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    It's a bit more then just about naming. In the new math library the idiom seems to be separate logic from data. So float3 is not a vector. There is nothing about it telling you it's a vector. But you can do vector operations on it via math.

    But along comes floatNxN. It mixes up logic and data and is not consistent with floatN. quaternion is another odd duck that follows a slightly different trend.

    Calling this consistent I don't know how you get there. Easy to use? I can accept that assuming a level of familiarity. I like floatN/floatNxN it's easy to read. But the separation of data/logic makes for a steeper learning curve, even if it is a small one.
     
  42. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    Moreover, Point3 is not a Vector3 algebraically, even if they have the same representation as Float3. APIs where points are distinct from vectors are cleaner and less error prone in use.
     
  43. xoofx

    xoofx

    Unity Technologies

    Joined:
    Nov 5, 2016
    Posts:
    417
    There is a message about the reasoning behind this choice. We are not going to change this vision. The scope and shape of `Unity.Mathematics` is now settled to what Joachim said here
     
    LogicFlow likes this.
  44. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    Thanks, we have already read it and discussed, why this reasoning is simply wrong.
     
  45. xoofx

    xoofx

    Unity Technologies

    Joined:
    Nov 5, 2016
    Posts:
    417
    Can you elaborate? Afair, there is currently not much logic in the floatNxN apart the operator overloading which is matching the expected operations on this types. Only the functions in math bring more logic. For quaternion, there are mainly constructors, which are mostly data that need to be expressed through some code "logic". Putting these common constructors into a different class just for the sake of following a separation between "logic" and "data" would be go against basic practicability.
     
  46. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    I was referring to the matrix specific stuff in floatNxN. There are matrix specific fields and methods.

    Forcing a separation would be impractical. The only way to make it consistent in this area is to do what most other libraries do, have explicit vector/matrix abstractions.

    That said I understand it adds some consistency in other areas, like the fact that shaders are a constant thing we often work with in relation to C# code. It's a trade off. On it's own I don't really have any strong opinions one way or another. However, this approach adds a slightly steeper learning curve because of the separation. You need to know more about the whole for the individual parts to make sense. We tend to have a lot of that in game development, too much IMO. That's the main reason I would have second thoughts. But on the other hand once familiar, it kind of works.
     
  47. Nyarlathothep

    Nyarlathothep

    Joined:
    Jun 13, 2013
    Posts:
    398
    I seem to remember hearing that Unity.Mathematics would be guarantee deterministic floating point maths. However I can't find any mention of this in the repo. What's the status of that at the moment?
     
  48. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,778
    Possibly (just guessing), is not there yet. But likely in future.
     
  49. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    704
    I guess having math library to share the same syntax with HLSL is ok as long as it's consistent. But I see there are problems with consistency in other parts of API. Enforcing the consistency in math library only seems bit unfair.
    Unity should try to take this opportunity to see if other APIs are following the guideline if there is any.
    (I really don't know what Unity naming guideline is. It seems that many were just random choices.)

    The simplest example would be that Unity is mixing Get*, Find*. They sound similar but not the same. I expect Get* not to return null but Find* may return null, therefore it requires null test, but Unity seems to mix them.

    Having a clear guideline would benefit to make clean APIs so that Unity internal developers would always follow it and makes the learning easier. Taking the same concept, you may have guideline that, Get* always return without null, Find* may return null. Search* is like Find* but it may be expensive and not to use too often and so on

    Consistency in naming is probably the most basic in API design but a good API should be also orthogonal. When there is Get* for one object, I expect Get* is supported for the similar objects. I often find that they are missing.

    Besides, Unity API has been around for so long and it probably requires some major overhaul. It's not easy to change existing APIs but I hope it's doable since you are updating the internals so much these days and I thought it's a good time to bring it up.

    When I was learning the Unity for the first time, I could not believe that I had to derive parent/child relationship from Transform. What if you want to have conceptual Parent/Child relationship without having the Transform? There are many examples that doesn't Transform and forced to find Parent/Child through many nested Transform was like a joke to me.

    Anyway, I wish that there is naming standard in Unity and you publish the guideline to prevent further confusions down the road and try to find an opportunity to overhaul them if they don't adhere to the guidelines.

    Cheers!
     
    Qbit86 likes this.
Thread Status:
Not open for further replies.