Can I create PanelSettings and RenderTexture at runtime for using with UIToolkit?

Good day everyone,

I want to create health bar for ingame units as world space canvas.
For tests I have created another project, imported UI Toolkit and UI Builder packages, created basic UXML template with one element inside (button), PanelSettings scriptable object and RenderTexture. This texture I then assigned as source for RawImage component inside World Space Canvas.
Everything works fine, if everything done by hands, but when I try to create everything at runtime nothing works.
I’ve debugged this for hours and here is the result:
If I change render texture of PanelSettings that was created in Editor, everything renders as expected but as soon as I replace editor’s PanelSettings with one that was created at runtime, nothing renders to texture.
Looks like I’m missing some step when creating PanelSettings

Have someone checked creation of PanelSettings and RenderTexture at runtime?

Here is code that I’m using:

public class PanelSettingsTest : MonoBehaviour {
    public bool ReplacePanelSettings;
    void Start() {
        GameObject gameObject = Instantiate(Resources.Load("Prefab_with_Canvas_RawImage_UIDocument") as GameObject, Vector3.zero, Random.rotation);
        RenderTexture renderTexture = new RenderTexture(200, 100, 24, RenderTextureFormat.ARGB32);
        renderTexture.Create();
        renderTexture.name = "RenderTexture #" + renderTexture.GetHashCode();

        if(ReplacePanelSettings) {
            PanelSettings panelSettings = ScriptableObject.CreateInstance<PanelSettings>();
            panelSettings.name = "PanelSettings #" + panelSettings.GetHashCode();
            gameObject.GetComponentInChildren<UIDocument>().panelSettings = panelSettings;
        }

        gameObject.GetComponentInChildren<RawImage>().texture = renderTexture;
        gameObject.GetComponentInChildren<UIDocument>().panelSettings.targetTexture = renderTexture;
    }
}

Versions:
Unity Editor 2020.2.b2
UI Toolkit 1.0.0-preview.9

Hello, there’s currently an asset that is not built into the player if your PanelSettings is created only at runtime. That’s why if you use a PanelSettings you created in the Editor it works, the asset is assigned correctly and packaged in build time. We’re working on this but for now please create your PanelSettings as an asset in the Editor.

1 Like

Ok, I got it. Thank you for reply.
Since this looks like a bug, I’ve changed prefix for this thread to bug.

This is not really a bug as it’s more a consequence of how assets work in Unity.
The only for us to fix is to include the default style sheets in all Unity builds even if no PanelSettings are used in a project, which can negatively impact the build size.

Normally PanelSettings are referenced through a Scene and the styles sheets are pulled through a reference.

For your use case, although we want to give a more descriptive error, I’d recommend simply using a PanelSettings reference from your MonoBehaviour and modify it as needed. Alternatively, use a Resource folder or Asset Bundle so that you can load the asset at runtime by name/path.

1 Like

The problem for me is that I can set render texture only in PanelSettings asset, and I need to do this for every ingame unit, because every unit its has its own health. As a workaround I can create thousand PanelSettings in Resources folder, create service that contains that pool of PanelSettings and take/release one on demand. But this “workaround” looks strange for me.
Maybe I’m doing something wrong and you can recommend better implementation of this.
Structure of this “whole plan”:
6464236--725050--structure.jpg

I’ve read your comment again and added link of default stylesheets to newly created PanelSettings from one that was created in editor.
Works OK now. Here is project files if someone will need to do the same.

6464293–725056–RenderTextureTest.zip (56.1 KB)

Thank you Antoine and JuliaP for helping me with that problem.

1 Like

hi @ProFiLeR4100 ,

Quick note. We won’t batch UI geometry across PanelSetting instances. If you have many units, each displaying their health bar using a distinct PanelSettings (to draw to a distinct RenderTexture, for example), you’ll soon end up with a performance bottleneck.

One alternative would be to render multiple health bars in a single (or fewer) render texture, and sample that texture for multiple units when rendering health bars in 3D.

1 Like

Is there a straightforward way of displaying a health bar in in-game UI programatically?

There’s a health bar example on this demo: GitHub - Unity-Technologies/UIToolkitUnityRoyaleRuntimeDemo: This is a sample project to introduce the use of UI Toolkit in Runtime

@JuliaP_Unity That health bar is rendered in screen space, I’m trying to render in world space. I managed to figure it out for the most part, but had to stitch a bunch of resources together. Would be awesome to have a clear guide for this!

We don’t have specific examples of this, but for now the only way to do world space with UI Toolkit is by using render to texture and for that specifically you can find an example if you install the Samples for the com.unity.ui package in the Package Manager window, then select Window > UI Toolkit > Examples > Rendering.

1 Like

@JuliaP_Unity Thank you, I had already found those examples in the meantime but that might help anyone else who has come across this thread in their search.

It would be great to centralize these resources - documentation for UI Toolkit is a little spread out at the moment. I’d love to get to writing a highly overdue getting started guide, but it is unlikely that Unity would resort to freelance manpower for that.

Thanks again!

Another issue related to this thread I came across: there seems to be no way to create a UIDocument component programmatically. The only way I found to do it is to add it to a prefab and instantiate that prefab.

Am I missing something?

UIDocument is a MonoBehaviour like any other, you need to create it as a component to a game object like you’d do normally for any MonoBehaviour. Are you getting specific errors when you do that? If that’s the case please start a topic dedicated to that as we’d have to investigate and exchange information most probably. Thanks!

1 Like

@JuliaP_Unity My bad, I was creating RenderTextures and Materials using the new keyword so much I didn’t realize UIDocument, being a MonoBehaviour, should be added using .AddComponent<UIDocument>();

1 Like