Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice
  2. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  3. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Scripting New Mesh functions

Discussion in '5.2 Beta' started by Eric5h5, Jul 9, 2015.

  1. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Since the UI uses meshes now, my thoughts went like this: "OK, it uses meshes, that's cool. But wait...CanvasRenderer.SetVertices can use Lists. We have to go back to fixed arrays? Surely not...." And indeed, the Mesh class now has stuff like SetVertices, which takes a List. So my questions are:

    1) Shouldn't this be mentioned in the release notes? (And be in the docs?) It's kind of a big deal for meshes in general, never mind the UI.
    2) Shouldn't there be SetUV3 and SetUV4 functions?

    --Eric
     
    alexzzzz, jashan and shkar-noori like this.
  2. Tim-C

    Tim-C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Posts:
    2,221
    It should be and I'm doing that doc work today ;)

    We are doing a sanity check on the API atm, to make sure it's what we want, when we are sure all the api points will be there.
     
    jashan likes this.
  3. Tim-C

    Tim-C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Posts:
    2,221
    FYI:
    It's probably going to look like this:

    Code (csharp):
    1.  
    2. void SetUVs (int channel /*1 - 4*/, List<Vector2> uvs)
    3.  
     
    jashan and Vanamerax like this.
  4. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Yep, that makes more sense. Cool!

    --Eric
     
    shkar-noori likes this.
  5. ecurtz

    ecurtz

    Joined:
    May 13, 2009
    Posts:
    640
    8bit4life and FernandoRibeiro like this.
  6. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,649
  7. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    CanvasRenderer.SetVertices did have the ability to use both a List and an array with a length, so yes, it would be ideal for Mesh to have that as well. It's not really redundant, since Lists are good for some use-cases but fixed-length arrays are significantly faster. (Yes, Lists are backed by arrays anyway, but for whatever reason, they're slower.)

    --Eric
     
    8bit4life likes this.
  8. ecurtz

    ecurtz

    Joined:
    May 13, 2009
    Posts:
    640
    If there is a version that takes a size you can allocate a single static array for all your source data and use it for different target meshes. No garbage.
     
    8bit4life and FernandoRibeiro like this.
  9. Stephan-B

    Stephan-B

    Joined:
    Feb 23, 2011
    Posts:
    2,269
    + 100 on adding the ability to use Arrays with length.
     
    8bit4life likes this.
  10. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,649
    I think we should probably just fix that. Faster for which operations?

    (My guess is that accessing list elements incurs two bounds checks - one against the list size and one against the underlying array - but if that's the cause then there's got to be some way to eliminate that and just guarantee that the list size is always less than or equal to the array size).
     
  11. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,649
    You can do exactly the same thing with a List.
     
  12. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Faster for accessing the elements in the collection, both reading and writing. How much faster depends on the type; e.g. int[] is 5-6X faster than List<int>, and Vector3[] is about 2X faster than List<Vector3>. The more "complex" the type, the less of a difference there is.

    --Eric
     
  13. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,649
    Interesting. I'm going to have to try some experiments on that... my guess is that the more complex types are less cache-friendly so they're more expensive to access overall, and as that cost goes up, the overhead of doing the extra bounds check becomes less significant. But we'll see - 5-6x faster for basic int sounds more severe than the extra bounds check would really account for...
     
  14. ecurtz

    ecurtz

    Joined:
    May 13, 2009
    Posts:
    640
    Why would you be bounds checking each element anyway? This should be the C# equivalent of a memcpy().
     
  15. scheichs

    scheichs

    Joined:
    Sep 7, 2013
    Posts:
    77
    i need the ability to have a big static array and assign only a part of it dynamically to the mesh. currently i have to copy it to a garbage array with the desired length. most flexibility would be to have setvertices(buffer, offset, length) and so on
     
    Last edited: Jul 21, 2015
  16. Ferazel

    Ferazel

    Joined:
    Apr 18, 2010
    Posts:
    517
    I don't think bounds checking is the problem. Arrays in c# are bounds checked in order to throw index out of range exceptions.

    I can see this being a design paradigm that Unity struggles with often. Do they make the interface that is easier to use or the one that is more efficient. In this case, I feel that this would primarily be used by power users and thus the more efficient interface would be preferred.
     
  17. Zenix

    Zenix

    Joined:
    Nov 9, 2009
    Posts:
    213
    How would you do that with a list?
     
  18. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    A list is a static array. The amount of memory used will not change unless you add more items than the list capacity (which is 4 items by default), in which case the items are copied to a new array that's double the size of the old one, and the old array is garbage collected. Reducing the number of items in a list doesn't change the array size at all (unless you manually call TrimExcess). So if you have code like

    Code (csharp):
    1. var verts = new List<Vector3>(1000);
    then you have a static array with 1000 entries. Adding/removing items won't change this, unless you exceed 1000 entries, in which case you then have a static array with 2000 entries. All of this happens behind the scenes, so it looks like lists are dynamic, but they're really not; they're just arrays. (But slower for some reason.)

    --Eric
     
    Kronnect and 8bit4life like this.
  19. scheichs

    scheichs

    Joined:
    Sep 7, 2013
    Posts:
    77
    Yeah, but when you rebuild your mesh dynamically you'd have to use List.Add() instead of accessing via an index (which is much more flexible, readable and debuggable). I'd prefer a memcopy-like syntax.
     
    8bit4life likes this.
  20. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    +1 on array with length syntax. List<T> is just a specific case of that, and it's inefficient if you are doing a ton of dynamic mesh updates in realtime. Also, I'm using my own version of List<T>, so that'd automatically mean I won't be able to use it for mesh data. At the very least, make it IList<T>, not just List<T>.
     
  21. Astro75

    Astro75

    Joined:
    Dec 18, 2014
    Posts:
    48
  22. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    There's one sort of annoying issue with adding these new overloads with List<>, in that any code that passed null for the array will now fail to compile because the call is ambiguous. For example:

    mesh.SetTriangles(null, 2);

    now errors with "Call is ambiguous between SetTriangles (List<int>, int) and SetTrianglse(int[], int)."

    You can fix it by casting the null to the correct type in the call, but fixing that in a bunch of places is kind of annoying, and it also always feels weird to have to cast nulls.
     
  23. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    It would be nice to have IList<int> that could take both arrays and lists.

    Code (CSharp):
    1. public void SetTriangles(IList<int> indices, int submesh)
     
  24. Tim-C

    Tim-C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Posts:
    2,221
    The IL is compatible, but unless we gave each function it's own name there isn't anything we can do on our side (there is no way to autoupgrade this). ;(

    The function call crosses the c# -> c++ bridge. We need to have a concrete type as we make assumptions about memory layout ect. If we were to use an interface here then we can not do this.
     
  25. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    Code (CSharp):
    1. public void SetTriangles(IList<int> indices, int submesh)
    2. {
    3.     if (indices is int[])
    4.     {
    5.         SetTrianglesArray(indices, submesh);
    6.     }
    7.     else if (indices is List<int>)
    8.     {
    9.         SetTrianglesList(indices, submesh);
    10.     }
    11.     else
    12.     {
    13.         throw new NotSupportedException("You failed :(")
    14.     }
    15. }
    16.  
     
    Last edited: Jul 28, 2015
  26. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,649
    We're not going to have an API that takes an interface but then rejects every implementation of that interface except two.

    And, because the interface could implement things in any way, the only way we'd be able to support it is to call from native code back into managed code for each individual element, which would be horrendously slow. As Tim says, when we have a concrete type - an array or a List<T> - then we know how those are implemented and can do stuff like memcpy the entire buffer directly.
     
  27. Vanamerax

    Vanamerax

    Joined:
    Jan 12, 2012
    Posts:
    938
    and how about the offset + size optional parameters? I think this would be a valid addition to the API.
     
  28. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    Hardcoding concrete types into an API is never a good idea... Personally, I won't ever use List<T> because List<T> has some problems, like the indexer method call overhead. And sometimes it's just not the kind of data structure I need.

    Nothing beats array + offset + size in terms of versatility here, since it's the most low-level thing we can get with safe C#. It's also easy on your side - a simple memcpy all the way.
     
    8bit4life likes this.
  29. Deleted User

    Deleted User

    Guest

    I'm finding a lot of assets are broken with the "The call is ambiguous between the following methods or properties: 'Mesh.SetTriangles (int[], int)' and 'Mesh.SetTriangles(List<int>, int)'" Manual casting time :)
     
  30. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    What is the use case of passing null to Mesh.SetTriangles?
     
  31. Stephan-B

    Stephan-B

    Joined:
    Feb 23, 2011
    Posts:
    2,269
    As previous mentioned, it would be great to have the ability to set vertex attributes by using Arrays or Lists and to be able to specify a size for each (as well as offset)

    Mesh.SetVertices(Vector3[] verts, int size); / Mesh.SetVertices[List<Vector3> verts, int size);

    Mesh.SetVertices(Vector3[] verts, int start, int size); / Mesh.SetVertices[List<Vector3> verts, int start, int size);
     
    Dantus and Kronnect like this.
  32. Kronnect

    Kronnect

    Joined:
    Nov 16, 2014
    Posts:
    2,894
    Agree with @Stephan B . This kind of APIs are used a lot in the execution callstack at the end of the day and these suggestions will affect possitively from bottom up.
     
  33. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,649
    How come none of you are asking for an API whereby the buffers are shared between managed and native sides of the engine, such that data no longer needs to be copied at all? :)
     
    karl_, ZimM and Kronnect like this.
  34. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    If we do, will you implement it? ;) I figure incremental improvements to stuff that's already there has a better chance of getting done....

    --Eric
     
    karl_ likes this.
  35. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Can we have an API whereby the buffers are shared between managed and native sides of the engine?
     
  36. Stephan-B

    Stephan-B

    Joined:
    Feb 23, 2011
    Posts:
    2,269
    Direct access to vertex buffers would be amazing but like Eric said going for incremental improvements seems to get us there quicker sometimes.
     
  37. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    This x 10. I've been driven crazy by the copying back and forth stuff. Just give me pointers to the arrays of verts and so forth and set me free. (Oh, wait, it's C#.. How about a ref? ;) )
     
  38. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    It supports pointers.
     
  39. Zuntatos

    Zuntatos

    Joined:
    Nov 18, 2012
    Posts:
    612
    If you create an array and pass it to the engine and it uses the original memory (by pointer or by ref or whatever), would you have to notify the engine if you change anything to actually upload the data to the GPU?

    I can definitely see the performance improvements for things like dynamic water not being copied from managed to unmanaged every frame. And of course the 10's to 100's of MB's of RAM saved.

    PS: About the List<T> speed, could this be due to S***ty inlining due to the old mono version (no aggressive inlining attribute), as the index property is essentially a method?
     
  40. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    So... 5.2.0f1 is out. Are we not getting the array + offset + size variant?
     
  41. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,649
    Definitely not in 5.2 final, no.
     
  42. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    That's a shame :( List<T> variant is useless to me. Is this at least considered for a future release?
     
  43. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,649
    We have plans to improve this whole API, yes.
     
  44. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    Mesh.SetUVs can accept lists of Vector2, Vector3 or Vector4. What's the use case for Vector3 and Vector4? Are z- and w-components just ignored?