Target Practice
Download View on GitHub
Unity • Physics-Based Archery

Project Overview

Target Practice is a 2D physics-driven archery game where players control both the angle and power of their shots using a click-and-drag input system. A real-time trajectory preview helps players line up their shots before firing arrows at moving targets.

The project focuses on implementing projectile physics, responsive player input, and clear gameplay feedback through trajectory visualization, scoring systems, and dynamic target behaviour.

My Role

I developed all gameplay systems for this project in Unity using C#. The primary focus was building a responsive projectile system and supporting gameplay systems around it.

Key Technical Highlights

Gameplay Highlights

Archery Aiming System

Physics-Driven Archery Aiming

The aiming system uses mouse drag input to control both the angle and power of each shot while displaying a real-time trajectory preview. Vertical drag adjusts launch angle, horizontal drag modifies shot power, and the predicted arrow path is visualized using a LineRenderer. This gives players precise control over their shots while clearly communicating how the underlying projectile physics behaves.

Why it’s done this way
  • Drag input mimics pulling back a bowstring, making the control scheme intuitive.
  • Separating power and angle into two axes gives players precise shot control.
  • Real-time trajectory visualization helps players understand the projectile physics.
  • Immediate visual feedback improves readability and shot planning.
How it works
  • Mouse Down: stores the initial mouse position and enters aiming mode.
  • Mouse Drag: calculates drag delta to adjust launch angle and shot power.
  • Velocity Calculation: converts angle and power into a velocity vector.
  • Trajectory Prediction: projectile motion is simulated to generate trajectory points.
  • Visualization: points are rendered using a LineRenderer to preview the shot arc.
Code Snippets
  • Update() in PlayerController.cs – drag input and shot parameter calculation.
  • GetArrowVelocity() – converts angle and power into velocity.
  • DrawTrajectory() – predicts projectile path and renders the preview arc.
Aim Input Code Trajectory Code

Centralized Game State & Event System

A singleton GameManager controls the core state of the game including score tracking, arrow count, target spawning, and game over logic. Gameplay systems communicate through UnityEvents to keep systems loosely coupled and avoid direct references between UI and gameplay logic.

Why it’s done this way
  • Centralizes game state in a single authority.
  • UnityEvents allow UI systems to react to gameplay changes without tight coupling.
  • Systems remain modular and easier to maintain.
How it works
  • GameManager stores score, arrows remaining, and targets destroyed.
  • Property setters trigger UnityEvents when values change.
  • HUD elements subscribe to these events to update the UI.
  • Targets notify the GameManager when destroyed.
Code Snippets
  • Score property invoking OnScoreGained
  • ArrowsRemaining property invoking OnArrowsChanged
  • SpawnTarget() for randomized spawning
Game Manager Code Game Manager Code Game Manager Code
Arrow Physics

Physics-Based Arrow Simulation

Arrow movement is simulated manually rather than relying on Unity’s Rigidbody physics. This allows precise control over velocity updates, gravity application, and arrow rotation during flight.

Why it’s done this way
  • Ensures trajectory preview perfectly matches arrow motion.
  • Provides consistent behaviour regardless of physics settings.
  • Allows custom rotation to align arrow with velocity.
How it works
  • Arrow stores velocity when launched.
  • Gravity is applied each physics update.
  • Position updates using velocity * deltaTime.
  • Arrow rotates along the velocity vector.
Code Snippets
  • Launch() in Arrow.cs
  • FixedUpdate() updates movement and rotation.
Arrow Physics Code
Target Movement

Dynamic Target Behaviour

Targets spawn with randomized movement patterns including stationary, horizontal, and vertical motion, creating varied difficulty and encouraging players to adapt their aim.

Why it’s done this way
  • Movement variety increases challenge.
  • Different scoring rewards riskier targets.
  • Randomized patterns prevent repetitive gameplay.
How it works
  • Targets randomly choose a movement type when spawned.
  • Sine-wave motion controls horizontal or vertical movement.
  • Destroying targets awards score and spawns replacements.
Code Snippets
  • MovementType enum in Target.cs
  • Update() handles movement patterns.
  • OnTriggerEnter2D() awards score.
Target Movement Code
Back to Projects

Contact