Override base class type in subclass type

Hi, I’m making my first game, and I’m developing some custom UI animation scripts that derive from this AnimationBase class:

using UnityEngine;
using UnityEngine.EventSystems;
using System.Collections;

[ExecuteAlways]
[DisallowMultipleComponent]
public abstract class AnimationBase : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler, IPointerUpHandler
{
    public GameObject graphic;
    public float fadeTime = 0.05f;

    protected IEnumerator animCoroutine;

    public abstract void OnPointerEnter(PointerEventData eventData);
    public abstract void OnPointerExit(PointerEventData eventData);
    public abstract void OnPointerDown(PointerEventData eventData);
    public abstract void OnPointerUp(PointerEventData eventData);
    protected abstract void OnValidate();
}

The children classes all have a graphic field, but the type should be different with each subclass. For example, I have:

public sealed class TextColorAnimation : AnimationBase
{
    // Editor fields
    [Space(5)]
    public new TextMeshProUGUI graphic;

    // Other code...
}

…and:

public sealed class ScaleAnimation : AnimationBase
{
    // Editor fields
    [Space(5)]
    public new Image graphic;
   
    // Other code...
}

Apparently the new keyword isn’t supported in this case, because if I then compile and go into Unity I get an error and also the base class graphic variable and the derived class one both show in the inspector, which is not what I want of course.
I need this because all animations inherit a fadeTime field from AnimationBase, but I also need the graphic variable to be on top in the inspector, that’s why I’m doing this.

Any better ideas?

You can use generics:
AnimationBase : MonoBehaviour where T : Graphic

1 Like

If you’re going to manually do whatever property manipulation you need to do in the child animation classes, make the AnimationBase generic and use that instead.

class AnimationBase<T> : MonoBehaviour // etc etc
{
     T graphic;

     // etc etc
}

class ScaleAnimation : AnimationBase<Image>
{
    // graphic is now of type Image inside here
}

If you plan to manipulate the graphic inside the AnimationBase class, you can try using the UI.Graphic class instead of a GameObject, as that has certain extra shared properties of UI elements (colour, rectTransform, materialForRendering) and is used extensively in the other UI classes. Image and Text both derive from Graphic, for example.

If neither of those are suitable, you need to rethink your inheritance chain because there’s no other way to do what you want to do. I personally don’t think you even need inheritance here.

1 Like

Thank you all! I was doing class ScaleAnimation<Image> : AnimationBase this whole time. Now the issue is solved and I’ve managed to make the AnimationBase class actually useful using generics.