๐ Lesson 1.1: MonoBehaviour and the Component Model
You already know how to write C# classes. In Unity, most of the classes you write are a special kind: components. This lesson explains what a MonoBehaviour really is, why you never new one, and why Unity builds behavior by composing small components instead of growing deep inheritance trees.
๐ฏ Learning Objectives
By the end of this lesson, you will be able to:
- Explain the relationship between a GameObject, a Component, and a MonoBehaviour
- Describe where
MonoBehavioursits in Unity's class hierarchy and what it gives your script - Write a minimal MonoBehaviour and attach it to a GameObject
- Explain why you use
AddComponentinstead of a constructor, and whynew MyScript()is wrong - Apply composition over inheritance to design game behavior as small, reusable components
Estimated Time: 60 minutes
Project: Build a GameObject out of small single-purpose components โ a spinning, self-destructing pickup โ without a single line of inheritance.
In This Lesson
From Plain Classes to Components
In the "Introduction to C#" course you built classes that you controlled from top to bottom: you called new, you invoked methods, you decided exactly when everything ran. A console app has one entry point โ Main โ and you drive it.
Unity flips that around. There is no Main that you write. Instead, the Unity engine runs the loop, and your code is invited in as the engine ticks along. The way you plug your C# into that engine loop is by writing a component and attaching it to an object in the scene.
๐ Definition
Component: a piece of behavior or data that you attach to a GameObject. A Transform, a Rigidbody, a Camera, and every script you write are all components. A GameObject is essentially a bag of components.
This is the single most important mental shift for a C# programmer arriving in Unity: you rarely build one big class that "is" the player. Instead you assemble a Player GameObject out of many small components โ one for movement, one for health, one for the camera โ and Unity runs them all. Let's take that apart.
GameObjects, Components & MonoBehaviour
Three words get used constantly in Unity, and beginners blur them together. Keep them distinct:
| Term | What it is | Analogy |
|---|---|---|
| GameObject | A container that lives in a scene. On its own it does almost nothing โ it just holds components and has a name, a tag, and a layer. | An empty pegboard. |
| Component | A unit of data or behavior attached to a GameObject (Transform, Rigidbody, Light, your scriptsโฆ). | A tool you hang on the pegboard. |
| MonoBehaviour | The base class you inherit from so that your C# class is allowed to be a component and hook into the engine. | The standard mount that lets a tool hang on the board. |
Every GameObject always has at least one component: a Transform, which stores its position, rotation, and scale. You can never remove it. Everything else โ renderers, colliders, and your scripts โ you add on top.
(position, rotation, scale)"] GO --> R["Rigidbody
(physics)"] GO --> C["Collider
(collision shape)"] GO --> S1["PlayerMovement
(your script)"] GO --> S2["Health
(your script)"] style GO fill:#eff6ff,stroke:#3b82f6,stroke-width:2px style S1 fill:#e8f5e9,stroke:#4CAF50,stroke-width:2px style S2 fill:#e8f5e9,stroke:#4CAF50,stroke-width:2px
The green boxes are the scripts you write. They sit right alongside Unity's built-in components โ from the engine's point of view, your Health script and its own Rigidbody are the same kind of thing: both are components attached to the GameObject.
โ ๏ธ Important: A script asset sitting in your Assets folder does nothing on its own. It only runs when an instance of it is attached to a GameObject that exists in a loaded scene. "Attaching" a script is creating a component instance.
Where MonoBehaviour Comes From
When you write class Health : MonoBehaviour, you are inheriting a whole chain of Unity base classes. Each link in that chain hands your script another capability. Here is the real hierarchy:
can be referenced in the Inspector; Destroy() works on it"] O --> Comp["Component
knows its GameObject & Transform; GetComponent, CompareTag"] Comp --> Beh["Behaviour
adds the 'enabled' switch"] Beh --> Mono["MonoBehaviour
adds event functions (Awake/Start/Updateโฆ) & coroutines"] Mono --> Yours["Health : MonoBehaviour
(your script)"] style Mono fill:#eff6ff,stroke:#3b82f6,stroke-width:2px style Yours fill:#e8f5e9,stroke:#4CAF50,stroke-width:2px
You don't need to memorize the chain, but a few facts from it explain things you'll use every day:
- From
Object: your component can be dragged into an Inspector slot as a reference, andDestroy(...)can delete it. - From
Component: you getgameObject,transform,GetComponent<T>(), andCompareTag(...)for free โ no fields to declare (we cover these in Lesson 1.3). - From
Behaviour: theenabledflag. Setenabled = falseand Unity stops calling this component'sUpdate. - From
MonoBehaviour: the ability to define event functions likeAwake,Start, andUpdatethat the engine calls automatically, plus coroutine support. That is the whole point of inheriting it โ it's your hook into the game loop, which is the subject of Lesson 1.2.
๐ก Not every script is a MonoBehaviour
Only classes that need to live on a GameObject and respond to the engine loop inherit MonoBehaviour. Plain data classes, helpers, and static utilities stay as ordinary C# classes โ and you do new those normally. Reserve MonoBehaviour for "this thing is attached to something in the scene."
Your First MonoBehaviour
When you create a script in Unity (right-click in the Project window โ Create โ C# Script), you get a template like this. Two rules matter: it inherits MonoBehaviour, and the class name must exactly match the file name (a Health.cs file must contain class Health), or Unity won't let you attach it.
using UnityEngine;
public class Health : MonoBehaviour
{
// A field marked public shows up in the Inspector so a designer can tune it.
public int maxHealth = 100;
// A private backing value โ not shown in the Inspector by default.
private int currentHealth;
// Called once by Unity before the first frame. (More on this in Lesson 1.2.)
void Start()
{
currentHealth = maxHealth;
Debug.Log($"{gameObject.name} spawned with {currentHealth} HP");
}
// A normal public method โ other components can call this.
public void TakeDamage(int amount)
{
currentHealth -= amount;
if (currentHealth <= 0)
{
Debug.Log($"{gameObject.name} died");
Destroy(gameObject); // remove the whole GameObject from the scene
}
}
}
Look at what your class got for free without declaring any of it: gameObject (the object this component is attached to), Debug.Log, and Destroy. Those all came down the inheritance chain from MonoBehaviour and its bases. Your job was only to add the game-specific parts: a health value and a way to take damage.
โ Pro Tip: keep components small and named for their job
A well-designed component does one thing and its name says what: Health, PlayerMovement, Rotator, ScoreDisplay. If you're tempted to name a script GameManagerThatAlsoHandlesPlayerAndUI, that's three components wearing a trench coat.
Why You Never new a Component
Here is the biggest surprise for a C# programmer. In plain C#, you create an object like this:
Health h = new Health(); // โ WRONG for a MonoBehaviour
In Unity that line is a mistake. A MonoBehaviour is meaningless without a GameObject to live on โ new Health() would create a bare C# object with no gameObject, no transform, and Unity would never call its Start or Update. (Unity even logs a warning if you try.) You also should not write a constructor for a MonoBehaviour; the engine instantiates it, and your setup code belongs in Awake/Start instead.
So how do components get created? Two ways:
- In the Editor: you drag the script onto a GameObject, or click Add Component. Unity creates the instance for you.
- In code: you ask an existing GameObject to add one with
AddComponent.
// Create a GameObject, then add components to it โ the Unity way.
GameObject enemy = new GameObject("Enemy"); // a GameObject CAN be new'd
Health health = enemy.AddComponent<Health>(); // let Unity build the component
health.maxHealth = 50; // now it's safe to configure
๐ก Rule of thumb: You maynewaGameObjectand you maynewa plain C# class. You may nevernewaMonoBehaviourโ ask a GameObject toAddComponentit, or attach it in the Editor.
โ ๏ธ Watch Out
Because Unity โ not you โ constructs the object, a field initializer like private int currentHealth = maxHealth; can't depend on Inspector values being set yet. Do that kind of initialization inside Awake or Start, where the component is fully wired up. Lesson 1.2 covers exactly when each of those runs.
Composition Over Inheritance
In the OOP part of the intro course, "reuse" mostly meant inheritance: an Enemy extends Character extends Entity. That works for a while, but game objects vary along too many independent axes โ "flying?", "shoots?", "has health?", "can be picked up?" โ to fit one tidy tree. You quickly hit the classic problem: where does a flying, shooting, healable object go, versus a walking, shooting, healable one?
Unity's answer is composition: instead of one deep class that is everything, you attach several small components that each add one capability. Need it to shoot? Add a Shooter. Need health? Add a Health. Mix and match per object.
To make the enemy fly, you swap its Movement component for a FlyingMovement and change nothing else โ Health and Shooter don't care. To make a friendly turret, reuse Health and Shooter but drop Movement. This is why Unity ships Rigidbody, Collider, and AudioSource as separate components rather than one giant "PhysicalObject" base class.
โ The design guideline
Prefer "has-a" (composition โ attach a component) over "is-a" (inheritance โ extend a class). Inheritance still has its place (Health genuinely is-a MonoBehaviour), but for gameplay capabilities, reach for another component first.
๐ก Components talk to each other, they don't inherit from each other. When yourShooterneeds to reduce the target's health, it finds the target'sHealthcomponent and callsTakeDamageโ it does not try to be a Health. How one component finds another is Lesson 1.3.
Exercise & Quiz
๐๏ธ Exercise: Build a Pickup from Small Components
Objective: Assemble one GameObject's behavior out of two independent single-purpose components โ no inheritance between them โ to feel the component model directly.
Instructions:
- In a Unity project, create a Sphere (GameObject โ 3D Object โ Sphere) and name it
Coin. - Create a script
Rotator.csthat spins the object continuously, and a scriptSelfDestruct.csthat removes the object after a set number of seconds. - Attach both scripts to the
Coinvia Add Component. Each should expose a tunable value in the Inspector. - Press Play: the coin should spin, then disappear on its own. Notice that neither script knows the other exists.
- Reasoning question to answer in a comment: which of these two scripts could you drop onto a completely different GameObject unchanged? (Answer: both โ that's the point.)
Starter Code:
using UnityEngine;
public class Rotator : MonoBehaviour
{
public float degreesPerSecond = 90f;
void Update()
{
// TODO: rotate this object around its Y axis every frame.
// Hint: transform.Rotate(...) and Time.deltaTime (covered fully in Module 2).
}
}
using UnityEngine;
public class SelfDestruct : MonoBehaviour
{
public float lifetimeSeconds = 3f;
void Start()
{
// TODO: schedule this GameObject to be destroyed after 'lifetimeSeconds'.
}
}
๐ก Hint
transform.Rotate(0f, degreesPerSecond * Time.deltaTime, 0f) spins the object smoothly, frame-rate independent. To remove the object later, Unity gives you an overload of Destroy that takes a delay: Destroy(gameObject, lifetimeSeconds). Remember it's gameObject (the whole object) you want gone, not just the script.
โ Solution
using UnityEngine;
public class Rotator : MonoBehaviour
{
public float degreesPerSecond = 90f;
void Update()
{
// Frame-rate independent spin around the Y axis.
transform.Rotate(0f, degreesPerSecond * Time.deltaTime, 0f);
}
}
using UnityEngine;
public class SelfDestruct : MonoBehaviour
{
public float lifetimeSeconds = 3f;
void Start()
{
// Ask Unity to destroy the whole GameObject after the delay.
Destroy(gameObject, lifetimeSeconds);
}
}
Both components are attached to the same Coin, yet each is completely self-contained and reusable. Put Rotator on a pickup, a compass needle, or a fan โ it doesn't care. That independence is the component model working for you.
๐ฏ Quick Quiz
Question 1: What is the relationship between a GameObject and a Component?
Question 2: Why is new Health() the wrong way to create a MonoBehaviour?
Question 3: You need an object that can fly, shoot, and take damage. What does the "composition over inheritance" guideline recommend?
Summary
๐ Key Takeaways
- A GameObject is a container; Components give it data and behavior; a MonoBehaviour is the base class that lets your C# class be a component.
- Inheriting
MonoBehaviourhands your scriptgameObject,transform,GetComponent, theenabledswitch, and โ crucially โ engine event functions likeAwake/Start/Update. - You never
newa MonoBehaviour and you don't give it a constructor. Attach it in the Editor or callgameObject.AddComponent<T>(); do setup inAwake/Start. - The class name must match the file name, and a script only runs once it's an instance attached to a GameObject in a loaded scene.
- Favor composition โ assemble behavior from small, single-purpose components โ over deep inheritance trees.
๐ Additional Resources
- Unity Manual โ MonoBehaviour
- Scripting Reference โ MonoBehaviour
- Unity Manual โ GameObjects and the component model
๐ What's Next?
You now know what a MonoBehaviour is and how it attaches to a GameObject. Next we'll look at when Unity calls into it โ the event function lifecycle: Awake, OnEnable, Start, Update, FixedUpdate, and OnDestroy, and the exact order they fire.
๐ Component model unlocked!
You've made the leap from "one class runs everything" to "small components, composed." That idea underpins the entire rest of the course.