Review of Components, Inheritance, and Interfaces

When thinking about how to approach the architecture of a game in Unity, which approach is the best? Components, Inheritance, or Interfaces? The answer is that these are really just different tools and techniques at your disposal - one is not necessarily better than the other.

Unity Documentation

Using Components - This section of the Unity manual details how to use components in the Unity editor.

C# Documentation

Inheritance - This section of the MSDN C# Programming Guide details the concept of object-oriented inheritance as it relates to the C# language.

Interfaces - This section of the MSDN C# Programming Guide details the concept of interfaces as it relates to the C# language.

Resources

Object-Oriented Programming in Unity - Project Files - This is a zip file that contains the Unity project for this course. Download the file, unzip it, and then in your file browser (Finder on OS X and Explorer on Windows) navigate to Assets > _Scenes. Finally, choose the scene you'd like to open.

0:00

We've gone from using components to
creating object oriented components

0:05

that use inheritance.

0:06

Then we learned how we
can use interfaces so

0:09

that characteristics can be shared between
classes that are otherwise unrelated.

0:16

When thinking about how to approach
the architecture of a game in Unity,

0:20

which approach is best, components,
inheritance, or interfaces?

0:25

The answer is that these are really
just different tools and

0:29

techniques at your disposal.

0:31

One is not necessarily
better than the other.

0:34

In fact, in this game,
we're using all three.

0:37

Let's take a quick look to remind
ourselves how this is put together.

0:42

In the hierarchy,
select the Bow game object.

0:46

Then in the Inspector,

0:49

recall how the behavior of this
game object is actually composed

0:54

of two different scripts,
Shoot Arrow and Mouse Rotation.

1:00

These two scripts make sense as
separate components because each of

1:05

them serves a clear purpose.

1:07

And, other than the fact that
they're on the same game object,

1:10

they really don't have much
to do with one another.

1:14

Now in the Project window,
Go to the Prefabs folder.

1:21

And take a look at the stationary and
moving targets.

1:26

The stationary target
uses the target script.

1:33

And the moving target uses
the moving target script,

1:38

which inherits from the target script.

1:43

Well, we could have integrated
the moving target code into

1:46

the target script somehow and

1:48

then added a boolean variable to determine
if the target should be moving or not.

1:53

We could have also kept
the code the way it was before,

1:57

where there was only one target prefab and
it had two components on it,

2:02

one for the stationary code and
one for the moving code.

2:06

And then there's probably several
other ways of accomplishing the same

2:10

functionality as well.

2:12

Finally, we also created
the interface I targetable.

2:16

Any script components that implement
the interface can be hit by an arrow and

2:20

react to it in some way.

2:23

The question remains,
when faced with a programming problem,

2:27

should you choose components,
inheritance, or interfaces?

2:31

There are no hard rules about this, but
here are a few things to consider to guide

2:36

your thinking when you make
these types of decisions.

2:40

Inheritance is useful when you have

2:42

slightly different versions of the same
object, like in the case of our targets.

2:47

We have a basic target type, but then if
we want more specific types of targets,

2:52

such as moving targets,
we can inherit from the base class and

2:56

only write the part that's different,
rather than duplicating the same code.

3:02

Components are useful
when you have simple and

3:05

clear functionality that has
a single responsibility.

3:09

For example, on the bow, there's a script
called mouse movement that moves the bow

3:14

around in response to mouse movements and
limits it to a rotation range.

3:20

That script might be reusable if we
were to create other types of prefabs,

3:25

such as a crossbow or a grappling hook,
which would move in the exact same way.

3:31

The important idea here is that
a component should do just one thing and

3:36

do it well.

3:37

That's the power of single responsibility,

3:40

rather than a component doing
lots of different things.

3:45

Interfaces are useful when you
have a piece of functionality or

3:49

a characteristic that should apply
to several different classes, but

3:53

otherwise don't have anything
to do with one another.

3:56

For example, the targets are different
from the destructible props, which is also

4:01

different from the scoreboard, but they
should all react to arrows in some way.

4:06

The same types of problems
that interfaces solve

4:08

could also be solved with components.

4:11

As mentioned previously, you could, for
example, create a targetable component.

4:17

The difference is that interfaces
are generally better at separating

4:22

the different variations on methods.

4:26

For example, let's say that instead of
creating the targetable interface, you

4:32

created the concept of a game object
being targetable as a component.

4:39

We could add that to any game object
that needs to be hit by an arrow.

4:44

But only the targets award points.

4:47

So we would need to add
an if statement and

4:50

a boolean variable that's exposed in
the inspector to determine whether or

4:54

not a targetable game
object should award points.

4:58

Then only the destructible props
should destroy their game object,

5:03

but the scoreboard and
the target should not.

5:06

So that's another boolean and
another if statement.

5:10

You can see where I'm going with this.

5:12

The more different types of
reactions you want to have,

5:14

the more complex a single
component is going to become,

5:18

which breaks the idea of a component
having a single responsibility.

5:24

Finally, as a general rule, you should try
to favor composition over inheritance.

5:31

Sometimes, like in the case of
our targets, a game object really

5:35

is just a slightly different subset of the
same object and inheritance makes sense.

5:41

But what if we instead made our game so

5:44

that anything that got hit by an arrow
inherited from the same target class?

5:50

Then our game props and the scoreboard
would all be in one rigid tree of classes.

5:56

And if we come up with a piece of
functionality that belongs somewhere in

6:00

the middle of that inheritance tree,
then it's difficult to change.

6:04

It's a hard lesson to learn, and you'll
probably make that mistake a few times in

6:09

your programming experiences before you
get a better sense of when to inherit and

6:14

when to use components or interfaces.

6:18

Object oriented programming is a huge
topic that's been around for a long time.

6:23

And there's always more to learn,
but that covers the basics.

6:27

The thing I want you to remember is that
there's a lot of different ways to do

6:31

the same thing, and none of them
are necessarily correct or incorrect.

6:36

The best option isn't always clear,
and in fact,

6:40

I encourage you to play with this project
after this course and find some ways of

6:45

doing things that might work better than
the way that I had us write this code.

6:49

Conversely, sometimes you'll make bad
choices that seem like a good idea

6:53

at the time.

6:55

The true test of code quality is how
easily you can modify the code later on.

6:59

And it takes some time and practice to
determine if your code passes that test.