OO Design | Specific example

Hey,
I started a small prototype to get a grip on OOP in Unity. I like how my system works so far but I’m not happy with some parts of the design.

Here’s a simplified version of the code:

interface IPerson { IWeapon ActiveWeapon; }

class Bandit : Monobehaviour, IPerson { IWeapon ActiveWeapon;}


interface IWeapon { Attack(); }

class Revolver : Monobehaviour, IWeapon { Attack(); }
    
    
public class Controller : MonoBehaviour {
    
IPerson thisPerson;
    
    void Start () {
        thisPerson = (IPerson) GetComponent(typeof(IPerson));
    }
    
    void Update () {
        thisPerson.ActiveWeapon.Attack();
    }
}

It works just fine but…

1, I have to use non-generic way to obtain IPerson and I can’t define [RequireComponent (typeof (IPerson))] as IPerson doesn’t (can’t) inherit from MonoBehaviour

2, I can’t assign values in the editor. It would be very convenient to have public IWeapon currentWeapon; and assign different components to this but I can’t as IWeapon (or IPerson) can’t inherit from MonoBehaviour.

Could you please provide some feedback how to go around this? Thank you a lot for any input you might have.

I really want to use more structured way than my usual get this component, get that component … and force some methods using interfaces. Is it possible in Unity?

If I understand your questions correctly, I don’t think interfaces are really what you want. An interface is simple going to enforce that all classes that implement it conform. You can accomplish most of what you are after using simple inheritance:

public class BasePerson: MonoBehaviour
{
	public BaseWeapon ActiveWeapon;

	void Start()
    {
        //do whatever start up is common to all derived classes
        AddToStart();
    }
	
	//called by derived classes for implementation specific startup
	public virtual void AddToStart()
    {

    }
}

public class BaseWeapon: MonoBehaviour
{
	public virtual void Attack()
	{}
}

public class Revolver: BaseWeapon
{
	public override void Attack()
	{
		//instance specific attack
	}	
}

public class Bandit: BasePerson
{
	public override void AddToStart()
    {
		ActiveWeapon = new Revolver();
	}
	
	void update()
	{
		ActiveWeapon.Attack();
	}
	
}

This should get you most of the way there. If I’m not mistaken, if you want to set the 'Revolver" variable via the inspector, you’re still going to need a public GameObject variable and then use GetComponent to access the actual class. I see no need for your Controller class as you can simple add the derived “Person” class to your character. Hope this helps.

A few thoughts on this chain. The advice provided by gruhm from a professional and from a design standard is the correct answer and solution to this question. The advice being provided by Bunny83 is not a good design and will lead to performance issues due to the reliance on reflection. Let us be clear reflection is a huge performance cost and should be used with that in mind. Using reflection will always be slower than walking the inheritance chain.

If you follow what gruhm posted, it should be clear that a public GameObject property that gets and returns the actual class will allow you to assign values in the inspector, this can be done without the use of switches and or enums.

The comment that C# does not support multiple inheritance is correct yet also at the same time incorrect. It is true you can only do one inheritance per class, however if you design your classes the way gruhm suggested it should be clear that this limitation is not a limitation at all and actually can lead to better code design.

Allot of developers tend to use interfaces as a solution to the perceived notion that C# does not support multiple inheritance, in my opinion this is bad info and a bad reason to use an interface. An interface should never be used to implement multiple inheritance. An interface is implemented not inherited, it seems many people forget this fact.