If you only use AI coding tools to write new code, you're getting half the value. Claude Code, Copilot, and Cursor are just as good at reading code that already exists and pointing out what's wrong with it. That's especially true for game code, which is full of traps that compile cleanly but quietly eat your frame budget — exactly the kind of thing a human reviewer skims right past.
The problem is that out-of-the-box AI review is far too generic. It hands you a pile of web-backend nitpicks — variable names, null checks, exception handling — while sailing straight past the per-frame heap allocations and boxing that are genuinely fatal in a game. Game code review only becomes useful once you've trained the reviewer on the game's rules.
This post uses Claude Code as the example and walks through a workflow that pins your game-specific review criteria into a file and automatically attaches an AI reviewer to the diff on every commit. Two things matter: what you tell it to look for, and when it runs automatically.
1. Pin your game-specific review criteria into a file
The first step is to write down the performance traps your project cares about and collect them in a single file. Create something like review-rules.md at your project root, and tell the AI to review against this checklist every time.
# Game code review checklist
- GC allocations inside Update, LateUpdate, FixedUpdate (new, LINQ, lambda closures, string concatenation)
- Per-frame FindObjectsOfType / GetComponent calls
- Enumerator boxing from iterating a collection cast to IEnumerable
- Using Vector3.Distance for distance comparisons where sqrMagnitude would do
- Synchronous Resources.Load / Instantiate / Destroy calls on a hot path
Keeping the criteria in the same repo as the code means your teammates and the AI all share one yardstick. Every time you discover a new trap, add a line — and your review quality compounds over time.
2. Attach the AI reviewer to the diff automatically
Once you have the criteria, run the review on the changes only. Instead of feeding in the whole codebase, hand over just the diff — it saves tokens and keeps the reviewer focused.
git diff main...HEAD | claude -p \
"Review this diff against review-rules.md. \
Focus on game hot-path performance, and cite each issue with its file and line number."
Drop this one line into a commit hook or a CI step and every PR gets a review automatically. A natural division of labor falls out of it: human reviewers focus on architecture and game-design intent, while the mechanical work of catching performance traps goes to the AI.
3. In practice: a hot-path allocation the AI caught
Here's a piece of targeting code you see all the time. It compiles, and it works. But it fills the heap with garbage on every single frame.
public class TargetingSystem : MonoBehaviour
{
public Transform target;
void Update()
{
var enemies = FindObjectsOfType<Enemy>()
.Where(e => e.IsAlive)
.OrderBy(e => Vector3.Distance(transform.position, e.transform.position))
.ToList();
if (enemies.Count > 0)
target = enemies[0].transform;
}
}
The AI review flags three things here. First, FindObjectsOfType is the most expensive call of the lot — it sweeps the entire scene every frame. Second, Where, OrderBy, and ToList allocate a fresh list and lambda closures on every frame. Third, the sort uses Vector3.Distance, but since only the ordering matters, there's no need to take the square root.
The fixed version caches the enemy list once and finds the nearest enemy with a simple, allocation-free loop.
public class TargetingSystem : MonoBehaviour
{
public Transform target;
Enemy[] _enemies;
void Start() =>
_enemies = FindObjectsByType<Enemy>(FindObjectsSortMode.None);
void Update()
{
Vector3 p = transform.position;
float bestSqr = float.MaxValue;
Enemy best = null;
foreach (var e in _enemies)
{
if (!e.IsAlive) continue;
float sqr = (e.transform.position - p).sqrMagnitude;
if (sqr < bestSqr) { bestSqr = sqr; best = e; }
}
target = best ? best.transform : null;
}
}
As a bonus, the AI swaps the legacy FindObjectsOfType for FindObjectsByType, the API Unity 6 recommends. And if the enemy list changes at runtime so you have to hold it in a List, the modern CollectionsMarshal.AsSpan lets you iterate the backing array directly with no enumerator allocation.
using System.Runtime.InteropServices;
foreach (var e in CollectionsMarshal.AsSpan(_enemyList))
{
// Iterate the List's internal array directly as a Span — no enumerator boxing
}
4. Trust the AI, but verify the numbers yourself
AI review is good at telling you "an allocation happens here," but how many bytes it actually is and how much it really costs the frame is only an estimate. The final call has to come from measuring it yourself with the Unity Profiler and Memory Profiler. The AI also over-flags sometimes — it'll warn about an allocation in initialization code that runs exactly once as if it were on a hot path — so a human has to filter for context.
The point is to use the AI as a fast first-pass filter, not an automated gate. Sieve out the obvious allocation mistakes before a human ever looks, and your reviewers get to spend their time on the design decisions that actually matter.
Wrap-up
- Default AI review is tone-deaf to games. You have to pin game-specific criteria — hot-path allocations, boxing, per-frame scene lookups — into a file and train the reviewer on them.
- Feed it just the diff and run it automatically in a commit hook or CI, and performance-trap detection comes free with every PR.
- The AI is great at locating allocations and even suggesting modern-API fixes, but a human still has to confirm the real cost with the Profiler.
Top comments (0)