






Game Developer Generalist · 10+ years
Unreal, Unity and the web. Multiplayer, VR and performance, shipped end to end.
Toolkit
01 · Gameplay systems
GAS, AI & combat
Gameplay Ability System, creature and navmesh AI, combat and traversal, data-driven design.
Seen in Scales vs Steel ›
02 · Multiplayer
1,000+ users
Dedicated servers on AWS GameLift, Photon, Pixel Streaming, replication and interest management.
Seen in Virtuworx ›
03 · XR
Quest, Pico, Rift
VR on OpenXR with avatars, voice chat and comfortable in-world UI.
Seen in eyeora ›
04 · Performance
+30 fps
Profiling, DOTS with Jobs and Burst, PSO warm-up, and optimisation for low-end devices.
Seen in VR Vehicle Visualizer ›Career
VR and multiplayer projects in Unreal Engine and Unity, from Metaverse environments to game-based learning.
Built and optimised Virtuworx, an avatar-based virtual world, for 1,000+ concurrent users.
Shipped Unity mobile games to production, and was promoted within a year.
Open to gameplay and engine roles, and to freelance projects.
A science game for What Makes Us Human
Biology class, fought on the front lines of your immune system.
Designed and built solo in Unity · On the App Store and Google Play · Now playable on the web
Purpose
Lymph Attack is built for What Makes Us Human, a public benefit company making games across Life Sciences, Chemistry and Physics. The mission: make science fun, accessible, and unforgettable.
Every defender is a white blood cell. The macrophage even absorbs what fallen pathogens leave behind.
Bacteria and cold viruses attack in waves, each with its own speed, damage and behavior.
Plasma and cytoplasm become the resources you manage to keep the lymph node standing.
Under the hood
The systems I designed and coded in Unity and C#, kept loosely coupled and driven by data, so the game grows without rewrites.
Each unit's attack and targeting is a swappable strategy, so a new unit type is a new class, not new combat code.
public interface IAttackStrategy { void Attack(GridEntityBase attacker, GridEntityBase target, …); } // UnitManager picks one per unit case EntityName.Phil: return new RangedAttack(…); case EntityName.Bubbles: return new RangedExplosiveAttack(…);
Managers talk through C# events and every unit runs a small state machine, so systems never reach into each other.
public event Action<int> OnWaveStart; public event Action<GridEntityBase> OnWBCUnitSpawned; public event Action<GameState> OnGameStateChanged; enum EntityState { ReturnToBase, Idle, Search, Move, ReadyToAttack, Attack }
Async A* on a 26×44 grid. Pathogens route around defenders and re-path as the board changes.
Levels, waves and unit stats load from one JSON file into ScriptableObjects, so tuning never needs a rebuild.
// GameData.json { "UID": "Phil", "MaxHealth": 100, "DPS": 20, "AttackRange": 7 } JsonConvert.PopulateObject( json, chapters_SO, settings);
Chained Timeline sequences that wait until the player actually performs each step.
currentTimeline.Play(); yield return new WaitUntil( () => !IsWaitingForAction); // A unit was deployed → next step UnitManager.Instance.OnWBCUnitSpawned += OnWbcUnitSpawned;
A level-grid painter that saves walkable maps as JSON, and a one-click web build menu.
// Grid painter scene Right-click block cell Middle-click clear S save JSON L load // Editor menu Lymph Attack ▸ Web Build ▸ Build Release
Ported to Unity 6 web: fixed single-threaded pathfinding, cut the download 43% and kept the exact iPhone layout on any screen.
By the numbers
Lymph Attack is a game by What Makes Us Human, PBC. Designed and developed by Vishal Thakur.
Puzzle battle · squad RPG
Lead a squad of four heroes through monster-filled kingdoms, one match at a time.
Lead developer on a 4-person team · Playable in any browser · iOS and Android in the coming months
The game
Mega Match Heroes turns match-3 into a squad battle. Matching tiles on the battle board deals damage and charges your heroes' abilities, and the world grows one kingdom at a time, each with new enemies, mini-bosses and a kingdom boss.
Ten kingdoms are planned. The first, the Toxic Junkyard, sends Scrap Rats, Blade Beetles and Wrench Goblins at you before the Junkyard King.
An attacker, a controller, a healer and a utility hero fight together, and every match charges their abilities.
Enemies lock and disrupt tiles, and bosses smash the board, so every kingdom ends in a fight for control of the grid.
Under the hood
The systems I designed and coded in Phaser 3 and TypeScript, so new kingdoms, heroes and editions ship without breaking what's already there.
An edition flag is fixed at build time, so the browser edition carries no switch a player could flip to unlock the full game.
// src/game/Edition.ts export const DEMO = import.meta.env.VITE_EDITION … // src/game/Upgrades.ts if (DEMO && level > DEMO_LEVELS) return false;
Every scripted tutorial board is replayed during the build. It fails if a lesson's swap doesn't make exactly the intended match.
// scripts/verify-tutorial.mjs if (b.findMatches().length) return fail(…); const groups = t.findMatches(); if (groups.length !== 1) return fail(…); play(b, step.swap, i);
Opponent skill blends along a trophy curve, tuned by a script that plays thousands of battles against a model player.
Phaser only resumes audio when the window regains focus; this wakes the browser's sleeping audio on every return path.
export function keepAudioAlive(game: Phaser.Game) { const wake = () => { if (!ctx || sm.locked || ctx.state === 'running'… ctx.resume().catch(() => { … }); document.addEventListener('visibilitychange', …
Adds a cropped "face" frame to a hero card's texture at runtime, so one portrait also serves as an avatar.
// src/game/Opponent.ts if (!tex.has('face')) { … tex.add('face', 0, AVATAR_FACE.x, AVATAR_FACE.y, s, s); } return 'face';
A scene that starts with the game and is listed last, so it draws above every screen without each screen opting in.
// src/scenes/CreditScene.ts super({ key: 'CreditScene', active: true });
The browser edition's build deletes enemy art it never shows and drops source maps. The build-number script refetches git history on Cloudflare's shallow CI clones.
By the numbers
Mega Match Heroes is a game by MazGameDev. Art by the client's artists, audio from free-to-use sources; code and game systems by Vishal Thakur.
Competitive VR PvP · Meta Quest 3
A VR arena battle for Meta Quest 3. Command a deck of creatures and fight with your own hands.
Lead gameplay engineer on a 5-person team · Unreal Engine 5 · OpenXR · Meta Quest 3 · Captured from the headset mirror view
The game
Two players face each other across a mountain chasm, each guarding a Core. Every player is a commander and a fighter at once, in real time, in VR. It's built for Meta Quest 3 and tuned for OutReal, a cloud service that streams PC-quality VR straight to the headset.
Spend regenerating energy to deploy creatures from an 8-card deck. They cross the arena and attack the enemy Core on their own.
Pick up weapons with your own hands, from rifles and grenades to energy blades and a blackhole gun, and stop what your opponent sends.
No cover and no terrain to exploit. The only edge is what you deployed, and when.
Under the hood
Gameplay Ability System, server-authoritative netcode, dedicated servers, AI and VR performance: the systems I designed and coded in Unreal Engine 5 and C++.
Damage is a gameplay effect applied on the server through the ability system component. Its size comes in at call time via SetByCaller, so one effect serves every weapon in the game.
// SVS_SummonedCreatureBase.cpp if (!HasAuthority() || bIsDead) return; FGameplayEffectSpecHandle SpecHandle = AbilitySystemComponent->MakeOutgoingSpec( IncomingDamageEffectClass, 1.0f, ContextHandle); SpecHandle.Data->SetSetByCallerMagnitude( DamageTag, -FMath::Abs(DamageAmount)); AbilitySystemComponent->ApplyGameplayEffectSpecToSelf( *SpecHandle.Data.Get());
Creatures, weapons, buildings and spells are Data Assets. One gameplay ability reads the energy cost and spawn class from the asset, so designers add items without new code.
// SVS_ItemSpawnAbility.cpp const float DynamicCost = ItemDataAsset->ItemData.EnergyCost * -1.0f; CostSpecHandle.Data->SetSetByCallerMagnitude( FGameplayTag::RequestGameplayTag( "Data.Cost.Energy"), DynamicCost); … GetWorld()->SpawnActor<AActor>( ItemDataAsset->ItemData.SpawnClass, …);
Clients only ask. Every card play is a reliable Server RPC that checks and spends energy on the server, and a card the player can't afford is rejected with a Client RPC to that player alone.
// SVS_XRPlayerController.cpp void ASVS_XRPlayerController:: Server_PlayCreatureCard_Implementation( int32 SlotIndex) { if (!HasAuthority()) return; if (!TrySpendEnergy(PeekCDO->EnergyCost)) { Client_ShowEnergyWarning(PeekCDO->EnergyCost, CurrentEnergy); return; } …
Your hand of cards and your energy replicate only to you. Opponents can't read your next move from network traffic, and no bandwidth goes on state that nobody else needs.
// GetLifetimeReplicatedProps
DOREPLIFETIME(ASVS_XRPlayerController, TeamTag);
DOREPLIFETIME_CONDITION(ASVS_XRPlayerController,
CreatureHand, COND_OwnerOnly);
DOREPLIFETIME_CONDITION(ASVS_XRPlayerController,
WeaponHand, COND_OwnerOnly);
DOREPLIFETIME_CONDITION(ASVS_XRPlayerController,
CurrentEnergy, COND_OwnerOnly);A Win64 dedicated-server build, cooked, staged and deployed to an AWS GameLift fleet. Match state is set up once per world, because the player controller outlives each round but its timers don't.
// SVS_XRPlayerController.cpp if (!World || MatchInitWorld.Get() == World) return; MatchInitWorld = World; InitCardCycles(); GetWorldTimerManager().SetTimer(EnergyRegenTimer, this, &ASVS_XRPlayerController::RegenEnergy, EnergyRegenInterval, true);
Creatures spread around the enemy Core instead of queuing on one point, snap goals onto the navmesh with a fallback, and re-path on the next tick when blocked, so a hit never reads as a stumble.
// SVS_SummonedCreatureBase.cpp const FVector RingOffset = FVector(FMath::Cos(Angle), FMath::Sin(Angle), 0.f) * Radius; FVector GoalLocation = CoreLoc + RingOffset; if (NavSys->ProjectPointToNavigation(GoalLocation, ProjectedGoal, FVector(300.f, 300.f, 300.f))) GoalLocation = ProjectedGoal.Location; Req.SetAllowPartialPath(true);
A forward renderer with 4× MSAA and instanced stereo for clean, cheap stereo frames. PSO precaching, plus weapons pre-rendered during the countdown, moves shader compilation out of the fight, where a stall is felt in the headset.
; DefaultEngine.ini r.ForwardShading=True r.AntiAliasingMethod=3 ; MSAA r.MSAACount=4 vr.InstancedStereo=True r.PSOPrecaching=1 r.PSOPrecache.ProxyCreationWhenPSOReady=1
By the numbers
Scales vs Steel is a VR game for Meta Quest 3 on the OutReal cloud platform. Environment art and lighting by the project's artists, VFX and the VR framework from third-party packs; gameplay code and systems by Vishal Thakur.
Automotive VR · Oculus Rift
Step into a showroom and configure a vehicle in VR, with every option live from the cloud.
Built for threepointzero · Sole developer · Unreal Engine 4 · Oculus Rift at 90 fps
The experience
Built for threepointzero, the VR Vehicle Visualizer lets a customer walk around a vehicle in VR, from a luxury car to a motorcycle or a helicopter, and configure it in real time. The options come from the cloud, so the line-up can change without a new build.
Switch the vehicle's paint and materials between the options on offer, and see each one applied instantly.
Open the doors, turn the lights on and off, and move between the exterior and the interior.
Change the backdrop and the time of day, then save a configuration to the cloud and load it again later.
Under the hood
The systems I designed and built in Unreal Engine 4, so a high-detail vehicle stays smooth in the headset while every option changes live.
Paint and material options load from the cloud at runtime, so the client can change the line-up without shipping a new build.
A customer's configuration saves to the cloud and loads back seamlessly, without interrupting the experience in the headset.
Backdrops change, and the view moves between exterior and interior, without a hard cut or a dropped frame. In VR the scene is your whole view.
Time of day moves between day and night as one smooth transition rather than a swap, with the vehicle staying on screen throughout.
Doors opening and lights switching on and off play back smoothly at full VR frame-rate, on demand.
A high-detail vehicle in VR has to hold 90 fps on Oculus Rift. Profiling showed where each frame went, and the fixes gained 30 fps.
By the numbers
VR Vehicle Visualizer was built for threepointzero. Vehicle art and environments provided by the client; development by Vishal Thakur.
Avatar-based virtual worlds · Unity
A fully customisable 3D world for meetings, events and offices, built for real human connection.
Unity developer on a 30-person team · The Virtulab · 2017–2022 · 1,000+ concurrent users
The platform
Virtuworx is an avatar-based virtual environment used across many sectors. People design their own avatar and shape their own space, from a mapped copy of a real office to an imagined venue, and AI-driven analytics help them get the most from it. Real experiences and real human connection, while saving time, money and carbon.
Design an avatar, then choose how the world looks and feels, from a modelled office to a unique piece of virtual real estate.
Host conferences, exhibitions, speed networking and virtual offices, with camera and desktop streaming.
AI-driven analytics show how people use each space, so hosts can get more out of every event.
Under the hood
What I owned as a Unity developer: the multiplayer stack, the systems people touch every day, and the performance work that let 1,000+ users share a space.
The simulation moved to Unity's ECS, which lays data out linearly in memory, so the CPU processes thousands of players with cache-friendly operations.
Movement, collisions and state updates run on the C# Job System across CPU cores, compiled by Burst into highly optimised machine code.
Interest management sends each client only what's relevant to it, while delta compression, bit-packing and a lower tick rate keep bandwidth down as rooms fill.
A managed queue brings people into multiplayer sessions, so busy events fill smoothly as attendees arrive.
GPU instancing on a Scriptable Render Pipeline, aggressive LODs, and full physics switched off wherever it wasn't needed, so crowded scenes keep their frame-rate.
Profiling, caching and memory work, including leak investigation, lifted frame-rate by 25% and cut the crash rate by 40% on constrained devices.
In-world voice and text chat between avatars, so a virtual meeting feels like a real conversation.
A tutorial system that onboards first-time users, and mini-games for co-op mode that give groups something to do together.
By the numbers
Virtuworx is a platform by The Virtulab. Art and environments by the Virtulab team; I was a Unity developer on the platform.
Social XR · Meta Quest, Pico & mobile
Concerts, events and hangouts in shared 3D spaces, on a VR headset or a phone.
Unity developer on a 20+ person team · Photon + Agora · 100 players per space · Quest, Pico, iOS & Android
The platform
eyeora connects Creators and Explorers. Creators build 3D spaces in a browser-based XR studio and run free or pay-per-view events. Explorers join with a personalised avatar, in VR or in 3D Mode on a phone, and share the show with friends.
Multi-Zone spaces with 12 zones, media rooms, stage venues, stadiums, audio streaming and talent hunts.
Live hologram performances, synced 2D media, and 360 video with gaze-controlled hotspots.
Meta Quest, Pico, a phone in a mobile headset, or 3D Mode with no headset at all.
Under the hood
As a Unity developer I worked on every feature of the eyeora app and its XR Studio, and took a 100-player space from 20–25 fps to a steady 60.
Avatars, events and media stay in sync for up to 100 players in a space. Interest management, delta compression, bit-packing and a lower tick rate keep the traffic down.
Real-time voice between avatars through Agora, alongside text chat, so a hangout feels like being there together.
Every Explorer gets a personalised 3D avatar made from a single headshot, then moves with gaze navigation and teleport, no controllers needed.
Live hologram playback, 360 video with gaze hotspots, and 2D media kept in sync for everyone in the space.
The browser-based studio where creators build 3D spaces without code: drag-and-drop hotspots, multi-camera 360 sync, and real-time edits that publish straight to the app.
The crowd runs on Unity's ECS, with movement, collisions and state updates spread across CPU cores by the Job System and compiled by Burst.
GPU instancing on a Scriptable Render Pipeline, aggressive LODs, and full physics switched off wherever it wasn't needed: the budget a standalone headset demands.
Profiling on device showed where every frame went. With 100 players in one space, the app went from 20–25 fps to a steady 60.
By the numbers
eyeora is a platform by eyeora. Art and content by the eyeora team; I was a Unity developer on the app and XR Studio.
Mobile games · Unity · Google Play
Twelve casual games on Google Play, built in Unity to run smoothly on every phone.
Game developer · 12 titles · 1.6M+ downloads · Top titles past 500K
The games
Building sims, army and crowd battlers, puzzle and arcade shooters, each tuned for short sessions and low-end Android phones.
Under the hood
Across the catalogue I followed one production playbook: fast to load, smooth on budget Android phones, and easy to tune after launch.
Bullets, enemies, crowds and VFX come from pools instead of Instantiate and Destroy, so the busiest moments never trigger garbage-collection spikes.
URP with the SRP Batcher, GPU instancing for armies and crowds, static batching for scenery, and sprite atlases for UI.
No per-frame allocations: cached components, non-alloc physics queries, pooled collections and string-free UI updates, verified in the Profiler.
A trimmed layer collision matrix, simple colliders, a tuned fixed timestep, and kinematic or physics-free movement for large armies.
ASTC and ETC2 texture compression, mesh compression, Addressables for content on demand, and Android App Bundles to keep installs small.
Levels, weapons, upgrades and the economy live in ScriptableObjects, so balancing happens in data, without touching code.
Device-tier quality settings, adaptive resolution and frame-rate targets, and IL2CPP builds for ARM64 with code stripping, profiled on low-end hardware.
Ad mediation, in-app purchases and analytics events built in cleanly, so every game could be measured, tuned and monetised after launch.
By the numbers
Games published by Superace Play on Google Play. I worked on these titles as a game developer. Download counts as listed on Google Play.
Unreal Engine · Pixel Streaming · any browser
The virtual stage for live events: Unreal worlds that open in one click, in any browser, with no downloads.
Unreal developer · Built every feature · Unreal Engine streamed to the browser
The platform
Passage brings the energy of real-world events online. Guests join from a link, appear as avatars with their live webcam, and talk, explore and watch shows together in high-end Unreal worlds streamed straight to the browser.
Unreal-quality worlds streamed to the browser on any device. No apps, no downloads.
Webcam video avatars with voice and chat, so a virtual event feels like being in the room together.
Brand activations, conferences, premieres and performances, workshops and fan communities.
Flagship world
A fantasy adventure world built on Passage and played in the browser: unique characters, quests, farming and crafting, mounts and companions, and live community events in-world.
StrangeClan trailer · Unreal Engine, streamed in the browser
Under the hood
As an Unreal developer I built every feature of Passage and StrangeClan, from the streaming stack to the gameplay.
Gameplay systems in the test level · multiplayer, combat, gliding, climbing, swimming, loot and companions
Worlds render in Unreal Engine on cloud GPUs and stream to the browser over WebRTC, with input sent back in real time. One click, nothing to install.
Multiplayer keeps every guest, avatar and event in sync across a shared Unreal world, whatever device each guest joins from.
Each guest's live webcam rides on their avatar, alongside voice and text chat, so people actually see each other.
A modular, data-driven pipeline for face, body, outfits and skins that assembles thousands of unique characters from shared parts.
Gliding, climbing and swimming, combat with weapon pickups and loot chests, plus quests, farming and crafting, rideable mounts and companion pets.
Stages, screens and gathering spaces for community events, premieres and performances inside the world.
Plug-and-play environments and creator tools, so hosts can launch a branded space without building one from scratch.
Profiling and optimisation across rendering and gameplay raised frame-rate significantly. It matters twice here: every frame is also encoded and streamed.
Passage and StrangeClan are products of Passage. Art and content by their teams; I was an Unreal developer across both.