UIElements data persistance

Hello,

I’m writing custom UIElements EditorWindow where I have multiple fields to which I can input some values (TextField, Vector2Fields and such), but the values doesn’t get persisted the same way as in IMGUI and every time I restart unity or change Play/Edit mode the values get resetted.

I tried to look at viewDataKey (Unity - Manual: View data persistence) but I can’t get it to work, not sure if it doesn’t work or if I’m using it wrong.

Is there any way of persisting the data in the UIElements, or do I need to write something on my own to make the persistence work?

Thanks!

Hey @Clawiste,

It looks like simple fields such as <TextField> can be persisted just by adding a unique view-data-key attribute to your UXML template, or setting the viewDataKey property if you are dealing with the element in C#.

More complex fields, like the <Vector2Field> are actually compound fields. You can verify this by using the UIElements Debugger ( Ctrl+F5 to launch it):

159485-debugger.png

In this case, the <Vector2Field> has two <FloatField> children. The documentation on view data that you linked to seems to imply that both the parent element and children elements need to have a view key set.


I don’t know if it’s possible to set the view key of the children elements of a <Vector2Field> via UXML, but it is not difficult to do in C# now that we understand the structure of the UI. First we give our <Vector2Field> and name and view-data-key in our UXML template. Then, in C#, we find each FloatField child, and set their viewDataKey properties. Note the names of the float fields in the UIElements Debugger image above, unity-x-input and unity-y-input – that’s what we’ll use to find the children elements.

Below is a simple, but complete example for persistence of a <TextField> and <Vector2Field>. First, a preview:

159487-view-data-key-example.png

The values you enter in the String and Vector2 fields should be preserved on entering/exiting play mode, as well as after restarting the editor.


Assets/Editor/PersistenceTest.uxml

<?xml version="1.0" encoding="utf-8"?>
<engine:UXML
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:engine="UnityEngine.UIElements"
    xmlns:editor="UnityEditor.UIElements"
    xsi:noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd"
>
  <engine:TextField name="myTxt" label="String:" view-data-key="myTxt" />
  <editor:Vector2Field name="myV2" label="Vector2:" view-data-key="myV2" />
</engine:UXML>

Assets/Editor/PersistenceTest.cs

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

public class PersistenceTest : EditorWindow
{
    [MenuItem("Custom Tools/PersistenceTest")]
    public static void OpenWindow() { GetWindow<PersistenceTest>(); }

    public void OnEnable()
    {
        // Set up UI
        var template = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/PersistenceTest.uxml");
        var ui = template.Instantiate();
        rootVisualElement.Add(ui);
        // Add a view-data-key for the children of the Vector2Field
        var v2 = ui.Q<Vector2Field>("myV2");
        var xInput = v2.Q<FloatField>("unity-x-input");
        var yInput = v2.Q<FloatField>("unity-y-input");
        xInput.viewDataKey = "myV2.x";
        yInput.viewDataKey = "myV2.y";
    }
}

Hope this helps!

Note: I used Unity 2020.1.0b3.3385 for this answer. If the code sample I provided doesn’t work for you, please let me know what version of Unity you are using – this is actually a helpful thing to add to every question you ask, in case your issue is related to a bug that has been fixed in a newer version of Unity. Thanks!