Is it possible to have a camera in a scene that doesn't render the UI?

I am hoping to add screenshot sharing to a mobile game. I was thinking I could create a second camera attached to a render texture that I could enable to capture a screenshot when required.
Is there a way to hide the UI from this camera?

I don’t think you need to do anything? I’ve been using render textures to draw previews of stuff in UI Toolkit interfaces for a while, and I haven’t had any of my UI showing in said renders.

Have you been having UI show up in your render texture outputs?

I’m actually not sure what determines whether UI renders onto a camera or not.

You coud simply SetActive(false) the game object your UI lives in, let one frame pass (for rendering once without the UI), take screenshot and re-enable the UI.

Its a possibility… disabling the entire UI and re-enabling will likely have some unforeseen side effects - its a 2D game where a significant portion of the game is the UI. I was hoping not to have to interrupt the play view at all.

  • edit -
    I just tried disabling and re-enabling the gameobject containing the UIDocument. It does cause issues. Likely some of the UI updates are overwritten in the OnEnable code - which to this point has assumed that it is called only at specific times - my own fault really for not always adhering to a strict Model View Controller architecture.

It’s better to rootVisualElement.visible = false when dealing with UI toolkit, which doesn’t cause a whole reintialisation of the UI document.

But again, are you actually getting UI showing up in your render textures?

@spiney199 - you’re on the money. No - the UI isn’t rendered into the RenderTexture. I had assumed it would be. Thanks for the tip!

J

So after getting all that to work… turns out I need to also have some UI components rendered into the RenderTexture.
I managed to get it to work, but had to jump through some hoops.

One thing that took me a while to figure out was that my UI components (with rounded corners) rendered as white. Turns out my RenderTexture needed a depth stencil…

In case it helps someone else at some point, here’s some code. Perhaps someone more knowledgeable can tell me if I’m doing anything stupid.:

    [SerializeField] private Camera shareCamera;
    [SerializeField] private GameObject shareUI;
    [SerializeField] private UIDocument shareDocument;
    [SerializeField] private PanelSettings sharePanelSettings;

    private IEnumerator SaveScreenshotToFile()
    {
        yield return new WaitForEndOfFrame();

        int width = 512;
        int height = 512;
        var renderTexture = RenderTexture.GetTemporary(width, height, 24, GraphicsFormat.R8G8B8A8_UNorm);

        // render the share camera
        shareCamera.targetTexture = renderTexture;
        shareCamera.Render();
        shareCamera.targetTexture = null;

        // render the share UI on top of the camera
        sharePanelSettings.targetTexture = renderTexture;
        shareUI.SetActive(true);

        // wait for UI to render a frame
        yield return new WaitForEndOfFrame();

        shareUI.SetActive(false);
        sharePanelSettings.targetTexture = null;

        // read back the render texture and share it.
        AsyncGPUReadback.Request(renderTexture, 0,
        (AsyncGPUReadbackRequest request) =>
        {
            // Render texture no longer needed, it has been read back.
            GraphicsFormat graphicsFormat = renderTexture.graphicsFormat;
            RenderTexture.ReleaseTemporary(renderTexture);

            try
            {
                if (request.hasError)
                {
                    Debug.LogError("Unable to save screenshot: GPU readback error detected.");
                }
                else
                {
                    string filePath = Path.Combine(Application.temporaryCachePath, "screenshot.png");
                    using (
                        NativeArray<byte> imageBytes = request.GetData<byte>(),
                        encoded = ImageConversion.EncodeNativeArrayToPNG(imageBytes, graphicsFormat, (uint)width, (uint)height)
                    )
                    {
                        File.WriteAllBytes(filePath, encoded.ToArray());
                    }
                }
            }
            catch (System.Exception e)
            {
                Debug.LogError("Unable to save screenshot: " + e.Message);
            }
        });
    }