C# – Unity3D – Abstract Class, Monobehaviour functionality

c++, inheritance, unity3d

PREAMBLE

So I've been floating this question around on the Unity Answers forum for the past couple of weeks without a single reply. It seems to me that it would be a relatively straight forward question so I was wondering if anyone here might be able to help me with it in lieu of an answer over there.

So I have a bit of a dilemma.


GOAL

I want to use an inheritance structure for guns in my game. I want to make an abstract class (Gun) and then have subclasses of Gun (Laser, Rifle, RocketLauncher) which inherit from it and then create specific instances of these weapons. At the moment I'm doing this as an abstract class because there's a large variance between the way different subclasses of Gun implement the Shoot() function. (i.e. A rocket launcher will instantiate X Rocket GameObjects whereas a laser will probably use raycasting to determine an instant hit).

Furthermore, I would like to be able to have a List of Guns in the Players inventory and don't want to have to add and remove Scripts from my Player dependant on their active weapon. It's just nice for me if I can construct them in the following fashion:

Rifle ActiveWeapon = new Rifle(parameters);

I also don't want to have a finite number of weapons available to the player but want to be able to generate them at runtime (as drops or crafted for example) so I also don't want to write a fixed number weapon scripts.


ISSUE

The issue I'm encountering is that I want to be able to utilise some of the methods which are derivative of MonoBehaviours for example :

public override void Shoot () {     if (CanShoot)      {         StartCoroutine(Cooldown());         Rigidbody bullet = Rigidbody.Instantiate(BulletPrefab, transform.position, transform.rotation);         ... // Addforce etc.         ...     } }public IEnumerator Cooldown() {     CanShoot = false;     yield return new WaitForSeconds (FireRate);     CanShoot = true; }

Obviously since this isn't a MonoBehaviour class I can't use functions such as Instantiate to create bullets or WaitForSeconds to stagger them.

How should I tackle this issue?

Best Solution

You can have an abstract class that inherits from MonoBehaviour, the following works fine:

public abstract class AbstractClass : MonoBehaviour{    protected abstract void pouet();}public class InheritClass : AbstractClass {    // Use this for initialization    void Start ()    {        StartCoroutine(pouetCoroutine());    }    protected override void pouet()    {        Debug.Log("pouet");    }    private IEnumerator pouetCoroutine()    {        yield return null;        pouet();    }}

If you don't want your abstract class to be in a GameObject, you could use an external gameobject to manage the instanciation with an object pooling system.

About the coroutines, you could use a coroutine engine that starts and stop them. You only need to have a dictionary and a public function to start the coroutine and keep an id as a key to access it if you need to stop it later.

private startcoroutine(int id, IEnumerator ienum){    Coroutine c = StartCoroutine(ienum);    dictionary.Add(id, c);}