How to instantiate a template dynamically?

I have a template by alias is my custom control:

<ui:Template name="DialogTemplate" src="UIDialog.uxml" />
<Style src="UIManager.uss" />
<UIManager name="UIManager" class="full-screen" dialog-template="DialogTemplate" >
</UIManager>

However the only function that resolve it, VisualTreeAsset.ResolveTemplate is internal.

I tried using reflection to access the function and using it I am able to clone the template onto a new element, and it appears as expected.

public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
{
    base.Init(ve, bag, cc);
    var ate = ve as UIManager;
    ate.DialogTemplateId = _dialogTemplate.GetValueFromBag(bag, cc);
    MethodInfo dynMethod = typeof(VisualTreeAsset).GetMethod("ResolveTemplate", BindingFlags.NonPublic | BindingFlags.Instance);
    ate.dialogTemplate = (VisualTreeAsset)dynMethod.Invoke(cc.visualTreeAsset, new object[] { ate.DialogTemplateId });
}

However I hit an assert in the internal function VisualTreeAsset.CloneTree(VisualElement target, Dictionary<string, VisualElement> slotInsertionPoints, List<TemplateAsset.AttributeOverride> attributeOverrides) where it asserts rootAssets.Count == 1 which it is two, one for UXML and one for a Unity.UI.Builder.UnityUIBuilderSelectionMarker whatever that is.

So… is there a better way to do this? Or could this way be made to work in the future?

Hi @redwyre !

I’m not sure I fully get what you are trying to achieve. If you want to instantiate a UXML dynamically, have a look at the
Instantiate() method from the VisualTreeAsset class. You can then build a tree of VisualElements from the asset like so:

            var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("myAssetPath.uxml");
            VisualElement uxmlLayout = visualTree.Instantiate();

The UXML Template tag is for reusing UXML inside other uxml. The link has a better explanation on the Template tag if you are interested: Unity - Manual: Writing UXML Templates

This is at runtime, so the only way to get the template would be to use Resources, and I’d like to avoid that.

I’m just trying to use the existing Template element to load a uxml, and then reference the VisualTreeAsset inside the custom component. Using the template is completely dynamic.

I’m also creating another custom component, so using it is done like:

// where dialogTemplate is the VisualTreeAsset loaded before
var dialog = new UIDialog();
dialogTemplate.CloneTree(dialog);

I’ve uploaded all the relevant code which may make more sense:

I also don’t fully understand what you’re trying to do, but I wanted to remind you that it’s not true that you’d need to use Resources as you can have a reference to the VisualTreeAsset (UXML file) from somewhere in your project (a prefab, a scriptable object, etc) and load it from there.

It’s just a simple runtime UIManager that can open UIDialogs dynamically based on game events. I just want to have it all self contained in the UXML.

The Instance/TemplateContainer component already does this, but you’re saying I should make a complicated work around… I just don’t think I should have to be injecting templates from outside the UI system when it already has the capability.

Is it your issue that you need to open/close the dialog as necessary? If so can’t you just instantiate the template, from your UXML like UI Toolkit supports it, find that VisualElement corresponding to it and set its visibility by display flex/none as necessary?

I want to be able to instantiate any number of them (dialogs not so much, but windows - which will work the same - definitely)

All I really want is VisualTreeAsset.ResolveTemplate to be supported for use by users

Stumbled upon the same kind of need.

Trying to make a self-contained Custom Element with a UXML template, having to use Resources/Addressables just to load four lines of UXML is wasteful, where I could have the template as a static string in class.

Although, even that is not preferable, but at least could work.

Any other tips how to make self-contained Custom Elements using UXML? With self-contained, meaning, no need to load UXML dynamically, rather something that can be referenced more or less at compile time.

Something irks me that classes extending from VisualElement should have native support for a custom importer of sorts, that lets us hard-reference the UXML to the custom element “class”.

1 Like