Search Unity

  1. Unity 2018.3 is now released.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Want more efficiency in your development work? Sign up to receive weekly tech and creative know-how from Unity experts.
    Dismiss Notice
  4. Build games and experiences that can load instantly and without install. Explore the Project Tiny Preview today!
    Dismiss Notice
  5. Nominations have been announced for this years Unity Awards. Celebrate the wonderful projects made by your peers this year and get voting! Vote here!
    Dismiss Notice
  6. Want to provide direct feedback to the Unity team? Join the Unity Advisory Panel.
    Dismiss Notice
  7. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice

Unity.Mathematics available on github

Discussion in 'Entity Component System and C# Job system' started by xoofx, Apr 10, 2018.

  1. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    394
    Then you define parent/child relationship for your entities by yourself. Provided transform API is not for “conceptual” parent/child relationship, it's about concrete scene graph data structure: https://en.wikipedia.org/wiki/Scene_graph

    Of course their API for Transform is also poor since they are 3D engineers, not professional library writers. Just making the note that this particular your complaint is probably ill-founded.
     
  2. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    157
    Of course, you can design your own APIs, but that's not the point.
    It's one of the badly designed API that needs be part of the overhaul if there will be one in the future. Parent/Child relationship should be independent of Transform. Currently, to get the parent object, you need to GameObject.transform.parent.gameObject. Does this look like a right design? I would vote strongly against it if have a choice.

    Unity API was very primitive when it first came out and they probably thought, ... all GameObject probably just 3d objects and by default it will all have Transform... and transform needs hierarchy...and let's throw parent/child in there.
    Containers and manager type of classes are not 3D objects and they are forced to instantiated with Transforms.

    oh well.. it really bugs me to see that we are stuck with the bad design...so low level that I keep seeing everywhere.

    What I'm hoping is that there will be some cleanup on APIs, if not, have a clear guideline so that future API's are consistent, and orgothogonal.
     
  3. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    394
    Transforms by themselves make absolutely no sense if they are not ordered in tree with bidirectional traversal (so called “scene graph”). It's parent/child specifically for traversing this tree, not to have some abstract high-level meaning. This kind of API looks very same in all libraries: Xenko, Box2D, etc. It has well-known expected meaning (like algebraic linear transforms in homogeneous coordinates): when you call get-world-transform (or its component: position, rotation, scale, does not matter) it performs series of matrix multiplication from local-transform of the child up to the root.

    (Sorry if it's unclear, I'm not a native speaker, discussing such details is a little bit hard in sense of vocabulary.)
     
  4. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    394


    http://gameprogrammingpatterns.com/dirty-flag.html
     
  5. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    157
    @Qbit86, I'm not saying Transform doen't need hierarchy. They do but parent/child should be a property of GameObject, not Transforms. Transform should get the parent/child information from GameObject, not the other way around. This way, conceptual(not 3d object) GameObject can have parent/child relationship and Transform can be an optional component. Let's not talk too much about Transform as it is not the point of my post. Cheers!
     
    Qbit86 likes this.
  6. rizu

    rizu

    Joined:
    Oct 8, 2013
    Posts:
    604
    This is probably the last response on the ETA: https://forum.unity.com/threads/eta-of-floating-point-determinism.539534/#post-3559944.

    It doesn't seem like a thing you'd expect to show up before next winter (at earliest) and considering how these targets tend to drift, it's probably happening later during 2019 cycle.
     
    Antypodish and Nyarlathothep like this.
  7. Gen_Scorpius

    Gen_Scorpius

    Joined:
    Nov 2, 2016
    Posts:
    38
    I don't know if it has been mentioned or explained somewhere but what is the performance difference between using multiple floats vs the use of floatN in a burst-compiled job? Should I try to fill up my data in float4s for best performance?

    However, if I use floatN than I can't use the [Range] attribute to set different limits for the range of the individual floatN.x, .y and so on values. This would be useful to limit what the game designers can use as parameters in the inspector for ECS components with floatN variables.
     
  8. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    2,479
    I suspect there is none, or maybe very little, with benefits for floatN.

    Don't know if that the case, but you can do the normal float with range in the inspector and then set it back via script to floatN.
     
  9. Gen_Scorpius

    Gen_Scorpius

    Joined:
    Nov 2, 2016
    Posts:
    38
    I also think about using a modified Range property that allows me to set min and max for the individual values and a custom inspector but it would be nice to know if the compacting of the floats is worth the effort.
     
  10. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    2,479
    Also, you alternatively could have an array of float. This would be surely faster in terms of performance. Inspector from what I have seen, can easily tackle arrays with ranges, if you wish. Of course option may not always be feasible, depending on how many float you want per entity component. So once we get such options (eventually?), It shouldn't be too difficult to achieve what you need.
     
  11. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    633
  12. stubbesaurus

    stubbesaurus

    Unity Technologies

    Joined:
    Oct 7, 2016
    Posts:
    3
    @Gen_Scorpius floatN maps directly to the underlying SIMD types. On PC this would be SSE/AVX. This means that for many operations such as addition, multiplication, etc, performing it on a float4 is essentially the same cost as doing it on a single float. You definitely want to leverage floatN when you are performing the same operation on all the elements of the vector. Burst will try to automatically roll float values into float4 operations, but unless your data is laid out carefully it might end up not being worth it due to all the shuffling and repacking involved to convert to and from float4. Generally you want to keep things in floatN whenever possible to avoid needless shuffles.
     
    Ofx360 and laurentlavigne like this.
  13. xoofx

    xoofx

    Unity Technologies

    Joined:
    Nov 5, 2016
    Posts:
    84
    The math library will be compatible with deterministic mode in the future (note that deterministic mode will be only available from burst, not when running withing C# (though we will have to workout this as well).

    About deterministic mode, it has been postponed for preview likely next year (hopefully within Q1/Q2, but can't tell exactly)
     
    twobob and Nyarlathothep like this.
  14. NearAutomata

    NearAutomata

    Joined:
    May 23, 2018
    Posts:
    51
    I wasn't sure where to ask this question, so I decided to post it here. Players in my game can currently navigate in eight directions using WASD as usual. In order to prevent double the movement speed when moving diagonally I am normalizing the direction vector before multiplying it with deltaTime and my movement speed constant. After moving to the Job system and the new math library I noticed an unexpected behaviour.

    Usually
    new Vector3(0, 0, 0).normalized
    would return
    (0, 0, 0)
    however
    math.normalize(math.float3(0, 0, 0))
    returns
    float3(NaNf, NaNf, NaNf)
    which isn't what I expected in the first place. This forces me to write a really weird if statement that introduces previously unnecessary branching inside of a job:
    Code (csharp):
    1. public void Execute([ReadOnly] ref PlayerController controller, ref Position position)
    2. {
    3.     var v = normalize(float3(controller.Horizontal, 0, controller.Vertical));
    4.     if (!isnan(length(v)))
    5.     {
    6.         position.Value += v * MovementSpeed * DeltaTime;
    7.     }
    8. }
    I'd like to know whether this is intended going forward or just an oversight on your end?
     
    Qbit86 likes this.
  15. rizu

    rizu

    Joined:
    Oct 8, 2013
    Posts:
    604
    @NearAutomata You can't really normalize a zero vector as it doesn't have any length to normalize to begin with so different math libs deal with this in different ways. Neither Vector3 or new math lib approach is ideal and both are providing a compromise, in reality you are asking it to perform a task that isn't possible, I feel that NaN is more appropriate output for such task (even though it might not be as handy for your specific use case here).

    You could try this instead:

    Code (CSharp):
    1. public void Execute([ReadOnly] ref PlayerController controller, ref Position position)
    2. {
    3.     var v = normalize(float3(controller.Horizontal, 0, controller.Vertical));
    4.     position.Value += select(v * MovementSpeed * DeltaTime, float3(0, 0, 0), isnan(v));
    5. }
     
    RaL likes this.
  16. NearAutomata

    NearAutomata

    Joined:
    May 23, 2018
    Posts:
    51
    A few days ago I read something about
    select
    in particular. Although it isn't as straightforward as writing
    position.Value += normalize(float3(...)) * Speed * dt
    (which was basically the line using old
    MonoBehaviour
    it was written that
    select
    can be optimized much better than branches using if. Don't quote me on that though.

    Thanks for this suggestion which I'll gladly incorporate in my code.
     
  17. rizu

    rizu

    Joined:
    Oct 8, 2013
    Posts:
    604
    This is why I suggested it (should have mentioned it separately).
     
  18. NearAutomata

    NearAutomata

    Joined:
    May 23, 2018
    Posts:
    51
    @rizu I just stumbled upon the following experimental code in the sources:
    Code (CSharp):
    1. static public float3 normalizeSafe(float3 v)
    2. {
    3.     float len = math.dot(v, v);
    4.     return math.select(new float3(), v * math.rsqrt(len), len > epsilon3f);
    5. }
     
    rizu likes this.
  19. elZach

    elZach

    Joined:
    Apr 23, 2017
    Posts:
    7
    Hi, if I wanted to perform a division should I still use "/" or is there already a method in Unity.Mathematics?
    I expected to find something akin to math.div, similar to math.mul instead of "*".

    Is division just not in the library or does it use another keyword which i'm not familiar with?
     
  20. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    2,479
    I suppose / is optimized as well, as multiplication. And with burst.
    However, is good practice to use multiplication rather than division, when possible.
    For example instead 5 / 100 do 5 * 0.01f

    Tehcnically you don't need div. You just invert variable, if you need divide it.
    Instead math.div (5, 27) you can do math.mul ( 5, 1/27 )
     
  21. elZach

    elZach

    Joined:
    Apr 23, 2017
    Posts:
    7
    Alright, I wasn't sure if math.mul(x,1/y) wouldn't defeat the point of not just using x/y, because you'd still use the "/" operator. But thanks for the response. :)
     
  22. NearAutomata

    NearAutomata

    Joined:
    May 23, 2018
    Posts:
    51
    Writing 1/20 for example yields a constant while math.mul(x, 1/20) of course is not a constant. Depending on the compiler and its implementation those constants won't cause overhead compared to a "div(1, 20)". So basically a math.mul(x, 1/20) will be more optimized (replaced by a high performance internal machine command) compared to a "dynamic" x/20.
     
  23. pvloon

    pvloon

    Joined:
    Oct 5, 2011
    Posts:
    567
    Sometimes when working with 2D angles I find I want something similair to quaternions but for 2D - aka, complex numbers.

    Any chance to adding complex numbers for use with 2D angles?
     
  24. georgeq

    georgeq

    Joined:
    Mar 5, 2014
    Posts:
    398
    Sounds crazy, but you might be right. A lot of people believe "Mathematics" wasn't the wisest choice for a namespace. I agree that a better decision on the namespace's name would've generated a lot less opposition and complaints.
     
    laurentlavigne likes this.
  25. rizu

    rizu

    Joined:
    Oct 8, 2013
    Posts:
    604
    IMO the this smaller intrinsics library should just be called Unity.Intrinsics as that's what it is. And moving things out of Mathematics that everyone expect to be in Mathematics is wrong in principle. Basically what is happening here is that you are forcing ECS package for people who want to use the new job system with Burst (but don't want to get involved with Entities yet), this isn't logical at all and will just cause more confusion among users.

    So what I'd suggest is to move the intrinsics into separate package and keep (and extend) higher level math operations on Mathematics instead.
     
  26. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    2,479
    I would like to point out last two words, for now. Which makes sense, to keep mathematics library clean.

    There is no forcing involved here. We all know the whole ecs and related packages are in beta stage. So make sense to keep things away, until is decided, where they need to go.
     
    Cynicat likes this.
  27. illinar

    illinar

    Joined:
    Apr 6, 2011
    Posts:
    422
    Is there a way to get Euler angles from quaternion or float4x4?
     
  28. slim_trunks

    slim_trunks

    Joined:
    Dec 31, 2017
    Posts:
    41
    Are there any plans to implement bilinear and even better trilinear interpolation? I know they are probably not needed as much but having a canon implementation would probably result in better performance than a less thought out version.
     
    Nyarlathothep likes this.
  29. yoonitee

    yoonitee

    Joined:
    Jun 27, 2013
    Posts:
    2,166
    The library looks good.

    One question. How do you get to the float3 vectors from a gameobject transfrom.
    Do you have to do it this way? And vice versa?

    Code (CSharp):
    1. Vector3 a = gameObject.transform.position
    2.  
    3. float3 b = float3(a.x,a.y,a.z)
    Also how do you change an array of Vector3 to an array of float3 such as:

    Code (CSharp):
    1. Vector3[] verts = mesh.triangles;
     
  30. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,359
    Code (CSharp):
    1. float3 a = gameObject.transform.position;
    float3 and Vector3 are implicitly convertible to each other.

    The second one is more tricky. I wrote a helper function that takes a managed array, allocates a native array of the same size and copies the data:
    Code (CSharp):
    1.         static unsafe NativeArray<TR> ConvertArrayToNative<TS, TR>(TS[] array) where TS : struct where TR : struct
    2.         {
    3.             Assert.AreEqual(UnsafeUtility.SizeOf<TS>(), UnsafeUtility.SizeOf<TR>());
    4.  
    5.             var native = new NativeArray<TR>(array.Length, Allocator.Persistent);
    6.             var destination = native.GetUnsafePtr();
    7.  
    8.             var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
    9.             var source = handle.AddrOfPinnedObject().ToPointer();
    10.  
    11.             UnsafeUtility.MemCpy(destination, source, array.Length * UnsafeUtility.SizeOf<TS>());
    12.  
    13.             handle.Free();
    14.             return native;
    15.         }
    16.  
    Usage:
    Code (CSharp):
    1. NativeArray<float3> array = ConvertArrayToNative<Vector3, float3>(mesh.vertices);
    It's probably not the optimal solution but works for my experiments.
     
    Last edited: Oct 28, 2018
    xman7c7 and yoonitee like this.
  31. yoonitee

    yoonitee

    Joined:
    Jun 27, 2013
    Posts:
    2,166
    I wonder how efficient that is:
    Code (CSharp):
    1. float3 a = gameObject.transform.position;
    What I would suggest is that on game object there could be a property called "nativeTransform" which outputs all the values as native values.
    Or indeed on the transform property there could be properties called "nativePosition" etc.
    And indeed on the mesh there should be a property called nativeVertices.

    Even better, there could be a property called doubleTransform which contains transform in terms of doubles instead of floats. Which might be used in the future for more precision.
     
  32. Cyberwiz15

    Cyberwiz15

    Joined:
    Nov 10, 2016
    Posts:
    53
    I think in terms of efficiency your suggestion might not be adding noticable gains. The main performance bottlenect of using that would be in the memory traversal going about, not so much the allocation of the float3 value. Having a "nativeTransform" which outputs all the values at native would incur having to keep those values updated for every single object, but accessing the position as is will only be required in a specific subset of the code that we'll write.

    What you're describing is rather having data on the existing api accessible in a format that's ECS friendly, but that's just as achievable through using implicit conversion.
     
  33. yoonitee

    yoonitee

    Joined:
    Jun 27, 2013
    Posts:
    2,166

    I don't think so. I'm assuming that in a transform component inside it is just a matrix of floats and should be able to output them however it feels. I could be wrong though.
     
  34. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    23,840
    You are wrong. It is about memory being linear to traverse and cache friendliness. The whole point of all this is to prevent the CPU being stalled fetching memory from different locations. This takes much longer than assigning to floats.
     
  35. elZach

    elZach

    Joined:
    Apr 23, 2017
    Posts:
    7
    Hey there, I'm currently rewriting old Mathf/Quaternion code into burstable code using Unity.Mathematics.
    There are a couple of functions I was missing. Namely Quaternion.FromToRotation, Quaternion.RotateTowards, Quaternion.AngleAxis aswell as Quaternion.Angle.
    For the time being I wrote custom code to replace these functions. That code obviously won't be as optimized as the native mathematics functions. So I was wondering if there are plans for addition of these functions, or if they are already in and I just haven't found them.
     
  36. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    394
    Consider using System.Numerics.Quaternion, for example, CreateFromAxisAngle().

    Quaternion is SIMD-enabled in .NET, not sure about Unity.
     
    elZach likes this.
  37. rizu

    rizu

    Joined:
    Oct 8, 2013
    Posts:
    604
    There's Unity.Mathematics.quaternion.AxisAngle and Unity.Mathematics.quaternion.RotateX (and Y and Z) at least on the latest Mathematics package available through Package Manager.

    Whole point of the new Mathematics library is that works nicely with Burst compiler. I don't think you'll get similar perf gains from stock things that are optimized for .NET. Burst generates native code directly. It's not generic IL code that runs after it so you can't treat it the same way.
     
    illinar likes this.
  38. yoonitee

    yoonitee

    Joined:
    Jun 27, 2013
    Posts:
    2,166
    Five years ago. I said that Unity was badly optimized and could do with some much needed optimization. Certain Unity fanboys said that I was wrong and why was I complaining about Unity and I was just using it wrongly and that I didn't know what I was talking about!

    This year the priority of Unity is in optimizing the engine. Parts of which have been sped up by 5-10 times.

    Just came back to say "I told you so". :p
     
    Qbit86, LurkingNinjaDev and FROS7 like this.
  39. illinar

    illinar

    Joined:
    Apr 6, 2011
    Posts:
    422
    is there a float3 vector magnitude method somewhere?
     
  40. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    686
    You can use math.length\lengthsq, or write your own extension with naming magnitude\sqrmagnitude it's very simple :)
     
  41. illinar

    illinar

    Joined:
    Apr 6, 2011
    Posts:
    422
    or even more simple:
    float3 v; Vector3.Magnitude(v);
    :)
    But I'm thinking there might be something Burst optimized. math.length, that's nice, thanks.

    Also, can't figure out matrixes, if this is related to this thread. Need to convert world vector to local vector.
     
  42. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    686
    You must multiply vector to TRS matrix of every parent.
     
  43. illinar

    illinar

    Joined:
    Apr 6, 2011
    Posts:
    422
    I understand that, but specifically in Transform system there LocalToWorld and no WorldToLocal matrix, so can LocalToWorld be used in reverse somehow to convert it into WorldToLocal.

    I think I found it. math.inverse(float4x4)