Unity Community


Page 1 of 3 123 LastLast
Results 1 to 20 of 42

  1. Posts
    25

    Procedural mesh update slow on iphone 4

    Hello,

    I'm using Prime31's UIToolkit to create the user interface and HUD of my iOS game. All was working fine until last week when suddenly I would get horrible lag bursts whenever I moved or updated an interface element, which you can see in this image, but only when running on the iPhone 4 or lower, on PC and the iPad 2 it's fine. (So, moving the joystick thumb, or updating a button with the "pressed" image for example will cause horrible stuttering.)

    I've already tried rolling back my project to an earlier version yet the problem remains, so it must be caused by some change in Unity or iOS. I've tracked down the slowdown to updating the procedural mesh used for the UI. Even with only a few vertices the slow down still happens, and if I comment out the "mesh.vertices = tempVertices" assignment the slow down goes away (and the mesh isn't updated, of course), so my bottleneck isn't on the generation of the new vertex data, but on Unity's update. Anyone knows what's up? I've been banging my head on this for days now.


  2. Location
    Cambridge, UK
    Posts
    27
    I don't think you have selected one of the spikey frames in the image you supplied so I can't see for sure what's going on however....

    We're seeing the same issue and it looks like a problem in Unity related to the way it's updating OpenGL buffers and then trying to render from them which is causing massive stalls (it could potentially be a problem in the gl driver instead). One work around which sounds counter intuitive is to ensure that rendered geometry is always taking the dynamic batching path because this will cause it not to render from the OpenGL buffer and instead render from client memory which avoids the stall. To do this you need to render another mesh (that will not get culled) that uses the same material as the GUI elements that are causing problems. We're currently searching for another work around but right now that's the best we have I'm afraid.

    Hope that helps


  3. Posts
    25
    It not only helps, I want to hug you right now!

    I created another dummy mesh object that used the same material and consisted only of a single 0-area triangle, that made Unity dynamic batch both and sure enough, the slowdown is gone. I reported the bug to Unity, so hopefully it gets fixed some time in the future...

    Maybe Unity gives a different hint when uploading the vbo (GL_STREAM_DRAW instead of GL_STATIC_DRAW, maybe), causing the GL driver to behave better.

    Thanks again.


  4. Location
    Cambridge, UK
    Posts
    27
    Awesome!

    We've also found that you can ping-pong/double buffer meshes to avoid the problem but this has other drawbacks such as increased memory and hassle to get things to not cache the mesh they want to write to. This works because you have two buffers and so you're updating the one the GPU has finished with, where as with a single mesh it is trying to update a buffer in use by the GPU, which causes a stall.

    I do hope Unity fix the issue, it's a major pain.


  5. Location
    UK
    Posts
    83
    I've got my own GUI solution which is pretty similar to UIToolKit and I've also been suffering this problem (but not realised how to get around it until now),

    updating and reassigning the mesh vertices every frame would cause a Mesh.CreateVBO spike ( 5 - 11ms on iPod 4 ) which seemed way more than I expected.

    So, going off of froodydude's suggestion I tried implementing the mesh double buffering (write to one mesh one frame, and assign that to the mesh filter, then write to another the next frame and assign that.. etc), this took Mesh.CreateVBO down to 0.82 - 1.01ms when assigning the vertices every frame.

    Ive got a quite a few dynamic meshes so i'll be rolling this solution out to the other classes. I don't really like having to do it this way but it's working!

    I guess it would be good if there was a way for us to tell the engine "hey i'm probably going to be updating this mesh every frame, so treat it differently somehow"?

    Thanks froodydude for the tip!

  6. Super Moderator
    Location
    Great Britain
    Posts
    9,678
    I wondered about this problem myself, and ended up with the gui using a boned mesh.
    Currently working with Sony on our new
    PS4 and Vita game in Unity!

    This post is not representative of Simian Squared Ltd


  7. Location
    Curitiba - PR / Brazil
    Posts
    275
    Guy, I think i get the same issue on my project.

    Our game is 2D, but i can't find what is the problem on iPhone 4, the performance of the game on iPad 1 is fine! But on iPhone 4 i get get a crap performance..

    If i create one cube, and put all my materials on that, can pre warn the textures? or i misunderstood ?


  8. Posts
    407
    Quote Originally Posted by yuriks View Post
    It not only helps, I want to hug you right now! :D

    I created another dummy mesh object that used the same material and consisted only of a single 0-area triangle, that made Unity dynamic batch both and sure enough, the slowdown is gone. I reported the bug to Unity, so hopefully it gets fixed some time in the future...

    Maybe Unity gives a different hint when uploading the vbo (GL_STREAM_DRAW instead of GL_STATIC_DRAW, maybe), causing the GL driver to behave better.

    Thanks again.
    Would you mind showing me what files you modified in UIToolkit to achieve this? My team is facing the same issue. I'm trying to understand how do you create a "dummy mesh object that used the same material and consisted only of a single 0-area triangle, that made Unity dynamic batch both and sure enough, the slowdown is gone". Thank you.


  9. Location
    Cambridge, UK
    Posts
    27
    Quote Originally Posted by badawe View Post
    Guy, I think i get the same issue on my project.

    Our game is 2D, but i can't find what is the problem on iPhone 4, the performance of the game on iPad 1 is fine! But on iPhone 4 i get get a crap performance..

    If i create one cube, and put all my materials on that, can pre warn the textures? or i misunderstood ?
    Well it might be the same issue. If you have a pro licence use the Unity profiler and look for very high amounts of time spent in CreateVBO when it spikes/is slow. If it is this then you can fix by ensuring rendering takes the dynamic path. Unity will take the dynamic path when two or more meshes share the same material and are not culled. Note that this is a per-frame decision. The underlying problem is to do with buffer updates and how it submits geometry, it's not a problem with textures or materials.

    So for every mesh you change dynamically that frame you need to ensure that another mesh which uses the same material is also rendered and is not culled. This mesh can just contain a 0 area tri but must _not_ be culled.

    In pseudo code you could solve like this (but it can be improved upon):

    // One time
    - Create a mesh for every material in the game, put one 0-area triangle in in and set the culling data to be very large.

    // every frame
    - For every material used this frame, send the previously created mesh that uses that material.

    Like I say this can be improved, only dynamic mesh updates are affected and if there are already two non-culled meshes using a material being rendered then you won't need to send the extra mesh either.

    We ended up fixing by double buffering meshes, but this comes at a memory cost which in our case we felt was acceptable.

    I hope that helps


  10. Posts
    25
    I haven't tested it yet (I'm near a deadline, not the best time to be upgrading to beta unity versions) but it seems that the Unity 3.5 preview released today has a relevant entry in the release notes:

    - Various graphics optimizations:
    - Optimizations for OpenGL ES 2.0 to avoid performance spikes with dynamic geometry.


  11. Location
    Washington DC
    Posts
    60
    Quote Originally Posted by froodydude View Post
    // One time
    - Create a mesh for every material in the game, put one 0-area triangle in in and set the culling data to be very large.
    So for a noob who doesn't have a clue of what any of this is.. what are the steps I need to take to use this work-around?

    What I did was add a cube object, reduce it's scale to (0, 0, 0), and added every material to it's mesh renderer component. I'm guessing this is incorrect because I'm still getting 30-60% on Mesh.CreateVBO.


  12. Location
    Cambridge, UK
    Posts
    27
    Quote Originally Posted by goodtimeshaxor View Post
    So for a noob who doesn't have a clue of what any of this is.. what are the steps I need to take to use this work-around?

    What I did was add a cube object, reduce it's scale to (0, 0, 0), and added every material to it's mesh renderer component. I'm guessing this is incorrect because I'm still getting 30-60% on Mesh.CreateVBO.
    I suggest doing the whole thing in code. Create a mesh in code and add just one zero area triangle and material to it. It's possible Unity treats a scale of 0, 0, 0 in such a way that it doesn't render the object (which is why the problem doesn't go away). It does not however make the same tests per triangle. You also need to set the bounds of the mesh to something large so it doesn't get frustum culled.

    Note that really you only want to render these created meshes on problem materials and only when something else using that material is being rendered.


  13. Location
    Washington DC
    Posts
    60
    Still a bit confused.. Not much, but here's what I have so far.

    Code:  
    1.     //Vectors
    2.     var vert:Vector3[] = [Vector3(0,0,0), Vector3(0,0,0), Vector3(0,0,0)];
    3.     var tri:int[] = [0, 1, 2];
    4.    
    5.     //Mesh
    6.     m = new Mesh();
    7.     m.vertices = vert;
    8.     m.triangles = tri;
    9.    
    10.     //??

    Not sure how to add a material to the mesh. Do I need to attach the mesh to a renderer?


  14. Location
    Cambridge, UK
    Posts
    27
    Quote Originally Posted by goodtimeshaxor View Post

    Not sure how to add a material to the mesh. Do I need to attach the mesh to a renderer?
    Yes that looks about right, now:

    1) Add a MeshRenderer to the object and set a material on the mesh renderer.
    2) In code set the mesh on the MeshRenderer.
    3) You also want to set the bounds on the mesh using something like mesh.bounds = new Bounds( 100000.0f, 100000.0f ). This is just ensuring the object is not culled, but there are other ways of doing this such as parenting the object to the camera.

    Note you can add multiple materials to the mesh renderer if you want and use SetTriangles to set each submesh (which the docs claim is necessary).

    Once you've done steps 1 - 3 it should get rid of the spike.


  15. Location
    Washington DC
    Posts
    60
    Quote Originally Posted by froodydude View Post
    Yes that looks about right, now:

    1) Add a MeshRenderer to the object and set a material on the mesh renderer.
    2) In code set the mesh on the MeshRenderer.
    3) You also want to set the bounds on the mesh using something like mesh.bounds = new Bounds( 100000.0f, 100000.0f ). This is just ensuring the object is not culled, but there are other ways of doing this such as parenting the object to the camera.
    I'ved added a MeshRenderer component to the empty object I made in the scene/editor and added the problematic material to it. The same empty object also has the script attached to it. Now, I'm not sure how to do step 2, "In code set the mesh on the MeshRenderer".

    Also, you lost me where you said "you can add multiple materials to the mesh renderer if you want and use SetTriangles to set each submesh". I added multiple materials to the MeshRenderer component but again find myself stuck and out of luck.


  16. Location
    Cambridge, UK
    Posts
    27
    Quote Originally Posted by goodtimeshaxor View Post
    I'ved added a MeshRenderer component to the empty object I made in the scene/editor and added the problematic material to it. The same empty object also has the script attached to it. Now, I'm not sure how to do step 2, "In code set the mesh on the MeshRenderer".

    Also, you lost me where you said "you can add multiple materials to the mesh renderer if you want and use SetTriangles to set each submesh". I added multiple materials to the MeshRenderer component but again find myself stuck and out of luck.
    Sorry my mistake, you need to set the mesh on a MeshFilter so you need to add one of those to the object too.


  17. Location
    Washington DC
    Posts
    60
    @froodydude, thanks for your help so far. I just have a little bit left to make this work:

    Here's what I have so far:
    Code:  
    1.     //Vectors
    2.     var vert:Vector3[] = [Vector3(0,0,0), Vector3(0,0,0), Vector3(0,0,0)];
    3.     var tri:int[] = [0, 1, 2];
    4.    
    5.     //Mesh
    6.     m = new Mesh();
    7.     m.vertices = vert;
    8.     m.triangles = tri;
    9.    
    10.     //MeshFilter
    11.     goObject.AddComponent(MeshFilter);
    12.     filter = goObject.GetComponent(MeshFilter);
    13.     filter.mesh = m;
    14.    
    15.     //MeshRenderer
    16.     mRenderer = goObject.GetComponent(MeshRenderer);
    17.    
    18.     //Bounds
    19.     mRenderer.bounds.SetMinMax(Vector3(-10000f, -10000f, -10000f), Vector3(-10000f, -10000f, -10000f));
    20.     m.bounds.SetMinMax(Vector3(-10000f, -10000f, -10000f), Vector3(-10000f, -10000f, -10000f));

    I tried just running this but the MeshRenderer is still using up a ton of CPU. I have 8 different materials added to the MeshRenderer component in the editor. Do I need to do anything with them in the script? If so, could you give me a short snippet of code that would do this? I couldn't find any references to this anywhere. Thanks again


  18. Location
    Cambridge, UK
    Posts
    27
    Quote Originally Posted by goodtimeshaxor View Post
    I tried just running this but the MeshRenderer is still using up a ton of CPU. I have 8 different materials added to the MeshRenderer component in the editor. Do I need to do anything with them in the script? If so, could you give me a short snippet of code that would do this? I couldn't find any references to this anywhere. Thanks again
    Well from the docs it would look something like:

    Code:  
    1. for( int index = 0; index < mRenderer.materials.Length; ++index )
    2. {
    3.     m.SetTriangles( tri, index );
    4. }

    There is also a distinction between materials and shared materials and tbh I'm not all that clear on what is set when, and what impact this has so you might need to experiment with using both materials and shared materials and read the docs to understand what's going on. My feeling is you need to ensure materials are correctly shared but as I didn't fix the problem this way I can't say for certain.

    What you really need to do is for a frame capture in XCode so you can see the GL calls, this will tell you what the renderer is doing with your objects. The other thing to do is strip the problem back so you only have the bare minimum rendered to cause the problem. Once you have this you can iterate until the problem goes away and then add in another element and see what happens.

    This problem does look like it's potentially fixed in Unity 3.5 btw.


  19. Location
    Washington DC
    Posts
    60
    Thank you do much. You've been very helpful and patient with me. Strange thing is that I'm using the 3.5 dev preview and still getting huge numbers for CreateVBO. Perhaps I'm having a completely different issue. Either way, I'll try what you've suggested and iterate till I find the culprit. Thanks for the help!


  20. Location
    UK
    Posts
    83
    just seen a note in the 3.5 RC1 build notes [ Just available now for download ]

    "Graphics: Fix performance regressions with dynamic/static batching in multithreaded renderer vs. single thread"

    I haven't had a chance to test this yet, but will do in the next couple of hours.
    Will reply in here if this has made a difference.

Page 1 of 3 123 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •