Search Unity

  1. Unity 2018.3 is now released.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. We've updated our Terms of Service. Please read our blog post from Unity CTO and Co-Founder Joachim Ante here
    Dismiss Notice
  4. Want to provide direct feedback to the Unity team? Join the Unity Advisory Panel.
    Dismiss Notice
  5. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice

Camera.Render() seems to trigger Canvas.SendWillRenderCanvases()

Discussion in 'Unity UI & TextMesh Pro' started by cowtrix, Mar 21, 2017.

  1. cowtrix

    cowtrix

    Joined:
    Oct 23, 2012
    Posts:
    278
    Hey there. I've got a background camera rendering out some meshes to a RenderTexture. There is also a complex uGUI doing stuff with the user. Both of these have to run in parallel. I've found through profiling that calling a Camera.Render() on this background camera triggers Canvas.SendWillRenderCanvases() on the rest of the UI.


    What in tarnation! The background camera is set to have an empty event mask, and a culling mask of only one layer where it renders what it needs to. There are no UI elements on this layer. Has anyone seen this before? How do you tell a camera that it doesn't need to care about UI in any way, shape or form?
     
  2. cowtrix

    cowtrix

    Joined:
    Oct 23, 2012
    Posts:
    278
    For anyone's interest, I did end up solving this problem with some reflection. Basically I got the delegate, cached the value, nulled the value, did the camera render, and then set the delegate again from the cached value.

    Code (CSharp):
    1. var canvasHackField = typeof(Canvas).GetField("willRenderCanvases", BindingFlags.NonPublic | BindingFlags.Static);
    2. var canvasHackObject = canvasHackField.GetValue(null);
    3. canvasHackField.SetValue(null, null);
    4. Camera.Render();
    5. canvasHackField.SetValue(null, canvasHackObject );
     
    Last edited: May 5, 2017
  3. Thomas-Mountainborn

    Thomas-Mountainborn

    Joined:
    Jun 11, 2015
    Posts:
    322
    This is still an issue in 2017.3. Thanks @cowtrix for figuring out this hacky solution, though this really needs to be addressed officially. It makes no sense that this much performance is wasted - cameras that don't render any UI should not have to do expensive calculations on whether or not they will render canvases. I have a set-up with many cameras rendering to render textures, and this eats away 50 milliseconds per frame for nothing.
     
    Agent0023 likes this.
  4. MiFrilke

    MiFrilke

    Joined:
    Dec 14, 2016
    Posts:
    13
    We noticed the same issue in 2018.2.6f1 recently. It drastically impacts performance on consoles for us, so I'm happy to have found this workaround, thank you @cowtrix, I hope it still works in 2018.2.

    I've also reported this as a bug (ID 1090213), but have not heard back from QA for a few days.
     
    customphase likes this.
  5. MiFrilke

    MiFrilke

    Joined:
    Dec 14, 2016
    Posts:
    13
    We actually heard back from QA after a while and had a bit of back-and-forth about this issue (ID 1090213)
    The result was:

    "After contacting developers about it, this seems to be expected behaviour. Consider all the separate Camera.Render() calls as different screenshots - the UI has to be rendered.
    We're sorry that it's causing you inconveniences."

    Which seems absolutely ridiculous to me. This would imply Unity expects us to use Camera.Render() only for creating screenshots? If I want a screenshot that includes the UI, I can simply enable the UI layer in the CullingMask of my camera. But if I want to render literally anything else, why am I forced to endure this useless UIEvents.WillRenderCanvases call even though no canvases are actually rendered?
    Sure, there is the workaround Hack posted above, but this shouldn't be the only solution to such an inherently wrong behaviour.

    Attached profiler screenshot shows a simple scene with some dynamic UI and one disabled camera (in addition to the main one) that is rendered from the Update function of a custom script. You can see almost 1ms being wasted on stuff that is simply not needed. The project this profiler screenshot has been taken in is also attached (2018.3.0b12).
     

    Attached Files:

    Thomas-Mountainborn likes this.
  6. Thomas-Mountainborn

    Thomas-Mountainborn

    Joined:
    Jun 11, 2015
    Posts:
    322
    It is definitely ridiculous. The post I made at the beginning of this year is about a running project, so we have the same requirements to this day. The cameras only render depth to render textures for use in a custom shader, they will never have anything to do with UI. If it wasn't for cowtrix, Unity would not even have been viable for this project. It is such an easy thing to bypass and it hogs so much performance doing absolutely nothing. I see no reason why Unity is pulling the "intended behaviour" card here.
     
    MiFrilke likes this.
  7. mushdevstudio

    mushdevstudio

    Joined:
    May 9, 2014
    Posts:
    29
    When I disabled Pixel Perfect on the canvas the frame rate drop went away.