UI Builder issue with serialized UnityEvent

Hi, I’m not sure what’s the current support for UnityEvent in UI Builder, but I’ve run into the following issue:

I have simple custom Button element with UxmlAttribute of UnityClickEvent:

using UI.Events;
using UnityEngine.UIElements;

namespace UI.Lib
{
    [UxmlElement]
    public partial class Button : UnityEngine.UIElements.Button
    {
        [UxmlAttribute] public UnityClickEvent onClicked;

        protected override void HandleEventTrickleDown(EventBase evt)
        {
            base.HandleEventTrickleDown(evt);

            if (evt is ClickEvent clickEvent)
            {
                onClicked.Invoke(clickEvent);
            }
        }
    }
}

Here is the UnityClickEvent class which simply inherits from generic UnityEvent (AFAIK there is not way to serialize generics) and serialized using JsonUtility .

using System;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UIElements;

namespace UI.Events
{
    [Serializable]
    public class UnityClickEvent : UnityEvent<ClickEvent>
    {
    }

    public class UnityClickEventConverter : UxmlAttributeConverter<UnityClickEvent>
    {
        public override UnityClickEvent FromString(string value) => JsonUtility.FromJson<UnityClickEvent>(value);
        public override string ToString(UnityClickEvent value) => JsonUtility.ToJson(value);
    }
}

Now this is works fine for most of the time even after the editor restarts, but sometimes it just randomly breaks the reference by assigning some random rubbish even though serialised value inside the UXML file didn’t change.

Before:

After:

Hi,
Can you share an example project with the problem?
Its possible that the JSON contains some characters that are invalid in UXML or it could be an issue with serializing the field to JSON.

Hi, sure here is example project: GitHub - alex-solovev/UnityEventIssue

As I was making this example project I figured that the problem is caused by the ScriptableObject changing its instance ID. Frankly, I’m not that familiar with serialization but from what I found instance ID is not stable, based on that would you be able to recommend any alternative approaches to ensure that UnityEvent that is serialized to JSON is stable?

Oh yes that wont work.
What objects are you referencing? Assets or scene objects?
For assets you can use the asset path or guid.
Scene objects dont have stable ids, you could use the path/name or look at one of the stable id libraries around the internet.

1 Like

Okay, that makes sense, I mainly plan to reference scriptable objects, so I will try to use GUID for serialization, thanks!

1 Like