Serializing a Generic struct with implicit converters.

I was wondering how one would go ahead with serializing a generic struct with implicit converters. Something like:

EDIT: Made some edit to fix some issues

public struct Attribute<T>
    {
        [SerializeField] private T value; //only want to serialize this for the entire struct


        public T Value
        {
            get
            {
                return value;
            }
            set
            {
                this.value = value;
                OnValueChanged.Invoke(value);
            }
        }

        [HideInInspector] public UnityEvent<T> OnValueChanged;


        public Attribute(T value)
        {
            OnValueChanged = new UnityEvent<T>();
            this.value = value;
        }
        public static implicit operator T(Attribute<T> att) => att.value;
        public static implicit operator Attribute<T>(T arg) => new Attribute<T>(arg);
    }

Any other design/implementation is also welcomed.

The operators don’t mean anything to any serialiser.

But A: Decorate it with System.Serializable

And B: Declare it with a concrete type that Unity can also serialise.

Such as:

[SerializeField]
private Attribute<int> intAttribute = new Attribute<int>();

Mind you having a class called Attribute will cause ambiguous naming issues whenever you also are using the System namespace due to it also having an Attribute class.

1 Like

I believe that’s unsupported.
Let’s say you have a working struct already realized by the compiler, and everything is fine and you serialize your data, and butterflies are happy, and little lambs jump all over the place, but then you shut it down.
How is Unity supposed to know how to deserialize it?

edit: There you go, spiney199 obviously tried it. You need concrete types for the SerializeField attribute.

I’m sorry if my question was confusing but you misunderstand my point. I know unity cannot magically serialize a generic and of course I’ll make a concrete type out of it (Where else do you think I want it serialized?). But the issue here is that Unity is unable to serialize my “value” property because well it is a property and Unity can only auto serialize fields (That unity event you see there is properly serialized by the way). I’m wondering if there’s anyway I can use a serialize property without creating a new field and/or using editor scripting for writing my own property drawers.

I’m terribly sorry, but it’s hard to take people serious on this forum.

I need to constantly switch from IQ15 to IQ900. Most of the people have really weird issues with the simplest of things. And you can’t, or at least I can’t, tell the difference sometimes, so I tend to do the safest thing first: assume that you’re towards the median. If you don’t know what you’re doing, that’s better for both of us, and if you do know, then my hope is that you will understand the volume of drivel in this forum.

Sounds legit only after you’ve explained that you understand the basics. Makes sense to address the desired audience from a position of confidence immediately. “I know this, I’ve tried that, obviously I haven’t done this, yet I wish to be able to do that.” Just saying that out loud, I don’t mean to criticize you, it’s not anyone’s fault.

Anyway, as far as I know, Unity does not normally serialize properties, only fields (and I’ve read the docs on this literally today, to answer someone else). But you can perhaps implement ISerializationCallbackReceiver, set up serialized fields that are hidden in the inspector, and translate back and forth between your properties and these fields. I don’t know if this is too messy for your case. It should be possible to automate an entire object via reflection, to make the footprint on your class bearable (and scalable). However, I don’t know if you can create (or expand) an object in run-time and still be able to serialize it (without statically and explicitly marking its contents for serialization), I’ve never tried it.

My bad and you have nothing to be sorry about. My title wasn’t the brightest for I didn’t want to limit the answers/suggestions to serializing my class but also redesigning it if there was a more feasible solution that way. In any case, I’ll try looking into ISerializationCallbackReceiver if I find some time for it. For now it works by just having a serialized private field and a public property. I really didn’t wanna do it but it works okay. And of course I get that people here can be a bit difficult. Although I’m new to unity myself (~ 1 year) I have met the main demographic who usually don’t have the general programming background that they probably should and just hopped on the game development hype train expecting it to be super easy. Nothing against them but I just wish people learned things in a correct manner and didn’t just jump into the middle of a cesspool. Anyways, thanks for the suggestions.

1 Like

Well… the most straight forward way is going to be adding a new field. I think you’re going to have to as your getter and setter will cause an infinite loop, considering they reference themselves.

[System.Serializable]
public struct Attribute<T>
{
    [SerializeField]
    private readonly T _value; //you may have to remove readonly

    private readonly T Value
    {
        get
        {
            return _value;
        }
        set
        {
            this._value = _value;
            OnValueChanged.Invoke(_value);
        }
    }

    public UnityEvent<T> OnValueChanged;


    public Attribute(T value)
    {
        OnValueChanged = new UnityEvent<T>();
        this._value = _value;
    }
  
    public static implicit operator T(Attribute<T> att) => att._value;
    public static implicit operator Attribute<T>(T arg) => new Attribute<T>(arg);
}

Yeah that’s what I’ve done temporarily. I did say that I’d like to avoid doing this but it’s a okayish workaround, like I said in my previous message.

How is it a work around? It’s standard C# practice.

Your initial method literally had two infinite loops and was unusable.

Yes I get that. I don’t mean having a field and a property is my problem. I mean exposing that field with SerializedField. This does cause you to have sort of an heading for that object then a field to input your Value in. I would like it to be next to each other, like its treating my attribute as a variable of the concrete type that it is.

I’ll fix that in the initial post if it’s editable. That was a mistake on my end.

For now it will look like:

SpeedAttribute
Value [__________]

I would Like it to simply look like
SpeedAttribute [__________]

That has nothing to do with serialisation and is instead within the domain of custom inspector work.

Understood. I’m not a fan of writing custom inspectors and have very little experience with them. Can you point me to some references that can help me writing a custom inspector for this?