Lesson 18 - Object-Oriented Programming Intro

Tutorial Series: Introduction to Unity with C# Series

Previous Article  |  Next Article


Here we are ready to talk about Object Oriented Programming or OOP for short. You will be forgiven for wondering what all the fuss is about or if you are confused about a strange-sounding title. Objects, where are these objects, how do they relate to coding? Those would all be very common questions and you are about to learn the answer. Behind the mystique and scary-sounding lingo, the principles behind OOP are the same as every other coding principle you will come across. Ultimately simple concepts when understood as a piece within a larger puzzle. I think your poised at this point to easily tackle the OOP piece of the puzzle, having come to understand everything we have covered so far. Actually you probably didn't realize it but you have been doing OOP all along, because at the heart of OOP is a concept of separating your code into classes. Which is what we have been doing with every script we have written this far, but we have seen only 1 side of the 2-sided coin. A coin which on 1 side has a class definition and on the other side, an object instance of that definition.

Basically stated, when you are building a class, it is much like building a blueprint for an object that will be created later off of that blueprint. It is like when we construct our instructions within our method definitions only to be executed later once the method is called. It is much the same in that you have a class definition which is what we have been creating so far, that 1 side of the coin, that actually doesn't represent anything substantive until it is used to create and instance of it, by creating an object in memory, which we will get to exactly what that means in a moment. Yeah, we are going to expand on our simple understanding of classes as just simply labelled containers. They are labelled containers of information that describe the type of object you can create from it. Emphasis on type for reasons that you will soon see. Let me give you a simple example to illustrate this relationship between a class and an instance. Think in your mind of any actual object that exists in the world, any object; a tree, a house, a person. These can all be described by the class that they belong to. A tree clearly belongs in a very different class from a person or a house, right? Within that class or classification of that type of object in question is a description of its physical properties, which you can consider something like its fields As well as what it does or its behaviors and processes which you can think of as its methods. Its methods of achieving some end result, right? A tree might have a method of growing and, well, a human might have a method of growing, too. But they will be very different in those 2 different classes.

The object class that we are most naturally in tune with, I would say, and have a strong intuition of is our own. The class we call human, right? We can quickly call to mind common properties or fields which every human has in common. They will have unique values in describing each actual human being object as it were. For example, we have things like gender, height, age and so on. Those will be like the fields in the class human and the class definition, those fields and so on, will have to be broad. That it can refer to a range of actual human objects. Clearly, humans share a lot of things in common such as those traits, but we all have our own unique values in those fields and methods as it were. That is where the object instance comes into play. The class represents the broadest possible definition and remains just a definition until you build from it an actual instance of an object of that class. When you were born you became a new instance of the class human from that partial class blueprint called DNA, right? Taking this analogy back to objects and code, how do we give birth to a new instance of a class and code, thereby making an actual instance of an object in memory?

This is the basic structure of creating a new object in memory. You have the class. You start with somewhere in code your class name, in other words the name of your class. Some identifier or in other words like any other variable name. Then you have the equal sign, the assignment operator followed by the new keyword. New simply meaning a new object of this type followed by yet again a reference to the class name with either empty or non-empty parentheses after it. Then we terminate it with the semi-colon as usual. As you can see, it is surprisingly easy to create an object or a class instance, but so far all of our classes that we have been writing have had their object instances automatically handled and created by the Unity engine. Owing to a somewhat technical fact that I don't really want to go into too much right now. Remember how I mentioned that the stuff you write in the Update() and Start() method definitions eventually get called somewhere off in Unity? Well, so too do we see this in effect or should I say not see this in effect, with our object instances of the scripts we are creating. Simply stated, when we create a class that is also a MonoBehaviour, that deals a bit with inheritance which we won't go into just yet. Remember all the scripts we were writing, they have that reference to MonoBehaviour. When we create a class that has a MonoBehaviour, we are handing the instantiation of that class as well as the calls to common methods to that class like Start() and Update() We are handing that off to the Unity engine to handle all that outside of our view. We actually don't see the process of instantiation and calling those methods at work, but it is happening somewhere off in that Vortex of the Unity engine. Right?

Examining those MonoBehaviour scripts we have been writing won't really help you understand how this object model works. What we are going to do is now create a brand-new class and unlike all of our previous classes that have been MonoBehaviours, we won't directly embed it into the Unity engine by making it a MonoBehaviour. Instead, we will just have it not inherit from MonoBehaviour and we will have another script which is a MonoBehaviour, incorporate it. Right? You will see what I mean in a second. Basically this script, this class will just be a pure C# class. That way we will be able to better see how constructing classes and objects really works. The first thing I am going to want to do is create a non-MonoBehaviour script. In other words a script that doesn't derive from MonoBehaviour. In your Test folder, let's create a new script and let's call it NonMonoBehaviour. We will open that up. And here we go. We will remove MonoBehaviour so it is no longer inheriting from MonoBehaviour, we are no longer handing the job of instantiation and so on off to the Unity engine. Because it is not a MonoBehaviour we lose these references to Start() an Update(). They don't really have the same meaning they had before. Now let's do this, actually we will call it ... We have NonMonoBehaviour, I shouldn't have called it that, that is too broad. Actually we will rename it, this class, to Person. I don't actually have to rename the C# script here but I don't want to confuse you. Let's just call it Person, let's just keep it really simple. It is called Person and do the same thing. Call it Person. Take out those references, and we will write some fields for our class Person. string Name. Alright, so that is a pretty common property, string Gender; int Age. Alright? Some simple as I said common properties.

We will save that class and now we need to create an object of it in another class. Go back to Unity and this time we will make a new script but this one will be a MonoBehaviour because we want to output it to the Unity engine. Let's call it PersonFactory and before I forget, make sure you attach it to our game object so we can again see the output. We want to see the output of PersonFactory, attach it there and disable the other scripts. And let's write this in PersonFactory. Right? Because it is a MonoBehaviour we do make use of Start() and Update(), but we will remove Update() and we will just simply make our object instance of our Person class. Write this in: 'Person' and then I don't want to confuse you, but lowercase p, person. This is our variable name. It could be anything, but I am using a lowercase to show you that it is different. Remember it is case sensitive in C# so it is different from the actual class name Person with the uppercase P. person = new Person() with empty parentheses and a semicolon on the end. I am not even going to run this, because it is not really going to output anything of meaning to the Unity game engine.

The first thing I want to note to you is that now that we have a person, we have a person object off of that blueprint in our code, in our class PersonFactory here. Normally, what we would do to access the fields in that actual object would be to use the dot-accessor. person, lowercase p is now a variable, so we reference it yet again just by typing it again. We hit the dot-accessor and we notice that there are no fields where is Gender, Age and so on. Name as well, right? Where are they? Well we need to make the fields public so they are publicly viewable in outside classes, not just viewable within this class called Person. Just simply prefix all of these fields with public. No, definitely not that (laughs) public and we will save that. Now I will type this out again. Let's establish our fields for a new person. person and then we hit the dot-accessor, and there you see already our public fields are available to us. The first one I am going to create a value for our unique person object, is person. Name and type whatever you want in. Then person. Gender, again whatever you want as long as it is a string and person.Age. There you go, I am going to type in 26. Mario, Male, 26. I am not sure if you all know who I am referencing, you probably do given that this is a game development course that you are looking at right now. Now we will want to output this to Unity, so we will access the Debug.Log() as we have become used to. First the Name and then the Gender. Whatever order you want to do it in, it doesn't have to be the same order that you established those fields. We will do it in the same order when we output; Name, Gender and Age, right? We will save that and show the output just so you can see what we are doing. There you go; Mario, Male, 26. We have got this person object and we have output its fields to the Unity engine.

Related Articles in this Tutorial:

Lesson 1 - Who This Course is For

Lesson 2 - What to Expect from this Course

Lesson 3 - Installation and Getting Started

Lesson 4 - Starting the First Project

Lesson 5 - Prototype Workflow

Lesson 6 - Basic Code Review

Lesson 7 - Game Loop Primer

Lesson 8 - Prototyping Continued

Lesson 9 - C# Fundamentals and Hello World

Lesson 10 - Variables and Operations

Lesson 11 - Variables and Operations Continued

Lesson 12 - Floats, Bools and Casting

Lesson 13 - If Statement Conditionals

Lesson 14 - If Statements Continued

Lesson 15 - Complex Evaluations and States

Lesson 16 - Code Syntax vs. Style

Lesson 17 - Variable Scope

Lesson 18 - Object-Oriented Programming Intro

Lesson 19 - OOP, Access Modifiers, Instantiation

Lesson 20 - Object Containment and Method Returns

Lesson 21 - "Has-A" Object Containment

Lesson 22 - "Is-A" Inheritance Containment

Lesson 23 - Static Fields and Methods

Lesson 24 - Method Inputs and Returns

Lesson 25 - Reference vs. Value Types

Lesson 26 - Introduction to Polymorphism

Lesson 27 - Navigating the Unity API

Lesson 28 - Applying What You've Learned and Refactoring

Lesson 29 - Constructors, Local Variables in the Update Method

Lesson 30 - Collecting Collectibles, Items and Powerups

Lesson 31 - Spawning and Managing Prefab Powerups

Lesson 32 - Implementing Powerup State Logic

Lesson 33 - Displaying Text, OnGUI, Method Overloading

Lesson 34 - Referencing Instantiated GameObjects, Parenting

Lesson 35 - Understanding the Lerp Method

Lesson 36 - Creating Pseudo Animations in Code

Lesson 37 - Understanding Generic Classes and Methods

Lesson 38 - Animations Using SpriteSheets and Animator

Lesson 39 - Working with Arrays and Loops

Lesson 40 - Debugging Unity Projects with Visual Studio

Lesson 41 - Camera Movement and LateUpdate

Lesson 42 - Playing Audio Clips

Lesson 43 - Routing Audio, Mixers and Effects

Lesson 44 - Adding Scoring Mechanics and Enhancements

Lesson 45 - Scene Loading and Game Over Manager

Lesson 46 - Understanding Properties

Lesson 47 - Controller Mapping and Input Manager

Lesson 48 - Understanding Enums

Lesson 49 - Dealing with Null References

Lesson 50 - Handling Variable Framerates with time.DeltaTime

Lesson 51 - Preparing the Project for Final Build

Lesson 52 - Final Build and Project Settings

Lesson 53 - Introduction to the Unity Physics Engine

Lesson 54 - Understanding FixedUpdate vs. Update

Lesson 55 - Movement Using Physics

Lesson 56 - Attack Script and Collision Events with OnCollisionEnter2D

Lesson 57 - Projectiles and Stomping Attack

Lesson 58 - Parallax Background and Scrolling Camera

Lesson 59 - Infinitely Tiling Background Sprites

Lesson 60 - OOP Enemy Classes

Lesson 61 - OOP Enemy Classes Continued

Lesson 62 - Trigger Colliders and Causing Damage

Lesson 63 - Multi-Dimensional Arrays and Procedural Platforms

Lesson 64 - Finishing Touches

Lesson 65 - Series Wrap


Please login or register to add a comment