Element has no registered factory method.??

Hi folks!

Context:
Unity 2019.4.9f1
UI Builder: 1.0.0-preview7

I am creating a fancy tool using uielements and to keep my project organized I decided to create some custom components. I ready the documentation and a few examples and I had a good start.
Basically, I created 6 components. One of them is very “basic” and is used but others… and these are used by another. So, I have custom controls that consume other custom controls. So far, so good. Everything working fine.

BOOM

Out of the blue I started to have one of my components getting changed (by the builder) for a label with the text: “Unknow type: UIRichLabel”. This is (just a coincidence) my most basic custom control. It is a label with an icon. This is the UXML of it:

<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
    <ui:VisualElement name="UIRichLabel" style="flex-direction: row; align-items: center;">
        <Style src="FtueEditorWindow3.uss" />
        <ui:VisualElement name="icon" class="hide" style="margin-left: 5px; margin-right: 5px; justify-content: center;" />
        <ui:Label text="LABEL" name="label" style="font-size: 12px;" />
    </ui:VisualElement>
</ui:UXML>

And this is its related c# code

using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class UIRichLabel : VisualElement
{
    private const string TEMPLATE_PATH = "Assets/Editor/FTUE/UIRichLabelTemplate.uxml";

    private const string ERROR_ICON_STYLE = "error_icon";
    private const string WARNING_ICON_STYLE = "warning_icon";
    private const string INFO_ICON_STYLE = "info_icon";
    private const string NONE_ICON_STYLE = "hide";

    public enum IconStyle
    {
        None,
        Error,
        Warning,
        Info
    }

    public static readonly Dictionary<IconStyle, string> IconStyles = new Dictionary<IconStyle, string>()
    {
        {IconStyle.None, NONE_ICON_STYLE},
        {IconStyle.Error, ERROR_ICON_STYLE},
        {IconStyle.Warning, WARNING_ICON_STYLE},
        {IconStyle.Info, INFO_ICON_STYLE},
    };

    private const string ICON_SELECTOR = "icon";
    private const string LABEL_SELECTOR = "label";

    private VisualElement m_icon = default;
    private Label m_label = default;
    private IconStyle m_iconStyle;
    private Color m_color = default;

    public string Label
    {
        get { return m_label.text; }
        set { m_label.text = value; }
    }

    public int TextSize
    {
        get { return (int)m_label.style.fontSize.value.value; }
        set
        {
            m_label.style.fontSize = new StyleLength(value);
            m_icon.style.height = new StyleLength(value);
            m_icon.style.width = new StyleLength(value);
        }
    }

    public Color TextColor
    {
        get { return m_color; }
        set
        {
            m_color = value;
            m_label.style.color = m_color;
        }
    }

    public IconStyle Icon
    {
        get { return m_iconStyle; }
        set
        {
            m_iconStyle = value;
            SetStyle(m_iconStyle);
        }
    }

    public UIRichLabel()
    {
        VisualTreeAsset template = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(TEMPLATE_PATH);
        template.CloneTree(this);
        LoadInternalReferences();
    }

    public void LoadInternalReferences()
    {
        m_icon = this.Q<VisualElement>(ICON_SELECTOR);
        m_label = this.Q<Label>(LABEL_SELECTOR);
    }

    public void SetLabel(string title, IconStyle style)
    {
        SetLabel(title);
        SetStyle(style);
    }

    public void SetLabel(string label)
    {
        m_label.text = label;
    }

    public void SetStyle(IconStyle style)
    {
        m_icon.ClearClassList();
        m_icon.AddToClassList(IconStyles[style]);
    }

    public void SetClickCallback(Action callback)
    {
        m_label.AddManipulator(new Clickable(callback));
    }

    #region UXML stuff

    public new class UxmlFactory : UxmlFactory<UIRichLabel, UxmlTraits> { }

    public new class UxmlTraits : VisualElement.UxmlTraits
    {
        UxmlEnumAttributeDescription<IconStyle> m_icon = new UxmlEnumAttributeDescription<IconStyle> { name = "icon-style", defaultValue = IconStyle.None };
        UxmlStringAttributeDescription m_label = new UxmlStringAttributeDescription { name = "label", defaultValue = "Label" };
        UxmlIntAttributeDescription m_textSize = new UxmlIntAttributeDescription { name = "text-size", defaultValue = 12 };
        UxmlColorAttributeDescription m_textColor = new UxmlColorAttributeDescription { name = "text-color", defaultValue = Color.black };

        public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
        {
            base.Init(ve, bag, cc);

            UIRichLabel uIRichLabel = ve as UIRichLabel;
            uIRichLabel.Label = m_label.GetValueFromBag(bag, cc);
            uIRichLabel.Icon = m_icon.GetValueFromBag(bag, cc);
            uIRichLabel.TextSize = m_textSize.GetValueFromBag(bag, cc);
            uIRichLabel.TextColor = m_textColor.GetValueFromBag(bag, cc);
        }
    }

    #endregion
}

When I pass the mouse over another component (in the builder) that uses this richlabel, I got this in the console:

Element ''UIRichLabel'' has no registered factory method.
UnityEngine.UIElements.VisualTreeAsset:CloneTree()
Unity.UI.Builder.<>c__DisplayClass8_0:<ImportUxmlFromProject>b__0() (at Library/PackageCache/com.unity.ui.builder@1.0.0-preview.7/Editor/Builder/Library/BuilderLibraryProjectScanner.cs:248)
Unity.UI.Builder.BuilderLibraryView:OnItemMouseEnter(MouseEnterEvent) (at Library/PackageCache/com.unity.ui.builder@1.0.0-preview.7/Editor/Builder/Library/BuilderLibraryView.cs:93)
UnityEngine.GUIUtility:processEvent(Int32, IntPtr)

I read several posts about the possible causes, I saw it used to be related to
moment when the the uxmlfactory got registred, I saw a few hacks to work it around… but all old stuff, version 0.0.4 or something like that and supposely already fixed.

After 3 days trying to fix that…

BOOOOOM

Another components start to present the same symptom!! Seems like a cancer spreading out across my components!!

Please, I need to advices here… anyone with a word to comfort me is also welcome.

Joao

Hi,

I tried your usecase and it seems to work well on my side. I created 3 files:

/Assets/Editor/FTUE/UIRichLabel.cs with code above
/Assets/Editor/FTUE/UIRichLabelTemplate.uxml with uxml definition above
/Assets/Editor/FTUE/FtueEditorWindow3.uss with the following inside (just for testing purposes, did not have access to your content):

.error_icon {
    background-color: #FF0000;
}

.warning_icon {
    background-color: #FFFF00;
}

.info_icon {
    background-color: #5555FF;
}

.hide {
    display: none;
}

Opened the UI Builder (1.0.0-preview.7), with a new UI document (aka project’s main UXML file), set Library mode to “Project”, found the UIRichLabel and double-clicked on the entry to add an instance to my project’s UI document, everything worked out fine. I will probably need more contextual info to repro. How are you using the UIRichLabel specifically?

Sebastien

Having exact same problem. Was working fine, then next time I rebooted unity this occurred.

Seems to struggle when it clones it into my inspector. What’s strange is taking it outside of an assembly fixes it. My assembly is referencing UnityEditor.UI, UnityEngine.UI, UnityEngine.UIElementsModule, UnityEditor.UIElementsModule. No bugs in console until I try to open inspector.

Error:

Element 'RandomizableFloatField' has no registered factory method.
UnityEngine.UIElements.VisualTreeAsset:CloneTree (UnityEngine.UIElements.VisualElement)
BubblesEditorHelpers.BubblePositionInspector:CreateInspectorGUI () (at Assets/Scripts/BubblesEditorHelpers/BubblePositionInspector.cs:26)
UnityEditor.InspectorWindow:RedrawFromNative () (at /Users/bokken/buildslave/unity/build/Editor/Mono/Inspector/InspectorWindow.cs:144)
using Bubbles;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

namespace BubblesEditorHelpers {
    [CustomEditor(typeof(BubblePosition))]
    public class BubblePositionInspector : Editor {

        [SerializeField] VisualTreeAsset bubbleInspector;
        BubblePosition bubblePositionEditor;
        VisualElement thisInspector;
        Foldout defaultInspector;


        public override VisualElement CreateInspectorGUI()
        {
            thisInspector = new VisualElement();
 
            if (bubbleInspector == null) {
                DrawDefaultInspector(thisInspector);
                return thisInspector;
            }
 
            bubbleInspector.CloneTree(thisInspector); <--- Error

This is in the same assembly:

using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;

namespace BubblesEditorHelpers {
    public class RandomizableFloatField : Foldout
    {
  
        public new class UxmlFactory : UxmlFactory<RandomizableFloatField, UxmlTraits> { } <--- factory

Update: It required removing the namespace of the custom VisualElement to fix it, not necessarily the assembly. It works in an assembly as long as there’s no namespace in the file.

1 Like

Unity 2021.2.8f1 here.

In my case this happens when I change the namespace of the custom element. The element already was in a namespace and worked fine. After changing the namespace the

Element 'Foobar' has no registered factory method. errors started appearing.
Changing the namespace back to the original resolved the issue.

2 Likes

Same error here after I renamed the namespace in my .cs file (Unity 2021.2.7f1).

I could fix it by manually editing the .uxml file in a text editor and renaming the namespace to the new one.

Before (old namespace “Game.Play”)

<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
    <ui:Template name="PlayOverlay" src="project://database/Assets/Data/Ui/PlayOverlay.uxml?fileID=9197481963319205126&guid=8f3a6ea49da1aab4881b973bb23dde2c&type=3#PlayOverlay" />
    <Game.Play>
        <ui:Instance template="PlayOverlay" name="PlayOverlay" />
    </Game.Play>
</ui:UXML>

Fixed (new namespace “Game.Ui.Play”) - replaced “Game.Play” with “Game.Ui.Play”

<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
    <ui:Template name="PlayOverlay" src="project://database/Assets/Data/Ui/PlayOverlay.uxml?fileID=9197481963319205126&guid=8f3a6ea49da1aab4881b973bb23dde2c&type=3#PlayOverlay" />
    <Game.Ui.Play>
        <ui:Instance template="PlayOverlay" name="PlayOverlay" />
    </Game.Ui.Play>
</ui:UXML>

We’re likely going to support the [MovedFromAttribute] on VisualElement classes so that UXML assets remain compatible with the former namespace.
Unfortunately this class is not documented but it is public and used a lot at Unity.
When using the [SerializedReference] attribute in regular Unity serialization, this is also this attribute that is used to avoid breaking existing asset (see this thread).

It’s not perfect but it can be useful to avoid breaking all assets when renaming a namespace.

2 Likes

Did you solve your problem?