Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice
  2. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  3. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Abstract Class in List, only shows base variables

Discussion in '2020.2 Beta' started by grimofdoom, Nov 3, 2020.

  1. grimofdoom

    grimofdoom

    Joined:
    Sep 6, 2013
    Posts:
    168
    I purposely upgraded to 2020.2 early, because I need the reorderable lists and it is so far the easiest way since.

    I have a class called ActionSeries, which holds a property of List<Action>. How can I make the reorderable List<Action> be able to accept any class that inherits from Action (Click on the little '+' icon, and it gives a drop down or menu of classes that inherit from Action to choose from to add).

    Action is not inheriting from Monobehaviour, so it will be editable from the inspector, and later ActionSeries will be a ScriptableObject.
     
  2. grimofdoom

    grimofdoom

    Joined:
    Sep 6, 2013
    Posts:
    168
    I tried a basic button to just add a [new AddItemAction()] (that inherits from Action), to the [List<Action> Series]. While it does add a new Action, as far as I can tell, it only adds an Action and not an actual AddItemAction as it only shows what the Action class has and nothing that the AddItemAction has for settings.



    ActionSeries Editor
    Code (CSharp):
    1. [CustomEditor(typeof(ActionSeries))]
    2. public class ActionSeriesEditor : Editor
    3. {
    4.     SerializedProperty actions;
    5.  
    6.     private void OnEnable() {
    7.         actions = serializedObject.FindProperty("series");
    8.     }
    9.  
    10.     public override void OnInspectorGUI() {
    11.         ActionSeries series = (ActionSeries)target;
    12.  
    13.         EditorGUILayout.LabelField("Add Action Event to List");
    14.  
    15.         if (GUILayout.Button("Add Item")) {
    16.             series.series.Add(new AddItemAction());
    17.         }
    18.  
    19.         CEHelpers.Spacer();
    20.  
    21.         EditorGUILayout.LabelField("Action Series Settings");
    22.         DrawDefaultInspector();
    23.     }
    24. }
    25.  
    ActionSeries
    Code (CSharp):
    1. public class ActionSeries : MonoBehaviour
    2. {
    3.     public List<Action> series;
    4. }
    Action
    (I know the Run() > Run(null) is bad- just ignore it please)
    Code (CSharp):
    1. [System.Serializable]
    2. public class Action
    3. {
    4.     [Header("Action Settings")]
    5.     [Tooltip("Whether or not this can be ran multiple times")]
    6.     public bool runOnce = false;
    7.  
    8.     [Header("Action Info (do not touch)")]
    9.     [Tooltip("Whether or not this has ran before")]
    10.     [SerializeField]private bool hasRan = false;
    11.  
    12.     /// <summary>
    13.     /// What the Action will do, if allowed to run on [Perform]
    14.     /// </summary>
    15.     public virtual void Run(GameObject obj) {
    16.         //Does nothing
    17.     }
    18.  
    19.     /// <summary>
    20.     /// Run an action without a GameObject
    21.     /// </summary>
    22.     public virtual void Run() {
    23.         Run(null);
    24.     }
    25.  
    26.     /// <summary>
    27.     /// Base set for how to run an action, core method to launch Action's to do stuff
    28.     /// </summary>
    29.     public virtual void Perform(GameObject obj) {
    30.         if (!runOnce) {
    31.             //If [runOnce] is false, always run
    32.             Run(obj);
    33.             hasRan = true;
    34.         } else if (runOnce && !hasRan) {
    35.             //If [runOnce] is true but has not ran before
    36.             Run(obj);
    37.             hasRan = true;
    38.         } else {
    39.             //if [runOnce] is true, and has ran before
    40.             DisabledRun();
    41.         }
    42.     }
    43.  
    44.     /// <summary>
    45.     /// Perform an action without a gameobject
    46.     /// </summary>
    47.     public virtual void Perform() {
    48.         Perform(null);
    49.     }
    50.  
    51.     /// <summary>
    52.     /// Optional 'to do' for when runOnce is true, and it has already ran before
    53.     /// </summary>
    54.     public virtual void DisabledRun() {
    55.         //Do nothing
    56.     }
    57. }
     

    Attached Files:

    Last edited: Nov 3, 2020
  3. brunocoimbra

    brunocoimbra

    Joined:
    Sep 2, 2015
    Posts:
    679
    [SerializeReference] public List<Action> series;
    should do what you want. Just be aware that SerializeReference has several pitfalls (like not being compatible if the type to be serialized is a UnityEngine.Object or has nested reference to one)
     
  4. grimofdoom

    grimofdoom

    Joined:
    Sep 6, 2013
    Posts:
    168
    Thank you. This is beautiful.

    (And no, Action and what inherits it- do not inherit from Object or Monobehaviour thankfully)
     

    Attached Files:

    brunocoimbra likes this.