Roles: Programming Director, Gameplay Programmer, Assistant Producer
Team Size: 15
Engine/Language: Unity , C#
In the city of Neopolis, caught in a power struggle between Cylife, a corporate techgiant, and the rebellious eco-activists of Green Force, you play as Vel, a hoverboard-riding courier working for a company that profits from the chaos: Punk Deliveries.
Grind rails, wall ride past drones, dodge obstacles, and blaze through cityscapes while deciding where your loyalties lie. Will you side with progress or preservation?
Punk Deliveries is a semester-long game development project created collaboratively with a team, under the mentorship of Rockstar Games, an invaluable experience that provided industry insights and professional guidance. As the Programming Director, I spearheaded the development of the game's core mechanic: a physics-based hoverboard system. This involved implementing real-time movement physics, collision detection, and responsive controls using C# within the Unity engine, ensuring a smooth and engaging player experience.
Beyond gameplay mechanics, I managed our version control processes using GitHub, overseeing all pull requests, resolving merge conflicts, and maintaining a clean and organized repository structure. I also mentored team members unfamiliar with Git, providing guidance to ensure smooth collaboration.
Throughout the semester, I adapted to a variety of technical and project-related challenges, taking on additional responsibilities as the project evolved. This role not only refined my skills in game programming and software architecture, but also strengthened my leadership in team coordination, project planning, and agile development.
Additionally, I was named by Rockstar as one of the three MVPs of this project.
Over the course of five development sprints, I was primarily responsible for developing and refining the hoverboard locomotion system. I iterated continuously on the mechanic, incorporating feedback from our mentors at Rockstar Games to ensure the movement felt fluid, intuitive, and responsive. My focus was on creating a system that not only looked and felt natural but also offered consistent and predictable control for players.
During each sprint, the feel of the board was the main consideration.
Key Iterations:
Prototype Movement: Created a basic hoverboard movement system to establish foundational controls and physics.
Prototype Rail Grind: Implemented an early version of rail grinding, allowing the hoverboard to attach and slide along rails.
Prototype Wall Grind: Developed an initial concept for wall grinding mechanics to explore more complex hoverboard trick traversal.
Key Iterations:
Added Collision Avoidance on All Walls: Implemented wall detection and avoidance logic to large slow downs while traversing and improve overall gameplay feel.
Switched Controls Away from Tank Movement: Reworked the control scheme to move away from tank-style movement, enabling more fluid and modern-feeling navigation.
Key Iterations:
Incorporated Models: Replaced placeholder assets with final hoverboard.
Added Tilt When Turning: Introduced a tilt mechanic during turns to improve visual feedback and make movement feel more dynamic and responsive.
Smoothed Transition Between Wall Grind and Jump: Refined the transition logic for a more seamless and natural movement flow between wall grinding and jumping.
Bidirectional Rails: Updated the rail grinding system to support movement in both directions, increasing design flexibility and player freedom.
Key Iterations:
Integrated Final Models for Rails, Walls, and Player: Replaced all prototype models with final assets to enhance visual consistency and presentation.
Added VFX: Introduced visual effects to provide impactful feedback during grinding and movement.
Snappier Movement for Better Player Control: Tuned responsiveness of movement inputs to give players more precise and satisfying control.
Player Looks in Direction of Rail Grind: Adjusted player orientation during grinds for improved visual clarity and immersion.
Taking in the final peices of feedback all of sprint 5 was dedicated to improving the feel and addressing edge cases.
Physics-based movement was used to implement the base locomotion and jump mechanics of the hoverboard. A Rigidbody was attached to the board, and force was applied based on player input until a defined maximum speed was reached. The hoverboard used a simplified BoxCollider to handle collisions efficiently. Gravity was disabled to simulate hovering behavior.
When the board’s velocity is near zero, it introduces subtle wobble along the X and Z axes to convey a sense of floatiness. This wobble is suppressed during movement to maintain controlled navigation.
To handle terrain traversal smoothly, the board performs ground detection and uses the surface's normal vector to apply movement forces parallel to the slope, ensuring consistent acceleration regardless of incline.
During turns, tilt is applied to simulate a skateboard-like feel, enhancing responsiveness and player feedback.
Animation syncing was carefully tuned to match physics behavior, one example being the dynamic rotation of the character’s ankles to align with the orientation of the board.
The Wall Grind system is a modular setup composed of a WallGrindComponent attached to the hoverboard and wall grind wall prefabs containing a WallGrindScript and configured BoxColliders to define the grindable surface.
When the hoverboard enters a trigger collider on a wall grind surface, the player loses manual control, and the hoverboard is snapped and tilted to align with the wall. This allows for a smooth and consistent transition onto the wall, ensuring intuitive engagement without requiring precise input.
Once attached, the player rides along the wall until they either jump off or reach the end of the collider. The system was designed with 360-degree Y-axis rotation support, allowing designers to place wall grind surfaces in any orientation.
Extensive vector math was used to determine the player's relationship to the wall. The system calculates the wall's normal vector and compares it with the player's forward vector to determine whether the player is facing left or right relative to the surface. This information is then used to decide whether the player should grind along the wall “forwards” or “backwards”, ensuring the correct animation and movement behavior.
Several additional movement mechanics were implemented to expand the hoverboard’s moveset and enhance player control. These features included crouching, crouch jumping, sprinting, and boosting. Each mechanic was integrated based on design feedback and player experience goals, ensuring they contributed meaningfully to the sense of fluidity, mobility, and mastery over the hoverboard.
The Rail Grind system is a modular spline-based framework composed of three primary components: splines representing grindable rails, a RailManager class, and a RailGrindComponent attached to the hoverboard actor.
The RailManager maintains a dynamic list of all registered spline rails in the scene and performs per-frame proximity checks to determine the closest rail relative to the RailGrindComponent. This approach optimizes performance by ensuring that only the nearest rail is used for snapping and traversal logic.
When the hoverboard enters a defined activation range and the player triggers a jump input, the RailGrindComponent temporarily overrides standard physics and movement logic. It initiates a controlled transition by linearly interpolating the hoverboard’s position and orientation toward the closest spline, effectively snapping the player onto the rail. While this behavior is not physically accurate, it prioritizes gameplay fluidity and responsiveness, allowing for intuitive rail engagement without requiring precise player alignment.
Once attached, the system moves the player along the spline using parametric interpolation, typically by mapping a normalized time-based value across the spline's length. This ensures consistent grinding speed across rails of varying lengths. The grind continues until the player jumps off or reaches the end of the spline, at which point control is restored to the default movement system.
By decoupling rail content from core traversal logic, this modular design enables rapid iteration and scalability for level designers, allowing them to add or remove rails without requiring code changes.
Mid-project feedback emphasized that the player should feel a strong sense of mastery over the hoverboard. To achieve this, it was recommended that the hoverboard bounce off walls in a way that both enhanced responsiveness and minimized the feeling of hitting hard barriers.
To address this, a Collision Avoidance system was implemented. This consisted of a CollisionAvoidanceScript attached to three trigger colliders positioned on the front, left, and right sides of the hoverboard. Each trigger was assigned a specific enum type (e.g., Front, Left, Right) to indicate its directional context.
All avoidance-related parameters were configured through the main hoverboard script, ensuring designer-friendly workflows by consolidating adjustable values into a single location.
When the player entered one of the avoidance triggers, control was momentarily overridden, and the hoverboard executed a scripted avoidance maneuver based on the trigger’s type. These maneuvers applied directional forces or rotations to simulate bouncing away from obstacles, helping to maintain momentum and preserve flow.
This system significantly enhanced player feel, creating the illusion that players were seamlessly weaving through the environment like expert hoverboard riders, even when they made small mistakes.
A significant challenge faced by our team during this project was performance optimization. Initially, the game was running at a mere 4 FPS, with approximately 30,000 batches and 60 million vertices being rendered simultaneously.
Through focused optimization efforts, I was able to make substantial improvements within the constraints of the available time frame. After optimizing the game, the performance was enhanced to achieve 20-40 FPS, depending on the hardware, while reducing the number of vertices rendered to a range of 1 million to 10 million. Additionally, the batch count was lowered to approximately 7,000.
These optimizations significantly improved the game’s frame rate and rendering efficiency, making it more playable on a wider range of hardware.
In order to understand where our performance issues were coming from, I employed several analytic techniques and dedicated a couple of hours to research on optimization to ensure I was making the best decisions for our game. Some of the analytic techniques I used included Unity’s Stats Window, Profiler, Frame Debugger, and Rendering Debugger. Each of these tools was used to analyze specific aspects of performance:
Unity Stats Window provided a high-level overview of frame rate (FPS), memory usage, and rendering statistics, helping to identify general performance bottlenecks, such as frame time spikes.
The Profiler played a key role in analyzing art assets and lighting performance, specifically identifying issues with light calculations.
The Frame Debugger allowed me to step through the rendering pipeline, identifying unnecessary draw calls, overdraw, and objects that could be culled or simplified.
The Rendering Debugger helped diagnose rendering issues with lighting, identifying performance bottlenecks related to how many lights existence in one area.
By combining these tools, I was able to break down the performance issues systematically and make informed decisions on optimizing key areas of the game.
To reduce the batch count and improve performance, I created a static batch script that combined all child meshes under a parent object into a single mesh. By placing this script on models consisting of many parts or on groups of identical models, I was able to efficiently combine multiple objects into a single draw call, significantly reducing the number of batches required for rendering.
This approach helped optimize the game’s rendering pipeline by minimizing unnecessary draw calls, which is especially beneficial for complex objects or groups of objects that share similar materials.
Level of Detail (LOD) components were applied to nearly every model in the game to improve rendering performance. This was accomplished using Unity’s built-in LODGroup component. Based on research and analysis of our game’s performance metrics, I provided guidance to the art team on which assets would benefit most from low-polygon variants. For lower-priority models, I still configured LOD groups to enable early culling, optimizing scene performance even when simplified meshes weren’t available.
One challenge encountered was that Unity's LODGroup does not support lights directly. However, certain real-time lights were identified as performance bottlenecks when viewed from long distances. To address this, I created a custom LODLight script, which disables the light component once the player exceeds a specified distance threshold. This solution preserved visual fidelity up close while significantly reducing the impact of dynamic lighting on performance at scale.
As Programming Director, one of my primary responsibilities was overseeing our team's GitHub repository and managing all incoming merge requests. I reviewed each request to ensure that the submitted work functioned as intended, adhered to project standards, and did not introduce new bugs or regressions. This process was critical to maintaining a build-ready and playtestable main branch at all times.
Throughout the semester, I personally reviewed and merged over 150 pull requests, either integrating them directly when the work met our criteria or providing clear feedback to developers when further changes were required. This role sharpened my attention to detail, strengthened my ability to read and evaluate others’ code quickly, and emphasized the importance of version control discipline and codebase stability in collaborative game development.
One of the most significant challenges I encountered during this project was achieving the right "feel" for the hoverboard mechanic. While the core functionality was implemented by the end of sprint two, fine-tuning the experience required extensive iteration. Despite completing the major features early, the mechanic didn’t feel intuitive or satisfying at first, a reminder that functionality and user experience are not the same.
This aspect of the project taught me several important development lessons. First, I learned the value of early and frequent testing, especially for mechanics that depend heavily on user responsiveness. Second, I recognized the power of modular design, by structuring systems in flexible components, I was able to make adjustments without disrupting the entire codebase. Third, I made almost every key parameter a designer-adjustable variable, which allowed for rapid tuning based on feedback without needing a full rebuild. Finally, I found that clear and consistent documentation made collaboration easier and sped up the iteration process.
With more time, I would have continued refining the hoverboard's behavior, especially by addressing edge cases and improving the fluidity and responsiveness of movement in less common scenarios. These nuanced details are often what separate a good mechanic from a great one, and while I made significant progress, perfecting that polish within the constraints of a semester was a challenge. Given more development time, I would focus on these subtle refinements to elevate the overall player experience.
Another major challenge I faced was addressing optimization too late in the development cycle. In past projects, performance was never a significant issue due to smaller scopes, so I hadn’t developed a habit of prioritizing it early. However, with this project’s larger scale, the consequences of overlooking optimization became clear — I found myself scrambling near the end to reduce draw calls, lower batch counts, and minimize vertex usage to maintain acceptable frame rates.
This experience emphasized the importance of integrating performance considerations from the very beginning. Looking back, I would have implemented LOD (Level of Detail) groups as assets were brought in, ensured that all models were properly configured for efficiency, and kept profiling tools in the loop throughout development. Going forward, I plan to make optimization a continuous process rather than a last-minute fix.