Generic MonoBehaviours

MonoBehaviours in Unity are generally pretty cool, but can instantly become uncool when you want to work with Generics. The UnityEditor doesn’t know how to find and instantiate generic behaviours. It won’t even let you attach them, but there is a solution.

A Broken Example

Let’s say we had a set of car parts defined.

// Base CarPart class
public abstract class CarPart
{
	public abstract string getDescription();
}

// Car Part Impelementations
public class Wheel : CarPart
{
	public override string getDescription()
	{
		return this + ": Spins to make the car go!";
	}
}

public class Door : CarPart
{
	public override string getDescription()
	{
		return this + ": Opens to let people get in!";
	}
}

We want to be able to assign car parts to game objects using a CarPartBehaviour. If we want to maintain some specific typing, Generics are obviously a great solution, so we create a generic CarPartBehaviour<CarPart> class.

using UnityEngine;

// Car Part Behaviour
public class CarPartBehaviour<T> : MonoBehaviour where T : CarPart
{
	private T _carPart;
	public T carPart
	{
		get { return _carPart; }
		set { _carPart = value; }
	}

	protected virtual void Awake()
	{
		printDescription();
	}

	public void printDescription()
	{
		Debug.Log(_carPart.getDescription());
	}
}

If you create a few test objects and try to attach a CarPartBehaviour  script component to them, you will get some type of error depending on your version of Unity. This is what I am seeing in 5.0.2.

CaptureSo now what…?

The Solution – Extension

The solution might be a little cumbersome, but one exists- You need to create an extending MonoBehaviour for each CarPart type.

using UnityEngine;

public class WheelBehaviour : CarPartBehaviour<Wheel>
{
	public WheelBehaviour()
	{
		carPart = new Wheel();
	}
}
using UnityEngine;

public class DoorBehaviour : CarPartBehaviour<Door>
{
	public DoorBehaviour()
	{
		carPart = new Door();
	}
}

You should now be able to assign wheel and door behaviours to objects in your scene. Any code in the base CarPartBehaviour class will still work.

It’s not the perfect solution, but its a decent work around. The best part is that any GetComponents functions will work with CarPartBehaviour!

Hope this helps someone out there. Happy building!

-S

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *