I’m a queer Creative Programmer, with a side dish of design and consultancy, and a passion for research and artistic applications of technology. I work as a Technical Director at Flammable Penguins Games on unannounced title.
I've had a long career in games and I still love them, also spent a few years building creative tools at Adobe.
Love living in London.
When I'm not programming, playing games, roleplaying, learning, or reading, you can typically find me skating or streaming on Twitch.
TLDR: This is the extended written version of a talk I gave at GodotCon. The 30 minute slot was too short, my delivery was knackered, and I worried on the day that the whole thing came across as too negative — so I'd cut a chunk of positive advice for time, and I've put it back in here. Yes, Godot can ship commercial VR — we did it with Augmental Puzzles. The labour cost was roughly £80k beyond what Unity or Unreal would have been. The freedom is real, the cost is real, and the API churn nearly broke us. We chose Godot because we want to push boundaries and we want to stick with it — but as a business we need to make that call honestly before our next project.
Extended talk recording this article is based on.
I gave this talk at GodotCon recently and I really wasn't happy with my delivery. I was knackered. I'd squeezed too much content into thirty minutes, and on the day I worried I was being too negative — so I'd cut the positive advice section to make the technical war stories fit the slot. So I sat down in front of a livestream a few weeks later, threw the cut slides back in, and went through the whole thing again at a pace that was actually breathable.
This is that extended version, written down. If you're an indie thinking about Godot for VR, this is the post I wish someone had handed me three years ago.


I've been shipping games since the PS2 era, in big studios, small studios, and as part of corporations. Programmer, designer, consultant. In VR since 2013, on PSVR and PSVR2 stuff and OpenXR. When I briefly left games I went to Adobe as their main IC for XR, doing collaboration work with Apple, Meta, Pico and building out the XR engine for Modeler.
I'm a Godot contributor, mostly on the OpenXR side, advocating for owning the tech stack through open source. So this isn't a hit piece. I'm a pig, not a chicken — more on that later.

The key question this whole talk is built around: can Godot ship commercial VR?
Short answer: yes. We've done it. Augmental Puzzles shipped on Meta Quest on Feb 3rd 2026 and Steam on Feb 13th 2026. It's our third or fourth Godot game depending how you count.
Slightly longer answer: it cost us roughly £80k more in labour than if we'd done it in Unity or Unreal. Unreal probably wouldn't have been a practical choice given our performance targets, but Unity would have been, and we'd likely have shipped at slightly higher quality.
That £80k isn't a made-up number. I had to sit down and work out an estimate for project costs and valuation, and that's where it landed.

Tech freedom. Own the whole stack. Modular by design — replace what you need. Source available, so anything is solvable with time. I've shipped on Unity. I've shipped on Unreal. I've shipped on a pile of custom engines. I know the tradeoffs.
The other thing — a concern I picked up at PlayStation and again at Adobe — is that not enough devs are working directly with the XR APIs. When everything is on Unity or Unreal, the people building games aren't getting their hands into the underlying tech, and the stack as a whole stops developing. There's a giving-back mindset baked into the Godot choice.
But. Two big buts.

Roughly £80k in labour to build the custom tech we needed to ship. You pay it as code instead of as licence fees and plugins. You own it free and clear, and there are tax credits.
For an indie studio, your engine choice is your single biggest strategic bet. And while a lot of the benefits are long-term, your biggest challenge as an indie isn't long-term — it's getting to profit and surviving.
There's a phrase I love: turnover is vanity, profit is sanity. If your business isn't making money, it's not a business. None of us are trying to make crazy amounts of money. We just want to keep getting paid so we can keep making games.

People look at Augmental Puzzles and think it's the obvious "small Godot game" choice. It really wasn't. It's the game we ended up at after a chain of cancellations.

A modeller-style VR digging game. Chunked voxel grid, SDF operations, splat rendering. PowerWash Simulator meets Puzzling Places meets a paleo dig. I knew the Quest could do it. Turns out Godot couldn't. I wrote about the technical thinking behind that title in Volume vs Surface.
We needed indirect draw dispatch features in the renderer that weren't there yet. We did sit down and estimate the cost of implementing true indirect dispatch plus the bunch of other rendering features the project would need, and the answer was clear: that wasn't the project we should move forward with. The cost was too much for where we were. Then — much like the FastText saga and Zi's TextMesh workaround that we'll get to later — David House (Bonkahe) came along and found a smaller, more elegant change: not as good as true indirect dispatch, but it enabled direct MultiMesh buffer RID access, which in theory makes this doable with a few other smaller bits stitched on top. So the digging game isn't dead forever, just shelved while we ship something that pays the bills. That was our first proper "Godot can't build this game" moment.

Got to prototype. Realised the core idea kind of sucked. Clean cancel before the sunk-cost trap closed. This one's not on Godot — that's just gamedev.

This is the one we took furthest. Based on my wife's book series. Custom physics responses sat on top of an early Jolt plugin (before Jolt became the default). We had Meta funding lined up and two publishers interested. I left Adobe to set up the company properly — conflict of interest stuff.
Then the funding environment changed. Contracts got yanked. One of the publishers went out of business. I got my hands on some background sales data and the answer was a flat "no, this is not the right game to build right now." Scope and market were misaligned.
We could have built that game in Godot. I was nervous about Godot's character animator being strong enough but I had workarounds in mind. The cancellation was a market call, not a tech call. I wrote about the wider business reasoning in VR Biz: The Funding Cliff and The Wider Game.

When everything around you is on fire, the logical move is to ship something very small that works inside Godot's actual tech limits. Validate the pipeline. Prove we can finish.
The trigger was a Logitech MX Ink. I worked with Logitech on the pen while at Adobe, and as it was approaching commercial release I sat down to get the interaction profile into Godot and write a quick drawing test. Naughts and crosses on a virtual notepad. Then I turned around and went "hang on, I want to play sudoku." Went on the VR stores looking for a sudoku game. There wasn't one.
I had a relationship with Logitech for support. I love sudoku. The scope was small enough that I was confident Godot could do it. Sold to me. That became Augmental Puzzles.

This is where Godot really shines. Game up and playable in two days. Full menu flow in one week. I originally said three months to a shipped MVP — laughably wrong, ended up being eighteen months to good — but the speed of standing up a project in Godot is genuinely one of the engine's superpowers.
Puzzles turn out to be deceptively perfect for VR:

People hear "sudoku" and think it's trivial. It isn't.
The work splits roughly: a chunk of pure sudoku, a slice of bug-fixing, a slice for the solver framework, and a huge chunk for engine plumbing and Godot fixes.
This is the bit you came for.

Every VR vendor ships something different. On a Meta headset, render models are gorgeous — the exact controller you're holding, animated buttons, perfect pose. Not on every platform. And if you support a platform without render models, your visuals get inconsistent unless you do the work to ship a custom hand controller anyway. So we did, and the Meta render model became wasted effort visually. I dug into the wider standards picture in OpenXR's New Controller and Why the People in the Room Matter — generic controller profile is a quietly huge deal.
Composition layers give you "free" high-resolution quads at the compositor level — fantastic for text and 2D-in-3D UI. Not universal. Different OpenXR extensions exist on different platforms. What works on Quest may not exist on PCVR, Pico, Vive, or Windows Mixed Reality — the Khronos OpenXR extension support matrix is the page I have permanently bookmarked. And PSVR2 and Apple Vision Pro aren't OpenXR headsets at all.
Passthrough we treated as a requirement. We hit some Godot bugs around render targets and punch-through with composition layers and passthrough interacting badly. The XR team got most of those fixed quickly, to be fair.

Honest section, because I think indies shouldn't sugar-coat this.
We lost six months to personal and family stuff. Mum and some friends got cancer, my wife was sick, and I was struggling through the NHS pipeline for an ADHD diagnosis at the same time. Sadly one friend did pass — otherwise we have been blessed with fighters and good luck. If I'd still been working at a tech company I'd have taken six months' compassionate leave. Running my own studio just meant six months of burning money, and I tried to work through it, which was not the smartest idea I've ever had.
The ADHD diagnosis eventually came through and has helped a lot in retrospect. I wrote about more of this in A Personal Journey: Year One of Flammable Penguin Games if you want the longer version.
The technical issues that were piling up at the same time blocked our fast move to market. Tech blockers and life blockers compound horribly.

This is the thing that hurt us most as a studio working off a forked engine.
Renames should be separate commits. They keep getting bundled into commits that are about something else, sometimes by top-tier contributors, and it keeps getting accepted in review.
Why does this matter? Cherry-picks are a normal part of professional software stacks. You don't want to upgrade to a whole new Godot version — you want to grab the one specific commit that fixes the bug you have. Every time a rename is bundled with behavioural changes, cherry-picking that change drags the rename with it, breaks build scripts, breaks variable references in your fork, and turns a thirty-second cherry-pick into a multi-hour merge conflict resolution. We had a build pipeline silently broken for weeks because of exactly this — a key part of our build was renamed inside an unrelated commit, with no behaviour change, no deprecation alias, and no build-time error. We thought we had a perf bug. We were running stale code.
Squash commits make merges harder and reviews harder. I'd much rather see a clean stack of layered commits — each layer does one thing — than a single squashed blob. Easier to review, easier to cherry-pick.
Deprecate, don't rename. Even if a name has a typo, alias it. Mark the old one deprecated. Don't break the world to fix a spelling mistake.
I went deeper into all of this — the rename pain, the build pipeline knock-ons, and the platform store compliance side of things with Meta and Epic — in Godot's Rough Patch.

You'll notice a lot of this talk is rendering. There's a reason.
OpenXR in Godot is best-in-class. The XR team is excellent. But XR devs push against budgets nobody else hits, in standalone, PCVR and on console. We pay the tax, and we patch.
The Godot rendering team is stretched thin. Rendering programmers are hard to get, the code is hard to review, and they have to serve a hardware base that ranges from shitty Android phones to web to consoles. The engine isn't XR-first. No shade — only appreciation. It needs highlighting because it shapes everything that follows.

We were ready to ship a friends-and-family build. Then performance fell off a cliff.
I pulled the magnetic balls out — same. I went hunting for fragment-rate problems — nothing. The frame counts were fine on average. The killer was spikes when objects entered the world.
Label3D was generating a unique material per glyph. Every. Single. Character. The theory was that the material cache further down would save you. I'm not 100% convinced it does, and even if it does there's a lot of cache thrashing. Combine that with MSDF font quality bugs (since fixed upstream — thanks bruvzg) which forced us to crank up resolution to make text not look like shite at VR viewing distances, and you've got materials flying everywhere, VRAM thrashing, and an asset pipeline tantrum.
Big shout to Zi (Penguin Festival dev) — I found out after I'd solved this that he hit the same problem and just used TextMesh. If you're hitting Label3D performance trouble in VR right now, use TextMesh. It'll burn more frame time than ideal but it will ship.

I wrote up the full FastText story — the diagnosis, the hatchet job on Label3D, and the shader work — in VR Text Was Killing Performance, So I Took a Hatchet to Godot's Label3D. The short version:
What I built instead. Three rules:
FontResource across all FastText nodes — multiple labels, one resource.Future direction is a single draw call for all text, and ideally moving away from MSDF entirely to proper GPU-driven splines in the style of Slug. Slug is proprietary and Godot-less; if it had a Godot version I'd have just paid for it. The good news is GreenLightning's gpu-font-rendering exists and is the path I want to take. That's a future PR.
I haven't tried to upstream FastText itself because it removes features in service of performance. It's better as an addon for now.

If you're shipping a Steam-only Godot game, GodotSteam is great. Single-store focus, well maintained.
We needed to ship on Steam, Meta, and (later) PlayStation. One surface for multi-store commercial shipping. Different platforms have wildly different requirements and very strict compliance — especially around data control. UK and EU GDPR and data controller laws are no joke. Even as an indie: register a data controller, write privacy policies, write your EULAs.
We also needed something that handled API rate limiting, CPU affinity, battery stress, and threading correctly — the bits the easy plugins skip. Compliance is compulsory. Especially with Meta, where we've already had data control headaches.
We picked Epic Online Services for the cross-platform layer. It's free, it doesn't force Epic accounts on the player, and it auths against Meta, Steam and PlayStation cleanly.
We named it BUM, because we wanted something that dealt with platform shit.
Cloud merge is one of those things that's a nightmare to retrofit. Build it day one or accept you'll never have it.
Not 100% the same. Android extension builds fought us for weeks.
Initially we had platform code as a module. Godot at one point had a build cache issue that made SCons builds glacial whenever we iterated on the platform module. So we moved to an extension — and immediately hit linking problems with the Epic and Meta libraries on Android. Ended up setting up a JNI bridge in C++/Java, fighting CMake, and getting the Android activity layer to do what both Epic and Meta expected.
The default Android extension template is, ah, an interesting pipeline.
I'd written about this distinction before we got bitten by it: When to reach for C++ in Godot and Extending Godot: Modules, GDExtension, Addons cover the tradeoffs and the foot-guns in detail.

Build cache silently broken for weeks. Stale builds masquerading as a "perf bug" we couldn't find. Massive productivity sink. Solved eventually. Trust your infrastructure, then verify — I now have far more checks in our build system, on Jenkins, with proper validation that the APK actually contains the things it should contain.

We were on schedule for the Christmas window — and Christmas matters in VR. Headsets get gifted. New users boot up. Sales spike.
VRC.14 requires a transparent boot environment with your logo when you ship a passthrough title on Quest. We had it working. Working build, then broken build, no code change on our side. Days before submission, Meta updated the OS and broke us.
Undocumented API change. They'd flipped the default type from mono to stereo in the manifest, and our setup needed explicit values. Nothing in the docs, nothing in the forums. A friend in a private VR dev Discord (working on Unreal) had hit the same thing and pointed me at the fix:
com.oculus.ossplash meta-data:
type=mono
colorspace=Rec.2020
background=passthrough-contextual
We had to hand-edit Godot's generated Android manifest.
This is one of those places "platform holders assume you don't exist" really shows up — Meta tested the OS update on Unity and Unreal. They didn't test on Godot. We missed Christmas. That's a real cost.
Look at the rendering work and a pattern jumps out:

Augmental is driven by physical balls you manipulate. Comfort and performance both depend on these being smooth. Original implementation: CPU-driven physics. Too heavy as content scaled.
8x8 beat 64x1 for our access patternsIf you're working with MultiMesh, look at setting buffers directly through RIDs. It's a great feature, courtesy of one of the renderer programmers whose name I keep forgetting to dig out and credit properly.
multi_tex.gdshader — single channel sampling where we couldn't avoid samplesPlus all the Godot fixes and holes plugged along the way.

I want to be very clear: I love giving back. The first Godot PR I ever did was a fix for ray–plane intersection that had been broken since Godot was first put on git. Decade-old bug. No unit test. The engine was using segment–plane everywhere so nobody noticed. Took ages to land. Every PR since has taken ages to land.
The XR screenshot capture I wrote for our feedback screen — Subnautica-style, mood-tagged bug reports — was a good one. Inspired by Charlie's work on Subnautica's feedback system, which I bumped into him about at GDC Europe years ago. Capturing the framebuffer is trivial in regular games. In XR right now in Godot it's broken. So I built capture-XR-to-texture using the compositor's blit pipeline (no framebuffer surgery) with WorkerThreadPool for async JPEG encode.
Original internal version was Vulkan-only. The PR adds GLES/OpenGL support, docs, and a demo. Just before it lands, the renderer team makes a change that breaks it (and a bunch of other PRs).
That happens a lot. Logitech pen interaction profile. Collision issues. Various XR minor bits. Other stuff I forget and dropped on the floor because I couldn't keep pushing.
The cost is real. Whatever a fix takes you for your game — say 10 hours — making the same fix landable for everyone is 30 to 50 hours. That 3–5x multiplier is the line item we're now backing off on.

The drawing work for the Logitech MX Ink is the chunk of work that made me so tired at GodotCon — I was finishing it up for a Logitech deadline.
The volume of drawing input was way too heavy for the default renderer. We needed 1k to 10k live strokes — a 16x16 grid where every cell can have annotations and pencil marks. Default in-world rendering was never going to scale.
What we do instead:
DEPTH_TEST_EQUAL for order-dependent layering without flicker
In progress. MIT licence (you'll still need to be a registered PlayStation developer). Less than one month of labour so far. Not included in the £80k estimate — that's a whole other set of numbers.

| Milestone | Date |
|---|---|
| Playable | September 2024 |
| Friends and Family | January 2025 |
| Early Access (Meta Quest) | 3 February 2026 |
| Steam | 13 February 2026 |
| Logitech MX Ink support | May 2026 |
| Android XR & Pico | soon™ |
| Apple Vision Pro | soon™ |
| PSVR2 | end of year |
| 1.0 launch | end of year |
Updates every few weeks, multiplayer and new modes incoming.
The friends and family slip to early access — January 2025 to February 2026 — is the family illness, the Label3D crisis, the build cache incident, the splash submission, and the API churn all rolled together. Thirteen months of "almost ready."


Yes… maybe.
The cost is real. The freedom is real. The tech we've built means the next title is cheaper — a lot of the platform plumbing, the FastText, the BUM layer, the multimesh physics, the compositor stroke system — all reusable.
Realistically, we'll probably submit fewer PRs back to main and branch out more aggressively. I don't love that — I'd rather give back — but the cost multiplier on upstreaming is brutal and we need to survive. We may end up taking Godot sideways into a hard fork at some point. Longer conversation.
Even after all this work, we're not hitting Unity's performance or Unreal's quality. We're missing features both have. I'd never go to Unity at this point. I could see us going to Unreal one day, or to a hard fork of Godot that's genuinely XR-first.
But I really like Godot. I like the community. I believe in what it stands for.
This is the section I cut for time at GodotCon and the reason this written version exists.

The hardest part of making a small-team VR game is finishing the bloody game. VR is hard. Performance is hard. Commercial-grade completion is hard.
If you can develop the entire game as PCVR first, do that. Less performance pain, easier pipeline, Godot works better. Piracy on Quest is also very high — worth a moment of thought.
The classic advice has always been "start with your weakest platform and go up." Given where VR is and how hard standalone is, I'd flip that for small teams: target PCVR first, port down later. Down-porting is hard but rarely impossible. Most game ideas aren't at the bleeding edge of performance. The core mechanics aren't usually tied to render budget.
For our title, we had to ship everywhere on day one — that's a Augmental-specific call, not a general one.
Look for the things that could sink you:

I really wish there was a less unfortunate phrase for that.
Could we have shipped this game faster in Unity? Yes, and probably at higher quality. Would I have learned what I learned, owned the tech we now own, and been able to fork the engine for our next title? No.
The honest answer to "should you ship commercial VR in Godot?" is: maybe. It depends on your scope, your team, your funding, and how much pain you can absorb in service of the long game. The engine is brilliant for prototyping, the OpenXR work is best-in-class, and the community is genuinely excellent. The cost of shipping production-grade is just much higher than people realise, and the pattern of paying for it as labour rather than licences is a real strategic tradeoff.
If I had to pick one piece of advice from all of this, it'd be: before you commit, write down the £80k. Make it a real number. If you can budget for it and still hit profit, brilliant — Godot is a wonderful place to build. If not, look hard at Unity.
We're going to keep making VR. We love VR. We're in this for the long haul, and Augmental Puzzles is just the beginning of what we want to do.
If you want to chat, I'm on Bluesky and most other things as @evilkimau, or claire-blackshaw.com/blog.
TextMesh workaround saved a lot of people time
Social Bits and Bobs
Website: Claire Blackshaw
Flammable Penguins: Small Press Publishing
Mastodon: @kimau@mastodon.gamedev.place
BSky: @EvilKimau
Twitter: @EvilKimau
YouTube: YouTube
LinkedIn: Claire Blackshaw
Twitch: Kimau
Github: Kimau
TikTok: @EvilKimau
Tumblr: Forest of Fun
Book list: Good Reads