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. The 2023.1 beta is now available for testing. To find out what's new, have a look at our 2023.1 feature highlights.
    Dismiss Notice

Question DrawTransparentObjects excessive time, is this canvas related?

Discussion in 'Profiler Previews' started by LostShepherd, Aug 20, 2022.

  1. LostShepherd

    LostShepherd

    Joined:
    May 31, 2019
    Posts:
    36
    Hi,

    I've written a simple game and am relatively new to the profiler but have been learning it the past couple of weeks. My game is a basic 2D mobile game, not graphically intense at all e.g. plain black background simple colour objects and a few shaders nothing major. There is a little bit of 2D physics going on as there are up to 60 balls that can collide and effect balance but other than that nothing much going on.

    Currently testing on Android and it runs perfect on a modern phone e.g. Motorola G10 and I am hoping for a budget of 32ms or 30fps.

    I wanted to bench mark on an older phone though so dug out my old Samsung Galaxy S4, I would say it is passable and playable but not nicely smooth.

    On digging into the profiler and reading around what I have learned I think it may be an issue caused by having a single Canvas with everything on it, the canvas has two count down timers which are constantly updating in game and hidden panels \ buttons that appear at specific intervals e.g. end of level. There is also a score that gets updated.

    Really I'm just seeking some clarification if I am reading the profiler correctly or going down a dead end, what I think is causing the spikes and framerate drop when playing is the DrawTransparentObjects method which will spike from about 1/2ms right up to near 20ms on a spike pushing my game way up to 60+ ms.

    I'm thinking that if I reworked the canvas and split the constantly updating parts out like the timers and left the more static elements together e.g. pre-level notifications, end of level summary that I could bring this time down significantly.

    Am I on the right track here?

    *Also I have ran through and optimised a lot of other things I was doing wrong also e.g. referencing yield returns, avoiding over coding in update method, using object pools. I feel I have optimised a lot of the code and certainly noticed improvements from the reworks, but its just not enough for the older phone.

    Thanks in advance!
    LS
     

    Attached Files:

  2. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    1,907
    Hello,
    This might have better fitted into the URP or UI subforums as it's less related to the process and tooling of profiling in Unity and more to how the features in this area operate. So I don't have too detailed an understanding of the specifics here but it does indeed look like your transparent elements getting rendered for the UI camera take up a good chunk of your frame time.

    The 2 UI Profiler Modules (addable via top left-hand drop-down in the Profiler Window) and the Frame Debugger might provide more details of why that is, e.g. which elements are rendered in which batches and how that differs to other frames.

    The general advice, that I'm not sure if it still fully applies here, is indeed to split out the more dynamic parts of the UI into their own canvas, so that updates to these elements don't dirty the entire canvas hierarchy, causing necessary recalculations if layouts and what is or isn't visible to be rendered
     
    LostShepherd likes this.
  3. LostShepherd

    LostShepherd

    Joined:
    May 31, 2019
    Posts:
    36
    Thanks Martin,

    I didn’t get a chance yet but will have a shot at separating out the timers and the score dialogue from the other relatively static UI elements and see how that goes.

    I’m sure if they would each need their own canvas or it would suffice to move the more dynamic elements en masse onto a single separate canvas or provide a separate canvas for each?

    Thanks,
    N
     
  4. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    1,907
    I think everything that would update at close to the same frequency could be grouped together. Also make sure to keep the hierarchy complexity tow as that has an impact on the recalculations cost.
     
  5. LostShepherd

    LostShepherd

    Joined:
    May 31, 2019
    Posts:
    36
    Thanks Martin,

    I ended up splitting out the frequently updated canvas items individually e.g. the score value. radial timers and the two text based countdowns. It didn't really make much difference though unfortunately, I am still getting those spikes in the profiler. The hierarchy in those reworked canvas items is very simple now also.

    When I drilled further I see an awful lot of BatchRenderer.Flush followed by a StdRenderer.ApplyShader calls, these seem to be adding up and costing significant time.
     

    Attached Files:

  6. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    1,907
    Hmm, yeah, I was wondering if re-layouting costs shouldn't be captured under lilac UGUI.Layout samples ...

    Have you checked what the Frame Debugger and or the UI Profiler modules say about why these UI elements can't be processed in a single batch?
     
    Last edited: Sep 9, 2022
  7. LostShepherd

    LostShepherd

    Joined:
    May 31, 2019
    Posts:
    36
    Unity Version ~ 2020.3.25f1
    Profiling on Samsung Galaxy S4 connected via USB

    So I've done a ton of optimising ~

    Split out UI elements into logical canvas's e.g. dynamic \ static
    Ordered UI elements in hierarchy to reduce frame draw
    Substituted proper material to avoid default shader in UI sprites
    Significantly reduced canvas hierarchy complexity by removing anything unnecessary
    Updated Shaders to UPR

    More generally
    Removed almost all GetComponent statments
    Cached references in scripts
    Changed physics loops to use FixedUpdate instead of Update
    Removed any unused code
    Cached yield statements
    Changed TMP_Pro text pool to sprite pool
    Organised and put all my sprites on an Atlas
    For my timers I got rid of any .ToString updates
    Changed RigidBody2D Transform moves to be RigidBody moves to avoid physics recalculations
    Reduced the physics time step
    Set VSync to EveryVBlank
    Significantly reduced the number of items in my pools
    Reduced camera's from 2-1
    Simplified the UPR asset as much as possible e.g. no shadows \ lights \ no post processing \ no HDR \ set SRP & Dynamic batching (very simple game no need for that stuff)

    I've also been in the quality settings and used the lowest setting possible


    So with all that I do see an improvements but its still missing frames and I consistently get >32ms on basic menu UI frames where there is no physical gameplay. I don't quite see really long frames now like I was getting e.g. >90ms but its still jittery when I play and profile on the S4. Frame debugger shows the number of draws down from circa 80 -> 11 to 15 typically, so things are batching much better now.

    So after exhausting everything I could find and think to do, I thought I would create a new scene, completely basic with just a camera in it, surprisingly even it gives me frames >32ms and there is literally nothing on it.


    Unity Ver 2020.3.33f1
    So I thought make a new project specifically a 2D Mobile template one using the old In Built renderer, same thing just a scene with a single camera and nothing else, mostly the frames are around 30ms but occasionally one goes over, this seems ridiculous for a deployed app which essentially has no content< I would have thought it would have skipped along happily @200fps even on an old phone.

    One final thing I tried was to attach a script to an object and set the following ~
    private void Start()
    {
    //QualitySettings.vSyncCount = 0;
    Application.targetFrameRate = 60;
    }

    This helped a little too but it was no panacea, it feels like there is something obvious here I can not doing but I can't for the life of me see what it is. I just can't seem to get good performance on this S4 regardless of the complexity of the scene in play? is the phone just a dud (it seems to run other apps fine)?

    Here's some examples of what I see, any thoughts?

    Thanks,
    LS


    20220908_VSync_LowQUality.jpg 20220908_VSync_LowQuality_ProjSettings.jpg
     

    Attached Files:

    Last edited: Sep 8, 2022
  8. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    1,907
    Hey again,

    I have to admit, I've got nothing. I was going to suggest Adaptive Performance but the phone is too old to be supported. As a bit of a Hail Mary, you might try turning off Optimize Frame Pacing in the Player settings?

    Or try reposting with your latest findings in the android or URP subforums?