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
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Converting Enum value to Interface

Discussion in 'Scripting' started by Collin__Patrick, May 28, 2016.

  1. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    I an trying to make it so I can select the class I want a character to be, in the inspector via enum. I want to be able to convert the enum value into a interfece but dont know how. For an example if I choose "FighterClass" as my enum value, I want to set the "current class" interface to "FighterClass".

    This is an example of what I am trying to do. I know that I cannot cast a type into an interface instance.
    Code (CSharp):
    1. public enum CurrentCharacterClass{
    2.         FighterClass,
    3.         MageClass,
    4.         ArcherClass,
    5.         SpearmanClass,
    6.     }
    7.     public CurrentCharacterClass currentCharacterClass;
    8.  
    9.     void Awake(){
    10.         currentClass = new (ICharacterClass)currentCharacterClass();
    11.     }
     
  2. Craig8726

    Craig8726

    Joined:
    Jul 5, 2013
    Posts:
    79
    the class needs to be attached to a gameObject as a component ( public Class YourClass : Monobehaviour) then your public enum will be accessible in the inspector of the game object. From there you can create a switch in the update method to change things depending on the enum.

    Hope this helps and dot be afraid to ask questions the unity community is pretty friendly to new developers.
     
  3. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    I am very well aware that is an option, but if I use a switch, I will have more than I can manage making it hardly worth the effort. Also I don't think using the update method is a good idea, there is no reason for me to create a new instance every frame. Is there a way to condense a lot of switches or get the same effect?
     
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    Sure.

    You update whenever the class property is modified.

    Code (csharp):
    1.  
    2. public class Character : MonoBehaviour
    3. {
    4.  
    5.     public enum ChracterClass
    6.     {
    7.         Fighter,
    8.         Mage,
    9.         Archer,
    10.         Spearman
    11.     }
    12.  
    13.     [SerializeField()]
    14.     private CharacterClass _class;
    15.     private ICharacterClass _instance;
    16.     private bool _isAwake;
    17.    
    18.     void Awake()
    19.     {
    20.         _isAwake = true;
    21.         this.InitClass();
    22.     }
    23.    
    24.     public CharacterClass Class
    25.     {
    26.         get { return _class; }
    27.         set {
    28.             if (_class == value) return;
    29.            
    30.             _class = value;
    31.             if(_isAwake)
    32.                 this.InitClass();
    33.         }
    34.     }
    35.    
    36.     private void InitClass()
    37.     {
    38.         switch(_class)
    39.         {
    40.             case CharacterClass.Fighter:
    41.                 _instance = new Fighter();
    42.                 break;
    43.             case CharacterClass.Mage:
    44.                 _instance = new Mage();
    45.                 break;
    46.             //so on, so forth
    47.         }
    48.     }
    49.    
    50. }
    51.  
    52. public class Fighter : ICharacterClass
    53. {
    54.     //implement
    55. }
    56.  
    57. public class Mage : ICharacterClass
    58. {
    59.     //implement
    60. }
    61.  
     
  5. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,960
    You could make each interface you want derive from a base interface:
    Code (CSharp):
    1. public interface ICharacterBase {...}
    Code (CSharp):
    1. public interface IFighter : ICharacterBase {...}
    2. public interface IMage : ICharacterBase {...}
    3. public interface IArcher : ICharacterBase {...}
    Then instantiate it with a switch or if else:
    Code (CSharp):
    1. private ICharacterBase currentCharacter;
    2.  
    3. if (currentCharacterClass = CurrentCharacterClass.FighterClass) currentCharacter = new IFighter();
    But I must say that code like this looks incredibly suspect. What exactly are you trying to achieve? And is there a cleaner way to achieve it?
     
  6. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    If the main thing you're trying to do is get a dropdown in the Insepctor to choose which class of a certain interface to use, and you have a few extra dollars, I highly recommend FullInspector. Then you can just do:

    Code (csharp):
    1. [fiInspectorOnly]
    2. public class Character : MonoBehaviour
    3. {
    4.   public ICharacterClass class;
    5.   public ICharacterRace race;
    6. }
    and it will automatically give you dropdowns for all interfaces where you can pick which class to use and fill in the inspector with the fields for the class you chose.
     
  7. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    First, let me make it clear that I am not buying anything. Second, I already have the drop down in the inspector. Third, I am trying to condense the code so I am not making a switch with 100's of cases.

    What I am trying to achieve is taking an element from the enum and imply that that is the name of the interface instance I want. For example I have an element in the enum called "FighterClass"
    Code (CSharp):
    1. Public enum CharacterClass{
    2.      FighterClass
    3. }
    and I also have an instance of the interface named the exact same thing
    Code (CSharp):
    1. Public class FighterClass : ICharacterClass{
    2. }
    I want to be able to translate the element "FighterClass" in the enum into the "FighterClass" with the interface, thus removing the need for so many switches and reduces the line count from 300 to maybe 5.
     
  8. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,960
    Unfortunately this is not possible the way you want it. Enums in C# are simply symbolic, lexical wrappers for integral types. You will have to refactor your code.
     
  9. grizzly

    grizzly

    Joined:
    Dec 5, 2012
    Posts:
    356
    You could just use Reflection...

    Code (CSharp):
    1. public static T CreateInstance<T>(string name)
    2. {
    3.     Type type = Type.GetType(name);
    4.     return (T)Activator.CreateInstance(type);
    5. }
    6.  
    7. currentClass = CreateInstance<ICharacterClass>(currentCharacterClass.ToString());
    8.  
     
    Collin__Patrick likes this.
  10. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    Why are you using an enum then?

    I do something along these lines via reflection for my 'CharacterMovementController' class that has multiple modes for it.

    It just requires a custom editor script to draw the DropDown, and you store the name of the class, and you reflect the list of available classes.

    Here's how I get all types assignable to some base/interface type:
    Code (csharp):
    1.  
    2.         public static IEnumerable<Type> GetTypesAssignableFrom(System.Type rootType)
    3.         {
    4.             foreach (var assemb in System.AppDomain.CurrentDomain.GetAssemblies())
    5.             {
    6.                 foreach (var tp in assemb.GetTypes())
    7.                 {
    8.                     if (rootType.IsAssignableFrom(tp)) yield return tp;
    9.                 }
    10.             }
    11.         }
    12.  
    https://github.com/lordofduct/space.../blob/master/SpacepuppyBase/Utils/TypeUtil.cs

    You can say:

    Code (csharp):
    1.  
    2. var types = TypeUtil.GetTypesAssignableFrom(typeof(ICharacterClass));
    3.  
    This way you don't even have to write the long enum, make sure the enum names match the class name, and nothing like that.



    Note, this is what I use to serialize references to types:
    https://github.com/lordofduct/spacepuppy-unity-framework/blob/master/SpacepuppyBase/TypeReference.cs
     
    Collin__Patrick likes this.
  11. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    In this case, what is "Type" or what should it be changed to?
    Also are there any library's that I need, Unity says that it does not know what "Activator" is?
    *EDIT*
    I got it running now without errors but adding the System Library but how exactly does it work?
     
    Last edited: May 28, 2016
  12. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    reflection is built into .Net/mono

    the 'Type' class is a representation of a type

    Code (csharp):
    1.  
    2. var tp = typeof(SomeClass);
    3.  
    tp is just a runtime representation of the 'SomeClass' class.
     
    Collin__Patrick likes this.
  13. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    Ok I figured it out, I just didn't have my enum values set to the exact name of the class. Thank you to everyone who helped.