Serialize nested class in generic class using generic Type in base class

Hi,
again and again i stumble over this, can anyone explain why this doesn’t work, so i can once and for all stop doing it, knowing why i always misbelieve it should work:

[Serializable]
    public abstract class DragDataDropTarget<TDataType>: MonoBehaviour, IDropHandler
    {
        public event Action<TDataType> DataDropped;
      
        [SerializeField]
        public TDataEvent OnDataDropped = new TDataEvent(); //<---- this here

        public void OnDrop(PointerEventData eventData)
        {
            var source = eventData.pointerDrag.GetComponent<DropDataDragSource<TDataType>>();
            if (source == null || !source.HasData) return;
            DataDropped?.Invoke(source.TakeData());
        }
      
        [Serializable] public class TDataEvent: UnityEvent<TDataType>{}
    }

I always assume the nested TDataEvent serializes (/displays in the inspector) in derived parent classes, but it doesn’t.

The short answer is that unity can’t serialize any type which has a generic element as part of its typename, and your TDataEvent type is an inner type of a generic type, which means it is still considered a generic type.

Even though TDataEvent is concrete within the scope of DragDataDropTarget, the Fullname of that class is DragDataDropTarget1+TDataEvent. The 1 denotes a generic argument. Any class with a 1 (or 2, `3, etc, depending on how many generic elements are used) will be ignored by the unity serializer. You can see the fullname of a class by printing out typeof().FullName (eg typeof(DragDataDropTarget).FullName).

Even if you create a concrete DragDataDropTarget, eg public class ConcreteDDDT : DragDataDropTarget { }, the actual Fullname of ConcreteDDDT.TDataEvent would still be DragDataDropTarget`1+TDataEvent (actually, the fullname would be much longer, depending on what concrete types filled the generic parameters, but I have omitted that for clarity).

As to why Unity can’t serialize generic types, that is a much longer answer.

I think i see what you mean, that it’s still DragDataDropTarget’1+TDataEvent. I think i believed that through the concrete definition of the parent the child would inherit that ~conreteness, but it looks like that’s not the case.
Thanks for your help!