Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Profiler: What are "Calls"?

Discussion in 'Editor & General Support' started by John-B, Jan 4, 2014.

  1. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,259
    In the Profiler, I see several Update functions that should not be running (return immediately because certain conditions are false). Under the Total column, they show 0.0%, which is what I'd expect. But under the Calls column, some have large numbers, like 65 or 110. When I select one and look at the detail on the right, I see a long list of colliders (the objects in the scene this script is attached to), and each has a 1 in the Calls column.

    Is the Calls column Draw Calls? If so, why would a collider with no geometry or texture generate a draw call? If every collider in the scene generates a draw call, that would explain the huge number of draw calls and slow performance I'm seeing. Can anybody tell my why this is? Is Calls in the profiler something other than draw calls? If not, maybe I don't understand what draw calls are. I thought they were only for mesh geometry and textures.
     
  2. jgodfrey

    jgodfrey

    Joined:
    Nov 14, 2009
    Posts:
    564
    First, I'll qualify my response by saying that I don't have/use the Unity profiler, however I do use other profilers professionally.

    Generally speaking, "calls" is just that - the number of times a method is called while being profiled. Based on your description, the offending Update methods will still be *called* (because they exist), but don't really do anything (based on the current situation). So, I 'd expect them to show up in the "calls" totals, but they really don't take much CPU time (hence the mentioned 0.0%).

    Jeff
     
  3. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,259
    OK, that makes sense. Thanks. I wasn't sure if Calls was short for, or the same as, Draw Calls. Unfortunately, it doesn't help explain my low frame rate.
     
  4. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,649
    Yes, it's the number of calls made to the function in question.

    Note that an Update() function that returns immediately is still costly - Unity spends time processing the call and making the jump from engine-side to Mono-side, even if all you do once there is head back straight away. It's more efficient to disable components that don't need Update() calls, or to replace the Update() calls with coroutines/invokes (e.g. if you do need to do regular work but only once a second or something).

    As far as your low framerate is concerned, I suggest posting a screenshot of your profiler view so we can see the other CPU entries, along with a screenshot of your Statistics panel (in the Game view).
     
    gotiobg likes this.
  5. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,259
    I can't disable any of those components because they are attached to collider, and need to be active. But I don't think those calls are the main bottleneck.

    I have a 16 x 8 grid of tiles, and each tile can have a game piece. When there are a lot of game pieces and the entire board is in view, the frame rate on iPad 2 drops to around 15 fps. On close-up views, even when the camera is moving, it goes up to close to 60 fps. It stays around 60 on an iPad 3, and I haven't tested on an iPad 2 yet. n close-up views, even when the camera is moving, it goes up to close to 60 fps. The scene is mostly static, most of the time only one object is moving.

    I started out with over 1000 draw calls at about 12 fps with my test scene, but with batching, lighting, and other settings got it down to around 750 and 15 fps. I found the best performance with static batching off, dynamic batching on, optimize mesh data off. All my textures are square, 512 x 512, or smaller and compressed (full res vs. half res quality didn't make much difference). I also have 6 render textures now, and I started out with zero. I'm not sure where those came from, as I've only seen them in the stats before when deferred rendering path was on, and I'm using forward.

    I'm not sure what else I can do to reduce the number of draw calls without reducing the number of vertices. Each game piece is only a few 100 vertices, but they add up, and I don't know if I can simplify them any more. Any suggestions?

    I just noticed the frame rate in my screen capture is way low. That's because I was doing a screen capture. On my Mac it's around 85-90 fps.
     

    Attached Files:

    Last edited: Jan 5, 2014
  6. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,649
    I don't see what the colliders being present has to do with disabling the components - note that I'm talking about disabling the components via setting Behaviour.enabled, not deactivating the entire GameObject - disabling a component prevents Start/Update/LateUpdate calls from happening but that's all. But OK, it's probably not a big deal as you say.

    Well, if the FPS changes based on whether the board is in view or not - i.e. with a full board of pieces but the camera pointed in another direction, your framerate is fine, but with the camera pointed at the board it drops - then that implies it must be a graphical issue. If the framerate is still poor with the pieces in the scene even when the camera is pointed away then it's probably not a graphical issue.

    750 draw calls is still pretty high for mobile, I think. Like, I target 1200 draw calls for a GeForce 8800 on a desktop PC.

    Could be shadows?

    Number of vertices won't affect the number of draw calls. More important is the number of different meshes/GameObjects involved in a piece - ideally each piece has just one mesh and one material, resulting in one draw call. So what are your pieces like?

    Can you take a fresh screenshot of the Statistics window without screen capture stuff interfering, and include the Profiler screenshot like I asked originally? Other than the draw calls seeming high I'm hesitant to conclude anything else from that Statistics window because the numbers aren't representative of what you're actually seeing.
     
  7. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,259
    The frame rate changes based on how much of the scene is in view. If the entire board is visible in a wide view (most of the time), the frame rate is at its lowest, 12-15 fps. When the camera is zoomed in so only a few tiles are visible, the frame rate goes up to 60 fps, even while the camera is panning around. More objects visible = lower frame rate.

    Yes it is.

    No shadows.

    Each piece has more than one mesh. They were imported OBJ objects, and I don't know how to decrease or combine meshes. Vertices are already reduced as much as possible (any more, and I'd have square spheres). Each piece also has more than one material, as few as 2 to as many as 5; most have 2-3 materials. But many game pieces are instances of the same object, so they use the same textures/materials, and many different pieces share some of the same materials/textures.

    The only thing affected in the stats window is the frame rate, all other values are accurate. Attached is a capture of the profiler window. Still don't know where those 6 render textures are coming from.
     

    Attached Files:

    Last edited: Jan 5, 2014
  8. NomadKing

    NomadKing

    Joined:
    Feb 11, 2010
    Posts:
    1,461
    That's a very high amount of draw calls for such a simple scene.

    As superpig mentioned, number of vertices won't be areal issue here, but the draw calls will especially on mobile devices. With an average of 3 materials per piece, your full board of pieces is producing almost 400 draw calls (If you have similar inefficiencies on your board tiles, probably more). Getting these calls down to 1 per board piece should be your goal.

    Merging models together can be done in a number of ways inside and outside of Unity, but a lot of the specifics depend on the exact visual look your going for. If you could post a few shots of the pieces and what your aiming for visually, perhaps someone can offer some specific advice to help :)
     
  9. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,649
    Right. Then yeah, this + your draw calls count + your statistics and profiler measurement -> object batching is your problem.

    Ah, OK, yeah, this is your problem.

    If the multiple meshes in the pieces do not move independently - i.e. the piece is a single rigid unit, just made of multiple meshes - then you should be able to 'attach' them together in a 3D editor app (in Blender it's called 'joining' objects). This will produce one mesh.

    If the multiple meshes in the pieces *do* move independently - i.e. the piece has animated sub-parts - then, after joining together all the 'rigid' components, you could convert the remainder into a skinned mesh. Attach all the meshes together as in the non-animating case, but then create bones for each moving piece and 'skin' the relevant parts of the mesh to the bones. Then you'll be able to still animate by moving the bones, but Unity will still only have a single mesh to render. The downside of this is that you then incur skinning costs, but it's possible that'll be cheaper than the multiple draw calls - I'd merge the rigid pieces first and see where you're at.

    Either way, the other major thing is combining your materials further; you can do this by stitching textures together (iPhone 3GS upwards supports textures as large as 2048x2048 ) and then using the resulting texture/material to UV map multiple pieces. Parts that are transparent vs non-transparent will need separate materials because they use different shaders, but if all your different materials are actually using Mobile/Diffuse with different textures then there's no real need for them to be separate materials. Note that while reusing a material across different objects is better than not, it doesn't help much with draw calls, because meshes on separate objects have to be drawn separately anyway. (Dynamic batching helps a little with this but it'll help even more if you reduce the number of unique materials in play).

    Also, make sure that objects which don't move are flagged as static, with Static Batching turned on. If the objects don't exist in the scene at edit time (e.g. you're dynamically generating boards) then you could instead try adding the CombineChildren.cs script to the root of your static geometry once you've constructed it. That'll automatically merge meshes at runtime, combining materials where possible; you could use CombineChildren.cs for your playing pieces too but I'd recommend combining them in the 3D editor if possible because it's best not to do things at runtime when you don't have to.
     
  10. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,259
    I figured out how to combine meshes in my OBJ files, and that made a big difference. I now have one mesh per material, and that reduced the draw calls down to around 360 (from 750). FPS is now up to around 28-30 on iPad 3 (still afraid to try on iPad 2). I still have a few more objects to do this for, but they're not a big part of the scene and shouldn't make too much of an additional difference.

    All objects that don't move are already static (the prefabs, that is), but static batching has no effect on draw calls or frame rate (I thought you're not supposed to use static batching on iOS). Is that because the objects don't exist until runtime? Dynamic batching however does make a difference.

    I think the only thing left is combining materials into an atlas, but I don't really know much about that or how to do it.

    One other thing, my render textures are now up to 10 (started with 0). I have no idea what those are or why they keep increasing, but as long as frame rate is increasing, I'm not complaining.

    Thanks for the help. This has been a learning experience. I think I might finally be starting to understand draw calls.
     
    Last edited: Jan 6, 2014
  11. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,649
    Cool :)

    Yes; static batching effectively does the combine-meshes-into-single-object thing for all 'static'-flagged objects that are in the scene at build time. If you're creating your scenes by instantiating stuff at runtime, static batching will do nothing.

    The closest runtime equivalent is the CombineChildren.cs script, in the standard Scripts package (Assets->Import Package->Scripts). When this component is attached to a GameObject, it combines all children of that game object into a single mesh. So, if you're building up your level at runtime, you could make sure all the pieces are parented to the same thing, and as a final step AddComponent<CombineChildren> to that shared parent. Unlike Static Batching, this will ignore Static flags on things, and the meshes really do stop being separate things - so e.g. culling is performed against the entire combined mesh rather than against the individual pieces of it. Still, worth a try I think; and there may be a middle ground you can reach, like combining 'chunks' of level geometry so you get some reductions in draw calls while still maintaining some granularity in the culling.

    I'd probably solve the batching-level-geometry problem before looking at this, though it's a good thing to know how to do in general.

    Well, you could run a little code like:

    Code (csharp):
    1.  
    2. var RTs = (RenderTexture[])Resources.FindObjectsOfTypeAll(typeof(RenderTexture));
    3. foreach(var rt in RTs)
    4. {
    5.    Debug.Log("RT name: " + rt.name + " width: " + rt.width + " height: " + rt.height, rt);
    6. }
    7.  
    and look at the names/sizes to see if anything clues you into what's going on.Bear in mind that if you're doing this in the editor, though, I've got a feeling that number will include render textures that Unity uses for things like rendering previews of objects. The RT count when you're on-device is much more important.
     
  12. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,259
    I made some additional minor improvements. I disabled the behaviors ("behaviours" in Unity) that were running unnecessary Updates, and that helped with the frame rate a bit in Unity, but it's not very noticeable on the iPad. I also converted some Updates to coroutines, and the result was the same, some improvement in Unity but not much on iPad.

    One thing I found was that code running in an Update doesn't always work the same as in a coroutine. Many of the Update functions control animation, and for some, turning them into coroutines resulted in jerky animation, especially at start and end. So I had to leave much of my core animation control in Updates.