HamJam - Endless Runner challenges players to run as far as possible down a procedurally generated track. The core loop revolves around lane-switching, jumping, and sliding to dodge static and flying obstacles, collecting coins to purchase custom skins/map themes, and managing sprint meters. A chasing bear stays close behind, accelerating to catch the player if they crash, exhaust their energy, or make mistakes.

The project was commissioned to create a highly addictive mobile endless runner utilizing cloud-based user data retention and custom rendering profiles for low-end devices.


As the player runs further, their speed dynamically scales up (up to 50f). In early builds, the chasing bear's catch speed was hardcoded at 15f. This caused a game-breaking bug where the bear could never catch up to catch the player during a game-over or exhaustion sequence.
Implementing clean mobile haptics without adding heavy external asset-store packages. Furthermore, Unity builds often excluded the VIBRATE permission in the compiled Android manifest because haptics were called through native Java reflections (AndroidJavaObject) instead of standard APIs.
When players equipped a custom skin, Unity cloned the material instance on the renderer. The player movement script cached the material reference too early on scene initialization, meaning that speed boost transparency and emission visual effects were applied to a hidden, stale material instance.
Dynamic Catch Math: Rewrote the chasing bear's final catch logic (FinishMove) to dynamically calculate speed as PlayerSpeed + CatchBaseSpeed rather than using a static float. This ensures the bear successfully catches and defeats the player at any running speed.
Zero-Plugin Haptic Wrapper & Permission Hook: Developed a lightweight, pure C# VibrationManager wrapping Android's VibrationEffect and iOS's AudioServicesPlaySystemSound. Added a compiler-friendly reference to Handheld.Vibrate() to force Unity's post-processor to auto-inject the VIBRATE permission into the Android Manifest without manual XML edits.
Dynamic Material Resolver Hook: Replaced static material caching with a dynamic GetCurrentPlayerMaterial() getter in PlayerMovement.cs that queries the renderer's active material clone at the exact moment a power-up triggers. This corrected the reference mismatch so visual effects apply to the newly equipped skin.
Lightweight Stylized Rigging: Modeled and animated a vibrant 3D cartoon world using custom vertex-lit shader passes for maximum rendering speed across old smartphones.


Structured milestone sprints from core game loop validation to production-ready multi-platform release.
Developed the procedural infinite platform spawner, lane-switching controls, and basic jump/slide character physics.
Integrated PlayFab display name registration, secure cloud leaderboard statistics, and the coin-based unlock economies.
Added dynamic haptics, UI animations (pulse, bounce, wobble), delayed panel transitions, and resolved material instantiation bugs.
+50% Stability
100% Leak Resolved
100% Reliable Sync