Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Feedback Vectors should implement IEnumerable

Discussion in 'Scripting' started by josiest, Jun 24, 2019.

  1. josiest

    josiest

    Joined:
    Jun 3, 2019
    Posts:
    9
    I don't know if this has been suggested before, but I feel like it should be a no-brainer that Vectors should implement the IEnumerable interface. I find myself using System.Linq a lot and I often have to make arrays of each component so I can perform iterations on Vectors. For instance, consider this code, inspired by Amit's guide on Hexagonal Grids:

    Code (CSharp):
    1. /** Give the cube distance between a and b in cubic coordinates.
    2. *
    3. * Parameteres
    4. *  a, b - The cube coordinates for which to calculate the distance betewen
    5. */
    6. public static int CubeDistance(Vector3 a, Vector3 b) {
    7.     float[] aa = {a.x, a.y, a.z};
    8.     float[] ab = {b.x, b.y, b.z};
    9.  
    10.     return (int) aa.Zip(ab, (sa, sb) => Math.Abs(sb-sa)).Max();
    11. }
    12.  
    It's only a minor in convenience but it would be really nice if I could just write that method in one line:
    return (int) a.Zip(b, (sa, sb) => Math.Abs(sb-sa)).Max()


    *EDIT:* changed "manhattan distance" to "cube distance"
     
    Last edited: Jun 24, 2019
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    Code (csharp):
    1.  
    2. public static class VectorExtensions
    3. {
    4.     public static IEnumerable<float> AsEnumerable(this Vector3 a)
    5.     {
    6.         yield return a.x;
    7.         yield return a.y;
    8.         yield return a.z;
    9.     }
    10. }
    11.  
    Sure there's the overhead of creating the iterator object. But that overhead would have already occurred boxing the Enumerator returned by the GetEnumerator method of the theoretical IEnumerable implementation of Vector3.

    And anyways... it's linq. It's garbage heavy anyways.
     
    MadeFromPolygons likes this.
  3. josiest

    josiest

    Joined:
    Jun 3, 2019
    Posts:
    9
    This is pretty neat, and it also highlights a feature about c# which I think is really cool, but I also think it'd be cool if this kind of thing was integrated into the Unity Engine so I don't have to write something like this everytime I make a new project.
     
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    I'm surprised you haven't already created a library of classes that you import into every project...

    I know I have (it's in my signature).

    And I know many others have.

    I'd argue Vector3 shouldn't be an enumerable... becuase it's not really a collection. If it were then wouldn't the argument be to make all data structures with more than one field enumerable of its fields?

    But hey... if you want it, can't hurt to ask.
     
  5. josiest

    josiest

    Joined:
    Jun 3, 2019
    Posts:
    9
    I disagree. Look at languages like Mathematica and Matlab. Vectors are kind of the O.G. numeric collection data structure, like before programming was even a thing.
     
    Last edited: Jun 24, 2019
  6. josiest

    josiest

    Joined:
    Jun 3, 2019
    Posts:
    9
    Looking at your code, why not just make your own game engine at that point?

    (Also I'm very new to Unity, so I'm still getting adjusted to the workflow)
     
    Last edited: Jun 24, 2019
  7. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    I mean... sure, kind of.

    Don't get me wrong... my background is math primarily, that's what I went to college for. But even then I seldom had to enumerate them.

    Like take your method above... CubeDistance. And it's defined as:
    For starters... that doesn't seem to be the manhattan distance. It's the max of the distance on all 3 components.

    Regardless though, commonly manhattan distance (especially in games) is used for its speed since it doesn't require a square root. But you're adding all this overhead of linq (and creating arrays). So why even use the manhattan distance?

    I would have just inlined the entire algorithm:
    Code (csharp):
    1.  
    2. public static int CubeDistance(Vector3 a, Vector3 b)
    3. {
    4.     int v = (int)Math.Abs(b.x - a.x);
    5.     int result = v;
    6.     v = (int)Math.Abs(b.y - a.y);
    7.     if(v > result) result = v;
    8.     v = (int)Math.Abs(b.z - a.z);
    9.     if(v > result) result = v;
    10.     return result;
    11. }
    12.  
    (mind you this is your algorithm and not manhattan distance)

    Unless you intended to use Sum... in which case just add it all up:
    Code (csharp):
    1.  
    2. public static int CubeDistance(Vector3 a, Vector3 b)
    3. {
    4.     return (int)(Math.Abs(b.x - a.x) + Math.Abs(b.y - a.y) + Math.Abs(b.z - a.z));
    5. }
    6.  
    :shrug:

    Because I don't want to have to implement the physics engine, design my own editor, debug the engine across all platforms, create all the shaders/lighting systems... all the heavy lifting.

    My framework of code is more game mechanics focused, and has been built over 10 years of working with Unity to facilitate my artist/designer partner.
     
    DonLoquacious and Kurt-Dekker like this.
  8. josiest

    josiest

    Joined:
    Jun 3, 2019
    Posts:
    9
    Whoops, thanks for pointing that out! I'll just change the documentation. The algorithm is based off the Manhattan distance, but since it's on a hex grid instead of a square grid it's a bit different. Amit Patel calls this the "Cube Distance" in his hex grid guide. I just misread it is all.
     
  9. josiest

    josiest

    Joined:
    Jun 3, 2019
    Posts:
    9
    oh btw, I know Linq has overhead, but I like programming in it b/c it looks cool :cool:... and it's harder to write buggy code. (and for the purposes of what I'm doing right now I don't think it will make much of a difference in terms of speed... I'll see once I actually get a game up and running).

    Oh! And I think Linq definitely preferable when writing unit tests.
     
    Last edited: Jun 24, 2019
  10. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    Well... I can certainly feel ya on the "looks cool" aspect. I too enjoy writing me some linq.

    I wish you luck on your game making endeavours.
     
    xVergilx and josiest like this.
  11. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    I sometimes think people are too afraid of Linq in Unity. If its not run in a tight loop its fine. Even more so in later versions of Unity with better GC.
     
  12. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,745
    Vectors should not implement IEnumerable as it will lead to cpu and memory overhead. And you can always create your extension method for that

    Code (CSharp):
    1. public static IEnumerable<float> AsEnumerable(this Vector3 vector) {
    2.     yield return vector.x;
    3.     yield return vector.y;
    4.     yield return vector.z;
    5. }
    6.  
     
    MadeFromPolygons likes this.
  13. Boz0r

    Boz0r

    Joined:
    Feb 27, 2014
    Posts:
    419
    Vectors from math are equivalent to Lists og Arrays in most non-math specific programming languages, though. Vector3 is a fixed size, with specific named entries.
     
    MadeFromPolygons likes this.
  14. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,447
    Unity Technologies and Microsoft, among others, recommend to avoid LINQ where performance is a concern, which is pretty much every game.

    https://learn.unity.com/tutorial/fixing-performance-problems

    https://docs.microsoft.com/en-us/windows/mixed-reality/performance-recommendations-for-unity
     
    MadeFromPolygons and Boz0r like this.
  15. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    They dont mean it like that. They mean when it is of concern in a specific computer program. For example, if you know a piece of code does not run in a tight loop, in other words not every frame or from many places at the same time you can safely use Linq.
     
    josiest and DonLoquacious like this.
  16. josiest

    josiest

    Joined:
    Jun 3, 2019
    Posts:
    9
    I fail to see how implementing an interface would lead to cpu and memory overhead. Here's one example of how implementing an interface makes no significant impact on overhead.
     
  17. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    9,920
    Vector3 is struct. Value type. You will have boxing for sure and other problems. More info here:
    https://blogs.msdn.microsoft.com/abhinaba/2005/10/05/c-structs-and-interface/

    And you don't want boxing on a frequently used basic type like a VectorN. You want the least boxing humanly possible in a game in general.
     
    MadeFromPolygons likes this.
  18. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,745
    MadeFromPolygons likes this.
  19. MadeFromPolygons

    MadeFromPolygons

    Joined:
    Oct 5, 2013
    Posts:
    3,878
    Mathematical CS languages like that != game dev languages. Just because thats a thing in matlab, does not mean its justified in unity. Also vectors in matlab, just like in many languages are basically lists, they are not the same thing at all as Vector2, Vector3, Vector4 etc.

    lordofduct is right, Vector is not a collection so making it enumerable just doesnt make sense for general audience. If you want it for your specific purposes then write it once, then save it and import into projects each time like the rest of us do. Adding this in for a really specific use case that makes sense for one users but not for most, isnt a good thing to be doing to the engine as far as bloat and usability is concerned.

    Thats before we even talk about the overhead, and having lots of unnecessary overhead all over the place is not acceptable in games development where performance is key.
     
    josiest likes this.
  20. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358