Search Unity

12 FPS on a 500m x 500m Map, what can I do?

Discussion in 'High Definition Render Pipeline' started by John_Leorid, Jul 25, 2020.

  1. John_Leorid

    John_Leorid

    Joined:
    Nov 5, 2012
    Posts:
    651
    Hi ^^

    We have been working on a FPS Game with a bunch of assets and half of the 500x500 Map is filled with Objetcs - for the most part we get ~20 fps in the Build (.exe)

    Seems like the Directional Light which casts realtime Shadows is a big part of the performance problem.
    I get about 70fps if I disable the light and bake the occlusion culling.

    So Occlusion Culling only works if there is no directional shadow casting light. Setting the Light to mixed (because we have some dynamic Objects (Rigidbodies, Enemies, Player Weapon & Hands) and baking the shadows does not help at all.

    No shadows is not an option, so what can I do to improve the performance?
     
  2. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    Bake your lighting and reduce the shadow distances
     
  3. John_Leorid

    John_Leorid

    Joined:
    Nov 5, 2012
    Posts:
    651
    As I said:
    "Setting the Light to mixed (because we have some dynamic Objects (Rigidbodies, Enemies, Player Weapon & Hands) and baking the shadows does not help at all."
     
  4. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    and how big is your shadow distance settings?
     
  5. rz_0lento

    rz_0lento

    Joined:
    Oct 8, 2013
    Posts:
    2,361
    What kind of hardware you are using to test this? I ask because HDRP is pretty unforgiving on weaker GPUs.

    You can slim HDRP down by disabling features you don't use from both HDRP asset and default framesettings.
     
  6. Bordeaux_Fox

    Bordeaux_Fox

    Joined:
    Nov 14, 2018
    Posts:
    589
    From my experience, the performence should be not that bad unless you did not optimized your scene. We need to know more details about your project and setup. Can you some Profiling and check what takes your FPS? If it's just the Directional Light, you have to limit the shadow distance. Maybe you have just too many shadow casters. Can you combine some meshes in one mesh?
    And what's the target hardware you test with?
     
    Last edited: Jul 27, 2020
  7. John_Leorid

    John_Leorid

    Joined:
    Nov 5, 2012
    Posts:
    651
    "Can you some Profiling and check what takes your FPS?"
    Did that already, my scripts are fine, they eat almost nothing, simple standard Unity FPS Controller, Weapons and so on, almost no update loops - scripts are not the problem, neither are physics.
    All the performance is lost on the graphics side. I just don't know if it's on the CPU or GPU Side and I don't know how to get that information, as the GPU Time is not shown

    "If it's just the Directional Light, you have to limit the shadow distance."
    It's not the directional light, it's the sheer number of objects.
    Object Count --> You have 19824 objects in your scene, 11858 are renderers.
    Various different materials out of different asset packs combined with pro-builder objects and some custom textures/materials. Without Occlusion Culling we have <20fps and more than 700 SetPassCalls when looking at certain angles.
    When the Occlusion Culling is working, the framerate ist >70fps. The Problem is, that the directional light breaks the occlusion culling.
    If the directional light is turned off or set to baked, the occlusion culling works and we get the wanted framerate but then, enemies don't have shadows.
    If the directional light is turned on and set to realtime or mixed, I get very low framerates, when looking along the kind of linear map and ok-framerates when looking sideways. Conclusion: Occlusion Culling does not work when the directional light casts any kind of shadow, no matter if it set to realtime or mixed.

    Why would it matter where I am looking at in a closed room (yes, doors set to occluder static for testing purposes) when occlusion culling would do it's job?
    It doesn't - I can look around 360° when the directional light (only light source in the entire scene) is turned off. But I can't (looking along the map gives terribly slow framerates, while looking sideways works fine) when it is turned on.

    Maybe you have just too many shadow casters. Can you combine some meshes in one mesh?
    99% of them are set to Static and StaticBatching is turned on, so I expect unity to combine them. Combined Meshes are not nice to work with - lets say 5 rocks get combined into one mesh, then I can't move them individually anymore.

    My Hardware Specs:
    upload_2020-7-27_18-26-47.png
     
  8. Bordeaux_Fox

    Bordeaux_Fox

    Joined:
    Nov 14, 2018
    Posts:
    589
    On which Unity and HDRP is your project?
    Occlusion Culling cleary works for all of my three HDRP projects. Currently, I'm using Unity 2019 LTS and HDRP 7.4.1.
    If you made sure it's not an user error, you should file a bug report that Occlusion Culling is not working as intended.
     
  9. John_Leorid

    John_Leorid

    Joined:
    Nov 5, 2012
    Posts:
    651
    Unity 2020.1.0b13 (we'll upgrade it soon), newest HRDP Version (Version 8.1.0 - April 24, 2020).
    I think the shadow calculation keeps calculating shadows for everything on the map, no matter if occlusion culling is turned on. So all materials and objects are loaded for the shadows even when they are not visible.
    But it should only load dynamic objects and everything above them (non moving directional light as single light source) to calculate their shadows, instead of everything.
    So I don't think it's a bug, I think thats just how the lightning works.

    One Solution (maybe?) would be to manually disable/enable Objects on the map based on the player position (manually loading and unloading parts of the map) because it won't render disabled objects.
    But maybe theres a better solution somehow? Like a spot light, only for shadows, parented to the position of each enemy which gets turned on when the enemy is visible? IDK.

    Any Solution that avoids placing trigger colliders manually to hide or show map-parts would be nice.

    Or maybe it is a bug? IDK if the shadow calculation is supposed to ignore occluded objects or if there is any kind of intelligent algorithm which knows which objects are relevant for shadows on visible dynamic GameObjects?
     
  10. Bordeaux_Fox

    Bordeaux_Fox

    Joined:
    Nov 14, 2018
    Posts:
    589
    Last edited: Jul 27, 2020
  11. John_Leorid

    John_Leorid

    Joined:
    Nov 5, 2012
    Posts:
    651
    Thanks a lot for the link.
    After googling more and reading details about how the shadowmask is supposed to work (right after baking the lightning, with my directional light set to "mixed" and seeing no shadows in the distance) I found out, that "shadowmask" (which I was baking all the time) was disabled in the HDRP Asset.
    HDRP is actually quite complicated, theres the defaultAsset where you can configure the frame settings for the camera (where you have to enable shadowMask) then theres the HDRP Asset (per Quality, so actually 3 of them) where you have to enable shadowMask and then you have to bake it.
    Also the camera can override frame settings individually and I really don't understand why this feature has to be enabled in two different settings to (hopefully) work...

    Right now I am baking it again, with my mixed light and maybe I will get a nice combination of realtime & baked lightning with >60fps or maybe it won't work..
     
    Last edited: Jul 29, 2020
  12. John_Leorid

    John_Leorid

    Joined:
    Nov 5, 2012
    Posts:
    651
    Ok, so I changed the setting, baked the lightmap again now my frames are up to 26-32.
    I set the shadow distance, watched a lot of videos about shadow/lightning in HDRP and my final guess is, that we have too many object to render any kind of shadow at all.
    Setting the distance below ~50m will create ugly transitions between the baked shadowmap and realtime shadows.
    Right now I am baking the shadows again with a higher resolution (it is already running for >1h) maybe it will look ok then..
    Also I had a look at the frame debugger and the profiler of course. Seems like I am slightly CPU bound.
    A reference number of how many draw calls / set pass calls we should have would be really awesome - currently we have something above 1000 set pass calls - caused by various Art Assets and different shader keywords on their different materials.

    Camera stacking also costs ~3.5 milliseconds, turning the second camera off (which is used to avoid the FPS weapon from clipping through walls ... but it doesn't work with shadows, so I'll have to find another solution) pushes the framerate to 30-33fps - still far from the required 60fps. (in the build (.exe) of course)

    Is there no easy solution to find out what is affecting the framerate the most?
    Profiling scripts is 1000 times more easy - I just have to turn on "deep profling" and get the exact line that is causing problems.

    But graphics? The Frame Debugger tells me nothing about the performance, it just shows step by step what is rendered.
    Profiler only tells me if I am GPU or CPU bound, instead of pointing out which objects or HDRP features (like shadows) are killing my frames.

    Profiling Graphic performance always comes down to disabling things step by step until the framerate magically goes up - that's the most inefficient solution to debug anything.

    Last time was after a game jam, the trees on the terrain lowered the frames from 70fps to 15fps - after hours of disabling random gameObjects in the scene, I finally disabled the terrain, then deleted all trees and got my 70fps back.
    There has to be a better method to track such things down, right?
    Please tell me theres a better method.
     
  13. rz_0lento

    rz_0lento

    Joined:
    Oct 8, 2013
    Posts:
    2,361
    At least Nvidia Nsight does give you some perf metrics on gpu side.
     
  14. John_Leorid

    John_Leorid

    Joined:
    Nov 5, 2012
    Posts:
    651
    Now I think I start to understand the System.
    So theres the HDRP Default Settings inside the Project Settings which contain the basic values for any kind of post processing.
    The HDRP Asset and the Quality Settings provide values for these settings ("low" / "mid" / "high" for a lot of things that can be setup in the HDRP Default Settings).

    By creating a volume you can basically override the HDRP Default Settings. Same for the Camera Frame Settings and Reflection Settings.

    The camera has some additional settings like AntiAliasing, Dithering, Stop NaNs and so on - some of those are doubled? Dynamic Resolution can be Setup in the ProjectSettings and on the Camera, Stop NaNs too.

    Then Shadows - they consist of:
    - Light-Settings for example on the Directional-Light(every frame / onEnable / ..)
    - Volume Settings (either Default Volume or Scene-Global / Scene-Local)
    - Default-Scene Settings in the Camera (where you can turn on ShadowMaps, ContactShadows, ShadowMask)
    - On the Individual MeshRenderers (CastShadows OnOff)
    - The LightningSettings in the "Lightning" Tab (Window/Rendering/Lightning) where you can bake a ShadowMask, which will then be used for distant shadows with some blending (blending can be setup in the Volume Settings mentioned above)

    Maybe I am still missing something because I disabled all of them, then built the game and still had realtime Shadows.
    But now with 40fps-70fps (40fps outdoor, 70fps indoor). I still want to get those numbers up to >60fps at all times.

    Gosh, this is way more complicated than writing some scripts. Why are all those settings so shattered? Atleast there should be some kind of Debug-Windows which shows every currently active Override and sums up all PostProcessing/Volume Settings so I can understand what is affecting the currently rendered image..

    If I am still missing any hidden Setting, please tell me. ^^
    I'd really like to know why I am still having realtime shadows, when I disabled them in my Global Volume, in the Default Volume Settings and made sure that my player is not inside any local volume.
     
  15. John_Leorid

    John_Leorid

    Joined:
    Nov 5, 2012
    Posts:
    651
    Got it. If you turn on "Shadow Maps" in your (default or cam specific) Frame Settings For your Camera, realtime shadows will be automatically calculated according to your light in a range of about 30m.
    You can control the Range for Directional Lights in the Volume Override "Shadows" and for all other Lights in their specific settings.

    Now after disabling almost everything in the default frame settings for the camera + default Volume Setting + disabling all volumes in the scene + tuning the quality settings + configuring the HDRP Asset properly + disabling the second (weapon clipping) camera, I finally get 60-120fps.

    Insane how many different options, checkboxes, overrides are in this Render Pipeline.
    Shadowmask for example. It has to be turned on in
    "ProjectSettings/Quality/HDRP/YourHdrpAsset/Lightning",
    "ProjectSettings/HDRPDefaultSettings/DefaultFrameSettings/Lightning",
    "ProjectSettings/HDRPDefaultSettings/Default Volume Profile Asset"
    and can be configured in "ProjectSettings/Quality" (Shadowmask or Distance Shadowmask)

    4 Menus to control one feature! Plus one more Menu to bake it.
     
  16. rz_0lento

    rz_0lento

    Joined:
    Oct 8, 2013
    Posts:
    2,361
    John_Leorid likes this.
  17. matsakovd

    matsakovd

    Joined:
    May 29, 2019
    Posts:
    22
    Hi. I am facing the same lighting optimization problem on my project. Can you share the details of how you got the performance boost?
     
  18. John_Leorid

    John_Leorid

    Joined:
    Nov 5, 2012
    Posts:
    651
    This was more than a month of work, so I'll try to cover everything here:

    TLDR: I just disabled every single HDRP Feature in every single window / inspector / tab, then after I finally got my wanted framerate, slowly enabled some of them again, one after another.

    First thing was of course profiling - to make sure my scripts are not the problem.
    Then I
    - set almost all scene objects to static (except for doors, enemies, elevators and moveable boxes/chests)
    - disabled OccluderStatic from (semi-)transparent and small objects such as Windows, Fences, Trees, .. in the static dropdown (because baking the occlusion crashed the editor)
    - found out we had numerous high poly objects in the scene (>100.000 Triangles), so I wrote a tool to detect those and told the leveldesigner to use this tool and replace all of them with low poly ones
    - after this was done, I was able to bake the OcclusionCulling in ~2min without the editor crashing
    - then I wanted to check if the OcclusionCulling is working and discovered: it isn't
    - so I disabled all lights and suddenly, the performance was way way better
    - setting all lights to static also worked, so I just wanted realtime-shadows from my directional light for dynamic objects while showing baked shadows for all other objects
    - light baking also crashed the editor mutliple times until I reduced the "Lightmap Resolution" from 40 (default value) to 4
    - I also lowered the numers of "Direct Samples", "Indirect Samples", "Environment Samples", set Bounces to 0, increased the "Max Lightmap Size" to 2048 and set "Lightmap Parameters" to "Very Low Resolution" so I was able to bake lightning in ~20min on the CPU (GPU does not work with big scenes afaik, atleast it didn't work for me)
    - now I had my baked shadows and wanted to show them for all static objects and "add" dynamic shadows of my dynamic objects
    - then I got stuck, only static lightning was not suitable but I wasn't able to set my directional light to anything but static and keep the occlusion culling working as before

    - after discovering this, I wrote this forum thread
    - at this point, I just wanted to disable shadows altogether while only showing the baked ones, with my directional light set to mixed
    - I disabled all Volumes in my Scene
    - I disabled custom Frame Settings for all my Cameras (you want to control them from the project settings later)
    - and still had all kinds of realtime shadows and effects in the scene, so I checked the HDRP Asset again
    - so I checked the project settings, the Quality tab and tried to just turn everything off
    - then the HDRP default settings - and there are the settings which influenced my framerate the most
    - after disabling things there, I was at the point of my second last post in this forum thread
    Everything from there is already written in the thread. ^^

    PS: Maybe I should mention that this wasn't a HDRP Project from the beginning, we started with standard Unity, then switched to URP for our Prototype, found out that we are going to have High End Graphics and then switched to HDRP which took about one week because of errors and reimporting art assets to upgrade their shaders automatically (URP to HDRP conversion has to be done manual, as HDRP cannot upgrade URP materials).
     
    Last edited: Jul 31, 2020