four chameleons in a row

Refactoring UI Toolkit assets

In Unity, files are usually referenced by their GUID. This has the advantage that renaming or moving a file does not break the references to it.

That’s different in the UI Toolkit. UXML files reference other templates and classes with file paths and class names. Moving and renaming files will cause errors in the UXML files.

Templates and Stylesheets

You can insert UXML-files as templates into other UXML-file. In the UXML-code, the template is referenced by its path. But it also contains the fileID and guid.

<ui:Template name="ColorPicker1" src="project://database/Assets/RekoToolkit/ColorPicker/Content/Templates/ColorPicker1.uxml?fileID=9197481963319205126&amp;guid=c4987247f222f4086bebe9cd328e639b&amp;type=3#ColorPicker1"/>

Style sheets are referenced in the same way: File path + fileID + guid.

<Style src="project://database/Assets/RekoToolkit/Stylesheet.uss?fileID=7433441132597879392&amp;guid=81eb76309dc10405894a9031d6950f86&amp;type=3#StyleSheet"/>

Moving or renaming a template will break the containing UXML file. Fortunately, Unity detects this issue and logs it to the console:

(1,2): Semantic - The specified URI does not exist in the current project : Asset reference to GUID 'c4987247f222f4086bebe9cd328e639b' was moved from 'Assets/Old/File.uxml' to 'Assets/New/Template'. Update the URL 'project://database/Assets/Old/Template.uxml?fileID=9197481963319205126&guid=c4987247f222f4086bebe9cd328e639b&type=3#Template' to remove this warning.

When you select the broken UXML file in the Unity editor, the inspector shows the following warning. Clicking on the Apply-button usually fixes

The UXML-file shows the following warning in the inspector: Last import generated 8 warnings. 1 of the selected assets can be updated to fix some warnings. Click on the button below to apply the update to the UXML files. This action will update asset paths to resolve file references and prevent future warnings. Applying the fix will replace the entire UXML file. Custom comments and formatting may be lost. Button: Apply (Overwrites File)

You can fix multiple files at once. Go to the Project View and click on the icon with the exclamation mark (“Search by Input Log”). This will filter all files with input warnings. Now select all UXML-files and click on the Apply-button.

The projects view of the Unity editor. The dropdown of the button "Search by Input Log" is active and shows "Errors" and "Warnings".

Textures and other files

Textures are referenced with their filenames and the fileID. Renaming or moving the files will break all UXML-files that contain them.

<ui:VisualElement name="Checkerboard" background-image: url(&quot;project://database/Assets/RekoToolkit/checkerboard.png?fileID=2800000&amp;guid=5f0ecf175baf3467c999a3a71de5711a&amp;type=3#checkerboard&quot;);"/>

Unity detects these errors, but can’t resolve them automatically. You have to fix the path manually.

Data binding with types

Templates often use a data source type for data binding. The bindings are defined based on this type in the UI builder. An object of the same type is assigned as data source at runtime.

In the UXML-file, the data-source-type is defined with the type name, followed by its assembly name.

<RekoToolkit.ColorPicker.ColorPicker data-source-type="RekoToolkit.ColorPicker.ColorResult, RekoToolkit" />

The following actions will break the data binding:

  • Rename a class
  • Create, delete or rename an assembly definition (asmdef)

Unfortunately, Unity only logs an error if you open the errorneous file and at runtime. Sometimes, it’s a bit hard to find all UXML files with a wrong binding.

TypeLoadException: Could not load type 'RekoToolkit.RenamedType' from assembly 'RekoToolkit.RenamedAssembly'.
System.RuntimeTypeHandle.GetTypeByName (System.String typeName, System.Boolean throwOnError, System.Boolean ignoreCase, System.Boolean reflectionOnly, System.Threading.StackCrawlMark& stackMark, System.Boolean loadTypeFromPartialName) (at :0)
System.RuntimeType.GetType (System.String typeName, System.Boolean throwOnError, System.Boolean ignoreCase, System.Boolean reflectionOnly, System.Threading.StackCrawlMark& stackMark) (at :0)
System.Type.GetType (System.String typeName, System.Boolean throwOnError) (at :0)
UnityEngine.UIElements.UxmlUtility.ParseType (System.String value, System.Type defaultType) (at /Users/bokken/build/output/unity/unity/Modules/UIElements/Core/UXML/UxmlUtility.cs:122)
UnityEditor.UIElements.UxmlSerializer:SyncVisualTreeAssetSerializedData(CreationContext, Boolean)
Unity.UI.Builder.VisualTreeAssetExtensions:DeepCopy(VisualTreeAsset, Boolean) (at /Users/bokken/build/output/unity/unity/Modules/UIBuilder/Editor/Utilities/VisualTreeAssetExtensions/VisualTreeAssetExtensions.cs:20)
Unity.UI.Builder.BuilderDocumentOpenUXML:LoadDocument(VisualTreeAsset, VisualElement) (at /Users/bokken/build/output/unity/unity/Modules/UIBuilder/Editor/Builder/Document/BuilderDocumentOpenUXML.cs:726)
Unity.UI.Builder.BuilderDocument:LoadDocument(VisualTreeAsset, VisualElement, ThemeStyleSheetManager) (at /Users/bokken/build/output/unity/unity/Modules/UIBuilder/Editor/Builder/Document/BuilderDocument.cs:360)
Unity.UI.Builder.BuilderToolbar:LoadDocumentInternal(VisualTreeAsset, ThemeStyleSheetManager) (at /Users/bokken/build/output/unity/unity/Modules/UIBuilder/Editor/Builder/Toolbar/BuilderToolbar.cs:421)
Unity.UI.Builder.BuilderToolbar:LoadDocument(VisualTreeAsset, Boolean, Boolean, String, ThemeStyleSheetManager) (at /Users/bokken/build/output/unity/unity/Modules/UIBuilder/Editor/Builder/Toolbar/BuilderToolbar.cs:412)
Unity.UI.Builder.Builder:LoadDocument(VisualTreeAsset, Boolean) (at /Users/bokken/build/output/unity/unity/Modules/UIBuilder/Editor/Builder/Builder.cs:302)
Unity.UI.Builder.Builder:OnOpenAsset(Int32, Int32) (at /Users/bokken/build/output/unity/unity/Modules/UIBuilder/Editor/Builder/Builder.cs:439)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr, Boolean&) (at /Users/bokken/build/output/unity/unity/Modules/IMGUI/GUIUtility.cs:224)

My suggestion for this issues: Actively fix all UXML files after you have changed a type that’s used for data binding. Open your preferred IDE (e.g. Rider, Notepad++) and do a search and replace over all files in the Unity project:

Search: data-source-type=”OldTypeName, OldAssemblyFile”
Replace: data-source-type=”NewTypeName, NewAssemblyFile”

Prev
XR Interaction Toolkit

XR Interaction Toolkit

The XR Interaction Toolkit is a Unity package that provides high-level