Implementation question: Classes instantiating prefabs, or multiple prefabs with classes?

Hello everyone.

This is more like a discussion on which would do better in terms of implementation rather than an actual question, but here it goes:

In my game (something like an RTS, to make things a little bit clearer), I want each unit in game to be an instance of the class named Unit, which contains things such as an inventory, and all the stats for that single unit, I’m working on that so I can store everything I need to make units work independently and be able to take simple orders by themselves (like move there, or, get that thing into your inventory).

Anyway, so I’ve come into two different ways of doing this and I don’t know which would do better:

First I had thought of creating a prefab named Unit, with my Unit script attached on it, so that script would give my unit each property it needs (a 3d model, an HP value and so on…) But then I thought that if I wanted to do that through code, i could approach this in a different way which I think should work as well.

Let’s say I create the unit class, and instead of attaching it to a gameObject in the scene, I create instances of that class through code. And then, those instances are able to Instantiate an animated 3d model in scene and are able to control it, so I have many instances of that class in memory controlling a 3d model in the actual game but not being “inside” that gameObject.

What’s the best way to implement what I want? I don’t fully understand how unity works at that level, so I’m not able to decide which one would do better, I see both ways to be viable and I also can find some pros and cons, for example:

If I use the first method, I can easily access each unit’s Unit class, let’s say, with a rayCast where the mouse is clicking.

However, if I used the second method, I find it easier to save all my Unit instances into an array, not having to save the whole prefab multiple times, but a bunch of numeric values which I store in the class. Also, having an array with all the units in game seems easier with this second method.

Taking into account the way in which unity works, I find the first way to be more logical, however I don’t want to start coding in one way and then find out that the other one had some serious advantages.

Thank you very much

You must understand that the script you create that can be attached to game objects inherit from MonoBehaviour. That allow them to receive messages like Update, Start etc. However, you cannot instantiate them like any object with a new keyword. You need to either drag them in the editor on the gameObject, or to use AddComponent.

This being said, I suggest you create a class called UnitPool (or whatever) that contains all the instances of units, all inactive at first. This class must be able to provide an instance of a unit (activating it) or recycle one that is dead (inactive). That way, you don’t need to use Instantiate, which is quite expensive, and you can keep track of all the active instance.

This may be usefull.


First, the hierarchy so everything is well sorted in the hierarchy view. You don’t HAVE to do it, but it’s cleaner. So, create a GameObject named UnitPool, reset transform, add the script UnitPool.cs/js to it (I’ll get to that later). Then create other empty go with relevant names for those Units (Troopers, Tanks, etc), make them children of UnitPool, reset transform. Finally, drag you’re unit(s) prefab on the scene, make it child of the corresponding go and duplicate them 20 (or more). Select them all and uncheck the active checkbox.

The script now. Declare as many arrays as you have types of units. Assign them the duplicates in the inspector. Create an enum with the name of your units, like enum UnitType{ Trooper, Tank }. Then, create a function that returns a gameObject depending on the type :

// PS : It would be smart to create a class that does the array access, counter and wrapping.
public GameObject GetUnit( UnitType type )
{
    GameObject unit = null;
    switch( type )
    {
        case UnitType.Trooper : unit = trooperArray[ trooperCounter ];
                                trooperCounter++;
                                // Wrap the counter when we reach the end
                                trooperCounter = trooperCounter >= trooperArray ? 0 : trooperCounter;
                                break;
        case UnitType.Tank : unit = tankArray[ tankCounter ];
                                tankCounter++;
                                // Wrap the counter when we reach the end
                                tankCounter = tankCounter >= tankArray ? 0 : tankCounter;
                                break;
    }
    // Re-active it
    unit.SetActiveRecursively(true);

    // An init function is probably needed here, to restore health for instance
    return unit; 
}

Finally, a recycle function. The point is to make the unit disappear when it’s dead without destroying it. Basically, you just use SetActiveRecursively(true);. You might have to reset the parent if you changed it.

public void Recycle( GameObject unit )
{
    unit.SetActiveRecursively(false);
    unit.transform.localPosition = Vector3.zero;
    unit.transform.localRotation = Quaternion.identity;
}

As you may understand, you need at to have enough pre-instantiated units for any possibilities in your game. The best is probably to limit the number the player can create.