Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Question Generic List of type <int> not being serialized in the inspector but T as <int> is

Discussion in 'Scripting' started by Bazz_boyy, Jul 10, 2020.

  1. Bazz_boyy

    Bazz_boyy

    Joined:
    May 22, 2013
    Posts:
    195
    Hello,

    I'm trying to create a system using generics and scriptable objects to encapsulate the relationship between content items and the rank in which they get unlocked. I create a generic class BaseUnlockItemBase which contains a rank value and method for determining whether or not the generic type item is unlocked when given a rank. The user can simply extend this class to create new rank unlock items of different types.

    I then have a generic class RankUnlockedItemContainer which also extends ScriptableObject which is supposed to serve the purpose of containing RankUnlockedItemBase and providing means of retrieving items based on rank.

    Anyway, so when I extend RankUnlockedItemBase and specify the type parameter as type that can be serialized like int,string,etc, item will be serialized and visible in the inspector! However, when I extend RankUnlockedItemContainer and specify the type parameter, the list will not be serialized and shown in the inspector.

    Any ideas why?

    TL;DR Extentions of generic class wont serialize T as lists of ints or whatever but it's happy to serialize T as int or whatever

    Code (CSharp):
    1.  
    2. public class RankUnlockedItemBase<T> : ScriptableObject
    3. {
    4.     [SerializeField] private int acquiredRankPoints;
    5.     public int AcquiredRankPoints { get => acquiredRankPoints; }
    6.     [SerializeField] private T item;
    7.     public T Item => item;
    8.  
    9.     public bool IsUnlocked(int rankPoints)
    10.     {
    11.         return rankPoints > acquiredRankPoints;
    12.     }
    13. }
    14.  
    This works! item will be serialized in the inspector
    Code (CSharp):
    1.  
    2. public class RankUnlockedInt : RankUnlockedItemBase<int> { }
    3.  
    Code (CSharp):
    1.  
    2. public class RankUnlockedItemContainer<T> : ScriptableObject
    3. {
    4.     [SerializeField] private List<RankUnlockedItemBase<T>> items;
    5.     public List<RankUnlockedItemBase<T>> Items {get => items; }
    6.  
    7.     public List<RankUnlockedItemBase<T>> GetAllUnlockedItemsUpToRank(int rank)
    8.     {
    9.         List<RankUnlockedItemBase<T>> unlockedItems = new List<RankUnlockedItemBase<T>>();
    10.         for (int i = 0; i < items.Count; i++)
    11.         {
    12.             if (items[i].IsUnlocked(rank))
    13.             {
    14.                 unlockedItems.Add(items[i]);
    15.             }
    16.         }
    17.  
    18.         return unlockedItems;
    19.     }
    20. }
    21.  
    This doesn't work! items IS NOT serialized in the inspector
    Code (CSharp):
    1.  
    2. public class RankUnlockedIntContainer : RankUnlockedItemContainer<int> {}
    3.  
     
    Last edited: Jul 10, 2020
  2. Bazz_boyy

    Bazz_boyy

    Joined:
    May 22, 2013
    Posts:
    195
    Solved with:
    Code (CSharp):
    1.  
    2. public class RankUnlockedItemContainer<TItem, TValue> : ScriptableObject where TItem : RankUnlockedItemBase<TValue>
    3. {
    4.     [SerializeField] private List<TItem> items;
    5.     public List<TItem> Items {get => items; }
    6.  
    7.     public List<TItem> GetAllUnlockedItemsUpToRank(int rank)
    8.     {
    9.         List<TItem> unlockedItems = new List<TItem>();
    10.         for (int i = 0; i < items.Count; i++)
    11.         {
    12.             if (items[i].IsUnlocked(rank))
    13.             {
    14.                 unlockedItems.Add(items[i]);
    15.             }
    16.         }
    17.  
    18.         return unlockedItems;
    19.     }
    20. }
     
  3. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    Unity's built-in serializer is not terribly robust, and for some reason doesn't like nested generic types.

    You can work around this by declaring a non-generic subclass of the generic class that you actually want to use (which I think you figured out, though I didn't 100% follow your post).