Click-to-Shoot & Destroy
- Create a Player that shoots projectiles.
- Have Targets that spawn automatically.
- When a projectile hits a target, the target is destroyed.
- Demonstrate OOP design: base class for game objects, inheritance for projectiles and targets.
Step-by-Step Unity Setup
1. Create a New Unity 3D Project
- Open Unity Hub → New Project → 3D (URP optional) → Name it
OOP_Shooter. - Once loaded, delete the default “SampleScene” objects if needed, keep the Main Camera and Directional Light.
2. Create a Basic Scene
- Create an Empty GameObject called
GameManager. - Create a Cube called
Player→ position at(0, 0, 0). - Create a Sphere prefab for projectiles → name it
Projectile. - Create another Cube prefab for targets → name it
Target.
Make sure you turn Target and Projectile into prefabs by dragging them into a Prefabs folder in the Project window.
Assets/
├── Scripts/
│ ├── BaseObject.cs
│ ├── PlayerController.cs
│ ├── Projectile.cs
│ ├── Target.cs
│ └── TargetSpawner.cs
├── Prefabs/
│ ├── Player.prefab
│ ├── Projectile.prefab
│ └── Target.prefab
└── Scenes/
└── MainScene.unity
Step 3: Scripts Overview (C#)
We’ll make 4 scripts:
| Script | Purpose |
|---|---|
BaseObject.cs | Base class for shared logic |
Projectile.cs | Inherits from BaseObject |
Target.cs | Inherits from BaseObject |
PlayerController.cs | Handles shooting and player input |
BaseObject.cs
Demonstrates Encapsulation and Inheritance.
using UnityEngine;
public class BaseObject : MonoBehaviour
{
[SerializeField] protected float health = 1f; // Encapsulation
public virtual void TakeDamage(float damage)
{
health -= damage;
if (health <= 0)
{
Destroy(gameObject);
}
}
}
Projectile.cs
Inherits from BaseObject, uses Polymorphism with OnCollisionEnter.
using UnityEngine;
public class Projectile : BaseObject
{
[SerializeField] private float speed = 10f;
[SerializeField] private float damage = 1f;
void Update()
{
transform.Translate(Vector3.forward * speed * Time.deltaTime);
}
private void OnCollisionEnter(Collision collision)
{
BaseObject target = collision.gameObject.GetComponent<BaseObject>();
if (target != null && target != this)
{
target.TakeDamage(damage);
}
Destroy(gameObject);
}
}
Target.cs
Inherits from BaseObject.
You could extend it to move or respawn.
using UnityEngine;
public class Target : BaseObject
{
void Start()
{
// Give each target a random color to make it more fun
GetComponent<Renderer>().material.color = new Color(Random.value, Random.value, Random.value);
}
}
PlayerController.cs
Shoots projectiles on click.
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField] private GameObject projectilePrefab;
[SerializeField] private Transform shootPoint;
[SerializeField] private float shootForce = 500f;
void Update()
{
if (Input.GetMouseButtonDown(0)) // Left click
{
Shoot();
}
}
private void Shoot()
{
GameObject projectile = Instantiate(projectilePrefab, shootPoint.position, shootPoint.rotation);
Rigidbody rb = projectile.GetComponent<Rigidbody>();
rb.AddForce(shootPoint.forward * shootForce);
}
}
Step 4: Hook It Up in the Editor
- Add Rigidbodies & Colliders:
- Add a Rigidbody to
ProjectileandTarget. - Ensure both have colliders (
SphereCollider,BoxCollider). - Check
Is Trigger = false.
- Add a Rigidbody to
- Player Setup:
- Add the
PlayerControllerscript to thePlayerobject. - Create an Empty Child under Player → name it
ShootPoint→ move it to the front of the player cube (e.g.,(0, 0, 1)). - Drag the
Projectileprefab into theProjectile Prefabfield in the inspector.
- Add the
- Target Setup:
- Create a few
Targetprefabs in random positions around(x: ±5, y: 0, z: 10).
- Create a few
Optional Step: Add Target Spawner
To demonstrate composition and encapsulation, add this:
using UnityEngine;
public class TargetSpawner : MonoBehaviour
{
[SerializeField] private GameObject targetPrefab;
[SerializeField] private int targetCount = 5;
[SerializeField] private Vector3 spawnArea = new Vector3(10, 0, 10);
void Start()
{
for (int i = 0; i < targetCount; i++)
{
Vector3 pos = new Vector3(
Random.Range(-spawnArea.x, spawnArea.x),
spawnArea.y,
Random.Range(5, spawnArea.z + 5)
);
Instantiate(targetPrefab, pos, Quaternion.identity);
}
}
}
Attach TargetSpawner to the GameManager object, assign the Target prefab.
Key OOP Concepts Demonstrated
| Concept | Where |
|---|---|
| Encapsulation | BaseObject.health with protected access |
| Inheritance | Projectile and Target inherit from BaseObject |
| Polymorphism | TakeDamage() can behave differently in child classes |
| Composition | PlayerController uses composition (contains shoot logic, uses projectile prefab) |
Run It!
Press Play → Left-click → your player shoots projectiles that destroy cubes when hit.
This project can easily be extended with:
- Sound effects
- UI score
- Enemy movement
- Reload timers
3. Build the Scene
- Create a new scene called MainScene and save it in
Assets/Scenes/. - Add:
- Directional Light
- Main Camera
- GameManager (Empty Object) → attach
TargetSpawner. - Player (Cube) → attach
PlayerController.- Create a child object
ShootPoint→ position(0, 0, 1).
- Create a child object
- Create Prefabs:
Projectile: Sphere withRigidbody,Collider, andProjectilescript.Target: Cube withRigidbody,Collider, andTargetscript.- Drag both into
Assets/Prefabs/as prefabs.
- Link in the inspector:
- On PlayerController: assign
Projectile Prefabto yourProjectile. - On TargetSpawner: assign
Target Prefabto yourTarget.
- On PlayerController: assign
4. Test It
Click Play → left-click → see projectiles fire and destroy colored cubes 🎯
You can easily extend this with:
- UI score counter
- Target respawn delay
- Player rotation with mouse
5. Export as a Unity Package
Once it works:
- In Unity, open Assets > Export Package…
- Check these folders:
ScriptsPrefabsScenes
- Click Export, name it:
OOP_Shooter_QuickStart.unitypackage - Done — you can now share or import it into any Unity project!
