Develop

Optimize Unity Meta Quest VR game performance with AI

Updated: May 5, 2026
Your slash game is functional, but you don’t yet know whether it holds the crucial 72fps on Quest. This tutorial guides you through measuring actual performance on the headset, identifying the bottlenecks consuming your frame budget, and resolving those issues. You use the same AI workflow as in previous tutorials, but this time focused on performance optimization rather than feature development.

What you need before starting

Open a terminal, navigate to your Unity project folder, and run claude. Send all prompts below in that Claude Code session.

Step 1: Capture a performance trace

Your game looks and feels right, but the Quest’s mobile GPU has a tight frame budget. The dissolve shader, energy blade, and mesh slicing you added in the previous tutorial all cost something. The only way to know the real cost is to measure it on the headset.
Play your slash game on your headset for 30 to 60 seconds. Trigger some combo chains and let the difficulty ramp up.
Tip: Run hzdb device configure-testing setup first to put your Quest in a testing-friendly state. It disables animations and keeps the screen awake for more consistent traces. Run hzdb device configure-testing restore when you’re done testing.
Terminal output after running hzdb device configure-testing setup
While the game is running, open your terminal and run:
hzdb perf capture --duration 10000 -o before_optimization
This captures a 10-second Perfetto trace from the Quest, including CPU/GPU frame timing, rendering stats, and system activity. The -o flag names the session so you can reference it in later steps.
Terminal running the hzdb performance capture command while the slash game runs on Quest
Verify: A trace is saved with session ID before_optimization and the file path is printed in your terminal.
Tip: To open the raw trace in Perfetto’s web UI, run hzdb perf open before_optimization. If you see a port 9001 conflict, run lsof -i :9001 to check what’s using it. If it’s a previous Perfetto server, stop it and retry. If it’s the Unity MCP, quit it with Ctrl+C first — you can restart it after the hzdb perf commands finish.

Step 2: Analyze the trace

You have a raw trace file with thousands of data points about what your Quest was doing during those 10 seconds. Instead of opening it in a trace viewer and reading it yourself, let Claude do the analysis. This prompt asks Claude to focus on the top bottlenecks rather than a full dump, so you get actionable results.

Prompt

I captured a Perfetto trace with session ID `before_optimization` while playing my slash game on Quest. Are any frames missing the 72fps target? What are the top 3 things eating the most frame budget? Break it down by GPU vs CPU.
Behind the scenes, the hz-perfetto-debug skill from the agentic-tools plugin reads the trace. The skill runs hzdb perf analyze-trace to query trace_processor for frame timing distributions, GPU render pass costs, thread scheduling, and bottleneck detection. This is a deterministic analysis of what actually happened on your hardware, not Claude guessing from training data. You can also run it directly in a separate terminal to see the raw analysis yourself:
hzdb perf analyze-trace before_optimization
Look for these patterns in the results:
  • Frame times above ~13.9 ms indicate dropped frames.
  • Draw calls above ~100 per frame suggest batching issues.
  • GC allocations during gameplay mean something is creating objects every frame.
  • GPU-bound means shaders are too expensive.
  • CPU-bound means scripts or physics are the bottleneck.
If your game is already hitting 72fps consistently, there’s almost always something to optimize, and the workflow is the same either way.
Claude analyzes the Perfetto trace and reports the top frame-budget bottlenecks
Verify: Claude identifies specific frames, timings, and bottleneck categories from your trace data.

Step 3: Review code and pick fixes

The trace tells you where the budget is going: a GPU bottleneck, a CPU spike, or GC pressure. Now let Claude look at the actual code to tell you why, and pick what to fix first. The features you added in the previous tutorial (dissolve shader, energy blade, runtime mesh slicing) are powerful but expensive on mobile hardware.

Prompt

Based on that trace analysis, review the slash game code for anything that's wasting performance on Quest. The dissolve shader, energy blade, and mesh slicing are probably the expensive parts. Between the trace data and the code, what are the top 2 fixes I should focus on first? Consider both the steady-state GPU cost and the worst-case frame spikes.
This flags VR-specific anti-patterns: things that work fine on PC but tank frame rate on Quest’s mobile GPU. Claude connects the trace data (where the budget goes) with the code (why it goes there) and recommends the highest-impact fixes.
Once Claude tells you the top bottleneck, you can cross-reference with Meta’s official optimization docs:
hzdb docs search "Quest GPU performance optimization"
Replace the search query with whatever Claude identified. This gives you Meta’s recommended fix alongside Claude’s analysis, which is useful when you want to double-check or go deeper.
Claude lists VR anti-patterns with file and line references and ranks the top two fixes
Verify: Claude recommends specific fixes with estimated impact, referencing both the trace data and actual code files.

Step 4: Apply the fixes

Now apply the two fixes Claude recommended. The exact changes depend on what your trace and code review found. Here’s roughly what to expect.
The first fix is usually a shader optimization. Claude simplifies the most expensive shader, reducing per-pixel computation and removing unnecessary overdraw.
The second fix is likely a memory optimization: pooling objects or reusing buffers to eliminate the GC spikes that cause the worst-case frame hitches.
Treat these as illustrative examples, not predictions for your project.

Prompt

Apply both fixes. For each one, tell me what you changed and what improvement you expect.
Claude reports the files changed and the expected gains for each applied fix
Verify: Code compiles, and the game still plays correctly in the Unity Editor.
If a fix breaks something: “The blade looks wrong after the shader change. Revert and try a less aggressive simplification.”

Step 5: Re-capture and compare

Time to close the loop. Comparing traces is how you confirm the fix actually helped and didn’t introduce a new problem. Build the optimized version, deploy it to Quest, capture a fresh trace, and compare. This is the core performance workflow. You use it any time you add expensive features.
  1. In the Unity Editor, press Ctrl+S (Mac: Cmd+S) to save your project.
  2. Go to File > Build Settings > Build. Save to your Builds folder as SlashGame.apk.
  3. In your terminal, install the build: hzdb app install ./Builds/SlashGame.apk.
  4. Launch the app: hzdb app launch com.YourCompany.YourApp (find your app name in Edit > Project Settings > Player > Other Settings > Package Name).
If install fails: Run export HZDB_ADB_PATH=$(which adb) and retry. This handles the case where adb devices shows your Quest but hzdb app install doesn’t.
Play again for 30 to 60 seconds, then capture another trace in your terminal (the first trace is safe because it has its own session ID from Step 1):
hzdb perf capture --duration 10000 -o after_optimization
This saves the new trace under the session ID after_optimization. You now have two session IDs — before_optimization and after_optimization — that you can pass to hzdb perf compare.
Now ask Claude to compare. Under the hood, Claude uses hzdb perf compare to diff the two traces, showing exactly what improved, what regressed, and by how much.

Prompt

I captured a new trace with session ID `after_optimization` after applying the fixes. Compare it against the original session `before_optimization`. Did frame times improve? Are the GPU or GC spikes reduced? Show me before/after numbers for the top issues.
The comparison shows what improved, what regressed, and what to fix next.
Animated before/after comparison showing improved frame times and reduced GC spikes
Verify: Frame times are more consistent, with few or zero frames above ~13.9 ms. Your before/after numbers may not show dramatic improvement. Thermal throttling, different gameplay intensity, and GPU clock states all affect traces and performance.
For a deterministic, no-LLM equivalent, run:
hzdb perf compare before_optimization after_optimization

Troubleshooting

ProblemFix
hzdb perf capture fails
Ensure Quest is connected: hzdb device health-check.
Trace file is empty
Play the game actively during capture. Idle scenes generate minimal data.
No improvement after optimization
Check whether the bottleneck is GPU-bound (shader complexity) or CPU-bound (script logic). Use hzdb perf capture --mode gpu for shader issues.
Dissolve or energy blade shaders still slow
Reduce noise texture resolution, switch to half-precision, and simplify emission calculations.
Mesh slicing causes frame spikes
Pre-allocate buffers in the mesh slicer and reduce the maximum simultaneous sliced halves.
trace_processor_shell download fails
Check your internet connection. hzdb auto-downloads it on the first performance capture.
hzdb app install fails
Try hzdb device health-check first. If the device shows but install fails, run export HZDB_ADB_PATH=$(which adb) and retry.
Your game runs well. You now have the core performance loop — capture, analyze, fix, and compare — to apply any time you add expensive features.