Search Unity

  1. We are migrating the Unity Forums to Unity Discussions by the end of July. Read our announcement for more information and let us know if you have any questions.
    Dismiss Notice
  2. Dismiss Notice

Showcase How to get a class take a type in the inspector/ Assign the type of a generic class in Inspector

Discussion in 'Scripting' started by ImNotaCommie, May 10, 2024.

  1. ImNotaCommie

    ImNotaCommie

    Joined:
    Jul 29, 2021
    Posts:
    1
    ---Skip to the underlined solution section for the answer.---​

    Less of a "how to" and more of a "how I"
    Caveat: I'm new to coding so sorry if the terminology is wrong or if the solution is bad.
    -this doesn't actually let you assign the type, but it is the exact work around for a generic type that I have been looking for.

    The problem is: I have a class that looks for a certain component to know if it is the type that it needs. I want to reuse this code for other items, but I don't want it to look for the same component every time. I don't want to re-write the code for every type. I also don't want to make a new class every time I want to change what it is looking for.

    Here is the solution that I came to:
    1) Make a list of type <MonoBehavior> - other types may work (eg; <Component>)
    2) Have prefabs with the target behavior on them, assign them to this list in the inspector
    3) Use this version of try get component: TryGetComponent(Type type, out Component component)

    Here is how I used it:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System;
    5.  
    6. public class RunAwayAction : MonsterBaseAction, IInteractable
    7. {
    8.     [SerializeField] private List<MonoBehaviour> _thingsToBeAfraidOf;
    9.     private Transform _afraidOf;
    10.  
    11.    
    12.     public void Interact(GameObject heldItem)
    13.     {
    14.         if (heldItem == null) {  return; }
    15.         for (int i =0; i < _thingsToBeAfraidOf.Count; i++)
    16.         {
    17.             if (heldItem.TryGetComponent(_thingsToBeAfraidOf[i].GetType(), out Component objectOfFear))
    18.             {
    19.                 _afraidOf = heldItem.transform;
    20.                 break;
    21.             }
    22.         }
    23.     }
    24.  
    25. }
    For some reason GetType() gives the most specific class even if the classes is taken from a list of monobehaviors. for example, I have a script called "burnableObject" even though it inherits from Monobehavior, the GetType() function will return burnableObject when it is taken from this list in this way, which is perfect and exactly what I needed to make this work.

    Hope this Helps!
     
    Bunny83 likes this.
  2. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,217
    Or instead of using dummy prefabs which would need to be shipped with your game, since they are referenced by your scene, you could use my SerializableMonoScript. It's a simple class that just stores the fully qualified classname of a component or ScriptableObject type and provides a nice object field in the inspector where you can actually drag and drop the MonoScript / script file directly. The generic version even provides an AddComponent version. So you can use this with a base class or interface type that should be implemented by the type you want to assign, and the AddComponent method would directly return the casted instance. Of course, casted to the generic type argument, not the actual type since that is supposed to be dynamic.

    Yes, that's pretty normal for polymorphism when a method is a virtual method. It can get overridden by derived classes so no matter what base class type the variable has, you will always get the overridden behaviour. That's the main point of polymorphism :)
     
    ImNotaCommie likes this.
  3. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    8,417
    A more straight-forward version would be to use scriptable objects to define your types. You can compare UnityEngine.Object equality for matching types, and it's trivial to make more and assign them via the inspector.
     
    ImNotaCommie likes this.