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. Dismiss Notice

Question Why fps does not change when changing the detail of the object?

Discussion in 'General Graphics' started by Zimaell, Jan 25, 2023.

  1. Zimaell

    Zimaell

    Joined:
    May 7, 2020
    Posts:
    338
    I did a simple test - I imported a character with a rig from a blender, two models - high poly and low poly, then I made a prefab and placed it on the stage, then multiplied it, there are 135 such models in total.
    I ran 2 tests - one with a high poly model and one with a low poly model.
    Tests were carried out in normal mode and with URP.
    But the result shocked me, the fps is the same, how is it?
    What am I doing wrong, why is the FPS result with a different number of polygons practically the same?
    Tried it in different ways, but the result is the same, tell me what's the matter?
    How to achieve an increase in fps by reducing the detail?
     
  2. Zimaell

    Zimaell

    Joined:
    May 7, 2020
    Posts:
    338
    screenshots
     

    Attached Files:

  3. DouglasPotesta

    DouglasPotesta

    Joined:
    Nov 6, 2014
    Posts:
    108
    I would guess that 10.2 million polys for your machine is insignificant compared to the baseline cost of the pipeline. The scene looks super simple. If you had more real-time lights, you may see performance changes. Also it depends on cast shadow and receive shadow settings. opaque geometry tends to be much cheaper than transparent geometry. Also Unity makes optimizations to the normal default materials. If they are not using normal maps on your material you don’t incur the extra cost for the vertex shader. The same is true for all the other bells and whistles on the material that are applicable. Try doubling your skinned meshes until you see performance drop on the high poly scene below 30 fps then compare with the low poly scene with the equivalent number of instances.
     
  4. Zimaell

    Zimaell

    Joined:
    May 7, 2020
    Posts:
    338
    in the project everything is set as standard, nothing has changed, light, shadows... I increased the number of prefabs on the scene by 9 times, the fps dropped to 10, but as you can see on the screenshots, there is no difference between high-poly and low-poly models. What are some ideas?
     

    Attached Files:

  5. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,660
    Geometry is clearly not your bottleneck, so probably a powerful GPU you have there.

    The amount of drawcalls however could be, there's +10000 of them in both cases (the "batches" number in the perf window). That's time spent by the CPU preparing and sending data to the GPU, the more individual meshes you render (instead of batched objects) the more drawcalls you'll have, and the slower rendering will be. The antidote to a lot of drawcalls is batching.

    You can think of drawcalls as colors in a painting: every time you switch to another color, you need to clean the brush, close the lid of the previous paint bucket, open the new paint bucket, and resume drawing. No matter how fast you draw, if you have to switch to a different color every time you draw something in your canvas you will waste an immense amount of time. Batching attempts to sort and group objects in the canvas by color so that you can: open each paint bucket only once, draw everything that uses that paint color, and be done with it.

    I would use the profiler to get a closer look at what's happening under the hood. Chances are you won't see a lot time spent in WaitForPresentOnGfxThread, which is where the CPU waits for the GPU to finish rendering. A lot of time spent in WaitForPresentOnGfxThread would indicate the GPU is slower at painting than the CPU is at giving it things to paint.

    Another potential problem is animation. You've got more than a thousand skeletally animated meshes, if skinning is not being performed in the GPU using compute shaders, having so many animated meshes could hurt performance.

    Note that in general, modern desktop GPUs can churn trough ungodly amounts of geometry. You're much more likely to hit a bottleneck in basically any area other than poly count.
     
    Last edited: Jan 26, 2023
    Zimaell likes this.
  6. Zimaell

    Zimaell

    Joined:
    May 7, 2020
    Posts:
    338
    Is it possible to somehow reduce the detail of the armature, apply something like the LOD system to the armature, as for meshes?
    What are the options for optimizing animated models?
    I think I'm not the first who faced such a question, what are the solutions on this issue?
     
  7. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,660
    LOD in this case won't help at all, since geometry rendering is not the problem as you just discovered.
    The drill is always the same: 1) profile, 2) determine bottleneck, 3) choose approach to eliminate bottleneck.

    If you're looking for crowds, you could use vertex-based animations as long as the animations are not many or not too complex. Similar to this, you could store the animation vertex data into a texture and use vertex texture fetch instead of using procedural animation, which allows you to play back arbitrary hand-authored animations.

    Both of these are very common techniques in games, and there's a myriad variants of them.

    However: if you need independent control of the animation of each and every character, want to have blend trees, IK chains and whatnot, you just can't brute-force your way by having that many SkinnedMeshRenderers on screen at once.
     
    Last edited: Jan 26, 2023
    Zimaell likes this.
  8. Zimaell

    Zimaell

    Joined:
    May 7, 2020
    Posts:
    338
    in your example, I see a prepared animation, in my case, I think it will not work because I don’t know where and what animation will be played in advance.
    so that you understand the essence of what is happening, I will give an example of games like strategies (red alert, starcraft...), I'm interested in what method is used there, I think not the same as in the above example (maybe I'm wrong). I have not started the following tests yet, but advise in which direction I should go, here is what I think to try:

    1. create several different prefabs in which the model will differ in the number of polygons and the number of bones, for example, at a far distance, no finger bones needed, and at a very distant distance, use a model without a rig.
    2. use these different modifications as prefabs for the lod system, or turn on the necessary prefabs by launching the beam into the camera, turn on the necessary ones based on the distance.

    Tell me, am I in the right direction, or is it better to even start testing like this, and use another method?
     
  9. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,660
    You can use vertex texture fetch instead of procedural animation, and just blend between multiple animations if you need. You even get linear interpolation between frames for free. Here's a short video on the subject, using Godot but the technique is exactly the same in any engine:


    And a short article:
    https://medium.com/tech-at-wildlife-studios/texture-animation-techniques-1daecb316657

    Combined with instancing, you can easily render several thousand animated characters. It's more limited than skeletal animation (can't use Unity's built-in blend trees, can't use IK, etc) but it is far more performant.

    Depends on how many characters you need to have on screen, how many bones per character, how many vertex influences per bone your animations require in order to look good, how many separate (sub)meshes your units are made of, your target platform (as you may be able to benefit from GPU skinning), whether you can benefit from impostor rendering and if so, which kind, and a LOT other things. It's way too much information to be condensed in a single post.

    If you must use skeletal animation, the crucial thing here is understand what linear blend skinning is, how it works, and how it relates to batching. Start by reducing the CPU workload by using fewer weights per vertex, try to use only 1 material/submesh per character, and make sure they're not updated when offscreen. Also try enabling GPU skinning in your project's build settings. Note these are just general tips, using the profiler to determine what the actual problem is is usually the best approach.
     
    Last edited: Jan 26, 2023
    Zimaell likes this.
  10. Zimaell

    Zimaell

    Joined:
    May 7, 2020
    Posts:
    338
    In general, the option with texture animation is definitely not suitable for me, objects have many animation trees and interrupt one animation and start on another.
    And this technology is difficult for me, except maybe there are some converters.

    I ran a series of tests and got the following results:

    1. several objects (of different quality) in the prefab that are turned on / off based on the distance to the camera, and I want to note that they will need to be switched by a script and not by a lod system, it works slower with a lod system.

    2. the first object has everything, the second has no finger bones, the third has one solid body bone (hips), also the 2nd and 3rd object in the bone weight settings are set to 1.

    3. applied the "optimize game objects" option. all these points helped to increase fps from 8-9 to 19-22, 1215 such prefabs were used in the test.

    Tell me what else can be done? are there any other options?

    And thanks for the help and advice.
     
  11. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,660
    This is by far the most performant way to do it, not only it offloads animation to the GPU but also allows to batch multiple characters together, further improving performance. Note that there's ways to automate it: Here's a video showing how to use a converter Unity made for specifically your use case:


    And here's the blog post for the same converter:
    https://blog.unity.com/technology/animation-instancing-instancing-for-skinnedmeshrenderer

    I can't think of anything else. Enabling compute skinning in your build settings will give you a performance boost, in case your platforms supports compute shaders.

    kind regards,
     
    Zimaell likes this.
  12. Zimaell

    Zimaell

    Joined:
    May 7, 2020
    Posts:
    338
    Thank you very much for your help.
     
    arkano22 likes this.
  13. Zimaell

    Zimaell

    Joined:
    May 7, 2020
    Posts:
    338
    I understand it does not work with urp yet? as far as I understand, something needs to be changed in the shaders, until I found a sensible answer on this topic...
     
  14. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,660
    No it doesn’t work with URP out of the box, as it needs some extra stuff added in the vertex shader. Should be fairly easy to adjust to URP though, if you’re comfortable with shader writing or ShaderGraph.