Object Oriented Programming In Unity

I’m having trouble understanding the relationship of OOP in unity. I understand that when you write a script and attach it to a game object, that object takes on those properties.

What I’m confused about is: Would it be better to simply use variables to give a game Object characteristics than trying to create a class or java script object?

I’m just starting to think it would be easier to make a variable called “weapon damage” and assign it a value than to make a class full of weapon vars and use that. Am I wrong?

Hello,

I’m new to Unity3D. I’m used to Object Oriented Programming. Going from Java → Unity3D and C#, I was looking for a good way to structure my classes, including game object properties and inheritance from super classes shared by different prefabs that each have their own subclass scripts. Below is one way to do it. If my reasoning and solution below feels obvious and trivial, feel free to disregard. This was a way for me to learn and find out a solution as many other answers were not as detailed and they lacked examples.

Let’s say I want to have some prefab game objects:

  • a Vampire game object
  • a Skeleton game object

They have their own special properties, implemented in corresponding scripts

  • Vampire script (class)
  • Skeleton script (class)
    typically added to their prefabs.

… but I want them to share properties and behaviour from an abstract super class “Creature”.
The class hierarchy could be much more sophisticated (e.g. Creature has other subclasses, like Human, Animal, etc), but to keep this example simple, this is one way to do it:

The super class “Creature” inherits the MonoBehaviour:

public class Creature : MonoBehaviour
{
	int hp;
	string name;

	//This works as a base constructor, to be called in the subclass's Awake() or Start()
	public void Init(string name, int hp)
	{
		this.hp = hp;
		this.name = name;
	}

	public virtual void ShowStats()
	{
		print("Hello, I'm "+name+", and my HP= "+hp);
	}
}

The Vampire and Skeleton classes inherit from Creature… and they can add extra behaviour, e.g. in overriding methods:

public class Vampire : Creature {

    // Use this for initialization
    void Start()
    {
        base.Init("Vampire", 2);
    }

    public override void ShowStats()
    {
        base.ShowStats();
        print("... and I'm a blood sucker too!");
    }
}

public class Skeleton : Creature {
    // Use this for initialization
    void Start()
    {
        base.Init("Skeleton", 1);
    }
}

The sub classes - NOT Creature - will be attached to the Vampire and Skeleton prefabs.
The game logic can then find all game objects tagged with “Creature” and iteratate through them, like this:

public class GameLogic : MonoBehaviour {
	// Update is called once per frame
	void Update () 
	{
        if (Input.GetKey(KeyCode.Space))
        {
            foreach ( GameObject creature in GameObject.FindGameObjectsWithTag("Creature"))
            {
                creature.GetComponent<Creature>().ShowStats();

                //We can then invoke creature specific behaviour, e.g.
                if (creature.name.Equals("Vampire"))
                {
                    //Do some cool vampire-specific stuff, e.g life draining...
                }
            }
        }
    }
}

This gives us…

  • Hello, I’m Skeleton, and my HP= 1
  • Hello, I’m Vampire, and my HP= 2 … and I’m a blood sucker too!

Advantages:

  • Only one actual GameObject is needed to contain both subclass and superclass(es).
  • Only one script (the subclass) needs to be attached to the prefab. Super class script(s) are included through inheritance.

Drawback with my outlined solution without a constructor:
I did not use a constructor as the Unity framework recommends using Awake() or Start() instead of normal class constructurs. Therefore, superclass initializer parameters is not enforced by compile errors, so it is possible to “forget” to pass initializer parameters to the superclass. There are surely ways to solve it. One way could be to create an abstract method in the superclass to, sort of, remind the implementor which parameters to initialize. But maybe there are better and more correct ways.

Another disadvantage:
If we want a clean logical model of our game objects, without connections to the actual “view”. Consider the Model-View-Controller design pattern where Unity GameObjects are intimately associated with the View.
While programming AI, we might want to handle a pure logical model of the game world to evaluate possible game world changes and future moves and positions of game creatures WITHOUT showing it in the view! In this case, we don’t want all that extra stuff inherited from the Unity framework in our objects, because sometimes, we won’t always create those GameObjects. We only want temporary “abstract” models for the AI algorithm to evaluate.
For this case, it may be better to have a pure logical class hierarchy of the game world and creatures in it, without inheritance from Unity MonoBehaviour. In that case, the Creature class shall NOT inherit from Unity MonoBehaviour. Instead the default script in each creature prefab should CONTAIN a pure logical Creature object (instantiated as the proper subclass.) In this case, we use OO “composition” instead of OO “inheritance”.

Please let me know if I got this all wrong and if it would be natural to do something entirely different, but it seems to work for me.

Best Regard
/Christian, Craze Music / Craze Creature Studios
www.craze.se

Yes… your impression that it’s more complex than in more ‘traditional’ languages betrays you not…

The pitfalls of Unity’s JavaScript. I struggled with this just like you…

The thing is: if you ‘just make a Script’… you are not actually ‘just making a Script’ ^^

You ARE, in fact, already making a class.

Unity just doesn’t tell you about it, it’s doing it behind the scenes…

Edit:

I’m just starting to think it would be
easier to make a variable called
“weapon damage” and assign it a value
than to make a class full of weapon
vars and use that. Am I wrong?

So basically… you are neither right nor wrong, you are just confused… because you can’t make a variable without having it inside a class.

But the question you are asking in the background: should I have a class ‘Weapons’ with ‘granade = 40 damage, ak47 = 20 damage, pistol = 10 damage’ or rather a class ‘WeaponDamage’ with ‘damage : int’, put that on your granade, ak47 and pistol and have it adjusted accordingly. Then the answer is YES, the latter is usually the better approach.

Make your way through the ‘oop’ and ‘scriptingbasics’ tags for more information…

Interesting question though, where prefabs come in to that… I don’t know if they are classes…? probably…

Greetz, Ky.

OOP is fundamental in modern software - specially in game engines - because it allows multiple clones of the same object to live independently at the same time. In a FPS game, for instance, you may have dozens of enemies patrolling around; when one of them find the player, it starts the chasing - but the others will continue in patrol, so they must be independent instances.

When you instantiate an object, everything in it is cloned - including the scripts and its variables - so it can be completely independent of all other instances. That’s why an Unity script is a class: a class contains its own variables, properties, methods etc., thus is able to be instantiated with total independence.

I understand that when you write a
script and attach it to a game object,
that object takes on those properties

Then you understand wrongly, GameObjects have a list of components. A script is a type of component. When you attach a script, the GameObject gets that component, and that component has properties. Look at how they are accessed:

myGameObject.GetComponent.<MyComponent>().myProperty

not:

myGameObject.myProperty

Nothing magical, just normal OO containment and reference.