Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Need help filling a list with all classes that inherit from an interface

Discussion in 'Scripting' started by lino1000, May 1, 2020.

  1. lino1000

    lino1000

    Joined:
    Mar 11, 2019
    Posts:
    11
    Hi everyone! Now Im sorry for this kind of question, I feel kind of stupid for asking this lol but on to the problem:

    So in my game there are enemies which they all can have random special abilities. I want to be able to change/switch out these abilities easily in the future by just creating/deleting one of the ability classes. These ability classes all inherit from the IPassiveAbility interface which does NOT inherit from monobehaviour.

    I thought it would be a good idea to make a class called PassiveAbilitiesList where at the beginning of the game I just let it go through all classes inheriting from IPassiveAbility, put them into a list and whenever an enemy comes up he gets a random ability from the list but I cant figure out how I can put objects of these classes into the list without hardcoding every ability into the list myself. So basically what Im asking for would be this:


    Code (CSharp):
    1. public class PassiveAbilitiesList : MonoBehaviour
    2. {
    3.     private List<IPassiveAbility> abilitiesList = new List<IPassiveAbility>();
    4.  
    5.     void Start()
    6.     {
    7.         foreach(IPassiveAbility pa in Assets/scripts)
    8.         {
    9.             abilitiesList.Add(new pa);
    10.         }
    11.     }
    12. }

    Is this, or something similair to this where it will get all passive abilities and put it into a list on its own, somehow possible? Can I go through the folder and get all classes which inherit IPassiveAbility and just make a new object of them or something similair to that? If not, would you suggest writing this instead or do you have better suggestions?


    Code (CSharp):
    1. public class PassiveAbilitiesList : MonoBehaviour
    2. {
    3.     private List<IPassiveAbility> abilitiesList = new List<IPassiveAbility>();
    4.  
    5.     void Start()
    6.     {
    7.         abilitiesList.Add(new Ability1);
    8.         abilitiesList.Add(new Ability2);
    9.         abilitiesList.Add(new Ability3);
    10.         abilitiesList.Add(new Ability4);
    11.         etc.
    12.     }
    13. }
    Thanks for your time and answers in advance already. I know this is kind of a retarded question but im seriously lost on how that would be possible to do since having to hardcode every ability would be a pain in the long run

    Edit: Just for reference even if its pretty empty but this is my IPassiveAbility interface:

    Code (CSharp):
    1. public class IPassiveAbility
    2. {
    3.     private string name;
    4.     private string description;
    5.  
    6.     public string GetName()
    7.     {
    8.         return name;
    9.     }
    10.  
    11.     public string GetDescription()
    12.     {
    13.         return description;
    14.     }
    15. }
    Edit 2: Just realised that my interface is not an interface my bad... Sorry Im pretty new to coding and Im not really sure but I think what I really want is an abstract class and not an interface. Please correct me if Im wrong.
     
    Last edited: May 1, 2020
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,735
  3. lino1000

    lino1000

    Joined:
    Mar 11, 2019
    Posts:
    11
    Cant get it to work. It tells me that I cant implicitly cast an IEnumerable<Type> to an List<IPassiveAbility> or just an IPassiveAbility and that an explicit cast exists and I might want to use that which makes sense but I cant figure out how I could cast it. Just to make sure, this is what I wrote:

    Code (CSharp):
    1. public IEnumerable<Type> FindDerivedTypes(Assembly assembly, Type baseType)
    2.     {
    3.         return assembly.GetTypes().Where(t => t != baseType && baseType.IsAssignableFrom(t));
    4.     }
    and this is how I call it:

    Code (CSharp):
    1.  
    2.         // Try 1
    3.         abilitiesList = FindDerivedTypes(Assembly.GetExecutingAssembly(), typeof(IPassiveAbility));
    4.  
    5.         // Try 2
    6.         abilitiesList.Add(FindDerivedTypes(Assembly.GetExecutingAssembly(), typeof(IPassiveAbility)));
    7.  
    8.         // Try 3  
    9.         foreach(Type t in FindDerivedTypes(Assembly.GetExecutingAssembly(), typeof(IPassiveAbility)))
    10.         {
    11.             abilitiesList.Add(t);
    12.         }
    13.  
     
    Last edited: May 1, 2020
  4. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,735
    Well yeah, the method i gave you returns a bunch of types. You need to then get an instance of each type if you want to add them to a List<IPassiveAbility>. This is a pretty good way to do that: https://docs.microsoft.com/en-us/do...edirectedfrom=MSDN&view=netcore-3.1#overloads

    Code (CSharp):
    1. var abilitiesList = new List<IPassiveAbility>();
    2.  
    3. foreach(Type t in FindDerivedTypes(Assembly.GetExecutingAssembly(), typeof(IPassiveAbility)))
    4. {
    5.   var instance = (IPassiveAbility) Activator.CreateInstance(t);
    6.   abilitiesList.Add(instance);
    7. }
    Note this will only work if you have a parameterless constructor for each of these types (or have not declared any explicit constructors).
     
    lino1000 likes this.
  5. lino1000

    lino1000

    Joined:
    Mar 11, 2019
    Posts:
    11
    This works! Many many thanks for your help ^_^
     
    PraetorBlue likes this.
  6. technostrife

    technostrife

    Joined:
    Apr 5, 2022
    Posts:
    3
    altugs likes this.