On this page

The Last of UST

A 4-player co-op party game where tethered players clear a gauntlet of themed stages — parkour, a gravity-flip runner, bomb defusal, and a boss fight — over Steam. My HKUST final year project.

  • Unity
  • C#
  • FishNet
  • Multiplayer
  • Plastic SCM

fyp

Check out the video!

Overview

A 3D online co-op game built in Unity, and the team final year project for my degree at HKUST (the name is a pun on The Last of Us). Up to four players join through a Steam lobby and play through a sequence of themed stages — a parkour platformer, a Geometry-Dash-style gravity-change runner, a Keep Talking and Nobody Explodes-style bomb defusal, a WipeOut quiz/elimination round, and a final boss fight. Players are physically chained to one another — the core mechanic is inspired by Chained Together — so every stage is a problem in moving as one rather than alone.

It was built by a team. My work centered on the multiplayer layer, the chain that binds the players, part of the platformer, and stitching everyone’s independently-built stages into one game.

Architecture

The whole game runs as a server-authoritative session on FishNet, with FishySteamworks as the transport so traffic rides Steam’s networking rather than raw sockets. A SteamWorkManager wraps Steam matchmaking — create / join / invite / leave a lobby, propagate the host address, and hand the connection off to FishNet — so joining a friend’s game is a single Steam invite.

A networked GameManager singleton is the spine. It’s a finite state machine (PlayingPlatform → PlayingGravityChange → PlayingBomb → PlayingBoss → End) that owns the connected-player list, the rope tether between players, and the per-stage setup (cameras, lighting, enabling weapons for the boss fight, firing the end cutscene). A persistent BootstrapSceneManager drives networked scene loadingLoadGlobalScenes / UnloadGlobalScenes — so every client transitions between stages in lockstep. Each hazard (moving, rotating, pushing, destructible and timed platforms, laser traps, randomly-spawned obstacles) gates its simulation behind IsServerStarted and replicates to clients, keeping the world consistent across the session.

My contributions

  • Multiplayer implementation. Built the game’s netcode on FishNet — networked player spawning and movement, and the server-authoritative obstacle and stage logic using FishNet’s ServerRpc / ObserversRpc patterns — running on top of the team’s Steam transport layer.
  • The chain. Implemented the chain that physically links the players — a Verlet-integration rope simulation with distance constraints, collision handling and GPU-instanced link rendering, plus a server-side pull force that drags a player along when the chain snaps taut. It’s the mechanic the whole game is built around.
  • Part of the platformer. Contributed to the parkour stage — player movement and the obstacle/platform hazards that make up the gauntlet.
  • Integration & workflow. Wired the separately-built stages into one coherent networked game loop through the GameManager state machine and the bootstrap scene flow, and set up the team’s source-control and build workflow on Plastic SCM (Unity DevOps), including ParrelSync for testing multiplayer locally.

Stack

Unity (URP) and C#; FishNet for netcode with FishySteamworks + Steamworks.NET / Heathen Steamworks for the Steam layer; Cinemachine, Visual Effect Graph and post-processing for presentation; ParrelSync for local multiplayer testing; and Plastic SCM / Unity DevOps for version control.