Defy gravity and dodge death in co-op space chaos.
Nebula Navigator is a co-op 2D platformer-shooter in which the players navigate deadspace corridors, dodging obstacles and blasting through hazards. Designed in Unity with C#, it blends precision movement, shooting mechanics, and power-ups for a fun yet challenging experience.
Nebula Navigator is my first game development assignment, created to solidify my understanding of core game mechanics - movement and shooting with basic structuring in Unity. This is a game of cooperation between players in a 2D space platformer wherein two players must fly, dodge, and shoot their way through tight corridors filled with obstacles.
While relatively simple, this game established my foundation in game development, teaching me how to structure mechanics, balance challenges, and optimize player experience on a basic level.
View key scripts used in Nebula Navigator.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.InputSystem;
public class PlayerMovement : MonoBehaviour
{
public float speed;
public Rigidbody2D rb;
private float horizontal;
private float vertical;
Vector2 lastVelocity;
public float speedUp;
private void Start()
{
rb = GetComponent();
}
void Update()
{
rb.AddForce(new Vector2(horizontal * speed, vertical * speed) * Time.deltaTime * speedUp);
}
private void FixedUpdate()
{
lastVelocity = rb.velocity;
}
public void Move(InputAction.CallbackContext callbackContext)
{
horizontal = callbackContext.ReadValue().x;
vertical = callbackContext.ReadValue().y;
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Player1") || collision.gameObject.CompareTag("Player2"))
{
var speed = lastVelocity.magnitude;
var direction = Vector2.Reflect(lastVelocity.normalized, collision.contacts[0].normal);
rb.velocity = direction * Mathf.Max(speed, 2f);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class Shooting : MonoBehaviour
{
public Transform shootingPoint;
public GameObject bulletPrefab;
public float bulletCD = 0.5f;
public bool shooting;
public float timeAfterShooting = 0;
private void Start()
{
shooting = false;
}
private void Update()
{
timeAfterShooting -= Time.deltaTime;
}
public void Shoot(InputAction.CallbackContext shoot)
{
if (shoot.performed && timeAfterShooting <= 0.0f)
{
timeAfterShooting = bulletCD;
Instantiate(bulletPrefab, shootingPoint.position, transform.rotation);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameRestarter : MonoBehaviour
{
public GameObject Player1;
public GameObject Player2;
public string Respawn;
private bool player1Dead = false;
private bool player2Dead = false;
void Update()
{
CheckPlayerStates();
}
void CheckPlayerStates()
{
if (Player1 == null || !Player1.activeSelf)
{
player1Dead = true;
}
if (Player2 == null || !Player2.activeSelf)
{
player2Dead = true;
}
if (player1Dead && player2Dead)
{
Debug.Log("Both players have died. Restarting scene.");
SceneManager.LoadScene(Respawn);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PauseGame : MonoBehaviour
{
public GameObject pauseMenuUI;
private static bool gameIsPaused = false;
private void Start()
{
pauseMenuUI.SetActive(false);
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
if (gameIsPaused) Resume();
else Pause();
}
}
public void Resume()
{
gameIsPaused = false;
Time.timeScale = 1f;
pauseMenuUI.SetActive(false);
}
void Pause()
{
gameIsPaused = true;
Time.timeScale = 0f;
pauseMenuUI.SetActive(true);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class FasterBoost : MonoBehaviour
{
public float boostedSpeed;
public float standardSpeed;
private PlayerMovement playerMovement;
public GameObject player;
private bool boosting;
public float boostTimer;
public float boostAmmount;
private void Awake()
{
playerMovement = player.GetComponent();
}
void Start()
{
boosting = false;
}
void Update()
{
if (boosting)
{
boostTimer += Time.deltaTime;
if (boostTimer > boostAmmount)
{
playerMovement.speed = standardSpeed;
boosting = false;
boostTimer = 0;
}
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag("Faster"))
{
playerMovement.speed = boostedSpeed;
boosting = true;
}
}
}
Learn more about this project, my other projects, and me also!