Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/brockmartin/roblox-game-skill/llms.txt

Use this file to discover all available pages before exploring further.

The Performance Audit workflow systematically identifies and resolves the most common performance bottlenecks in Roblox games: excessive part counts, CPU-heavy script patterns, memory leaks from unmanaged connections, and over-eager network traffic. It covers eight steps from initial project scan through applied fixes and a before/after comparison. Use this workflow when your game drops below target frame rate, when the MicroProfiler shows unexpected spikes, or as part of the Publish Checklist before going live. Trigger: “Audit performance”, “my game is lagging”, “optimize my game”, “FPS is low”, or as a pre-publish step.
1

Project Scan

Claude gathers baseline information and scans for known anti-patterns before diving into specific categories.
Uses get_project_structure to map the full source tree, then grep_scripts to scan for:
  • wait( — deprecated; should be task.wait()
  • .Heartbeat:Connect( — count across all scripts
  • Instance.new inside loops — mass instantiation without pooling
  • while true do tight loops without yielding
  • game:GetService called inside functions instead of cached at script top
All findings are recorded with file paths and line numbers for use in the priority report.
2

Part Count Audit

Claude evaluates the workspace part count and physics complexity.
Part CountStatus
Under 10,000Acceptable for most genres
10,000–50,000Needs StreamingEnabled or aggressive culling
Over 50,000Critical — redesign required
Beyond total count, Claude checks:
  • Unanchored partsBasePart instances where Anchored == false that are not intentionally physics-driven. Each costs physics simulation time every frame.
  • MeshPart triangle counts — Any MeshPart exceeding 10,000 triangles is flagged for LOD or replacement.
  • Transparency abuse — Parts with Transparency = 1 that still have CanCollide = true should have CanCollide and CanQuery disabled and be removed from the render pipeline entirely.
  • Union complexity — Large CSG UnionOperation instances that could be replaced with MeshPart for better GPU performance.
3

Script Audit

Claude reviews runtime script behavior for CPU-heavy patterns.
PatternIssueFix
Multiple Heartbeat connections per scriptFragmented update logicConsolidate into a single connection
while true do faster than neededWastes CPU every tickThrottle to task.wait(1/30) or task.wait(1/60)
game:GetService inside function bodiesRepeated lookup every callCache as top-level locals
wait() / spawn() / delay()Deprecated; unreliable timingReplace with task.wait() / task.spawn() / task.delay()
String .. concatenation in hot pathsCreates garbage per concatenationUse table.concat
Deep FindFirstChild / WaitForChild chainsFragile and slowCache references at initialization
Example: deprecated API and service caching
-- BEFORE (two anti-patterns)
while true do
    local players = game:GetService("Players"):GetPlayers()
    wait(0.1)
end

-- AFTER (task library + cached service)
local Players = game:GetService("Players")

while true do
    local players = Players:GetPlayers()
    task.wait(0.1)
end
4

Memory Audit

Claude searches for memory leaks and resource retention issues.Undisconnected event connections are the most common leak in Roblox games. Claude scans for :Connect( calls where the returned RBXScriptConnection is never stored or disconnected — especially inside PlayerAdded, CharacterAdded, and any function called repeatedly.
-- BEFORE (leak: connection never cleaned up)
game:GetService("Players").PlayerAdded:Connect(function(player)
    player.CharacterAdded:Connect(function(character)
        -- This connection leaks on every respawn
        character:FindFirstChild("Humanoid").Died:Connect(function()
            print("died")
        end)
    end)
end)

-- AFTER (connections stored and cleaned up)
local Players = game:GetService("Players")
local connections = {}

Players.PlayerAdded:Connect(function(player)
    connections[player] = {}
    player.CharacterAdded:Connect(function(character)
        local humanoid = character:WaitForChild("Humanoid")
        local conn = humanoid.Died:Connect(function()
            print("died")
        end)
        table.insert(connections[player], conn)
    end)
end)

Players.PlayerRemoving:Connect(function(player)
    if connections[player] then
        for _, conn in ipairs(connections[player]) do
            conn:Disconnect()
        end
        connections[player] = nil
    end
end)
Claude also checks for:
  • Instance.new() calls where the instance is never parented or destroyed (orphaned in memory)
  • Debris:AddItem() with lifetimes over 60 seconds, or not used at all for temporary effects
  • IntValue / ObjectValue instances created dynamically but never destroyed
  • Lua tables that grow unboundedly (e.g., logging every frame without pruning)
5

Network Audit

Claude evaluates RemoteEvent firing patterns for bandwidth efficiency.
IssueDescriptionFix
Remotes inside Heartbeat / tight loopsFires every frame — floods bandwidthGate with a throttle timer
Large table payloads (50+ keys)Expensive to serializeSend only changed fields
FireAllClients for player-specific dataSends private data to everyoneSwitch to FireClient
Excessive SetAttribute on replicated instancesCauses network churnBatch updates or use remotes
Instance.new on server in hot pathsReplicates to all clientsMove VFX to client-side
Example: throttled remote firing
-- BEFORE (fires every Heartbeat frame — ~60 times/second)
local RunService = game:GetService("RunService")
RunService.Heartbeat:Connect(function()
    UpdateStats:FireAllClients(getStats())
end)

-- AFTER (fires at most 10 times/second)
local RunService  = game:GetService("RunService")
local RATE        = 1 / 10   -- 10 Hz
local accumulator = 0

RunService.Heartbeat:Connect(function(dt)
    accumulator += dt
    if accumulator >= RATE then
        accumulator = 0
        UpdateStats:FireAllClients(getStats())
    end
end)
6

Priority Report

Claude compiles all findings into a tiered report.
## Performance Audit Report

### Critical (fix before shipping)
- [Finding]: [File:Line] — [Description and impact]

### High (significant impact on player experience)
- [Finding]: [File:Line] — [Description and impact]

### Medium (noticeable under load)
- [Finding]: [File:Line] — [Description and impact]

### Low (minor optimization opportunity)
- [Finding]: [File:Line] — [Description and impact]

### Summary
- Total findings:           X
- Estimated part count:     X
- Heartbeat connections:    X
- Potential memory leaks:   X
- Network hotspots:         X
SeverityThreshold
CriticalCrashes, server lag above 100 ms, or client FPS below 30 on target hardware
HighMeasurable frame drops, memory growth over time, or bandwidth spikes
MediumPatterns that degrade under load (20+ players)
LowBest-practice improvements with minor performance benefit
7

Apply Fixes

For each finding, Claude either applies the fix directly or provides the corrected code.
  • Direct fix — If MCP write access is available and the fix is safe (e.g., replacing wait() with task.wait()), Claude applies it and notes the change.
  • Code suggestion — For architectural changes (consolidating Heartbeat connections, implementing object pooling), Claude provides refactored code with explanation.
  • Manual step — For Studio-only fixes (anchoring parts, reducing mesh complexity), Claude gives clear instructions for the user.
All fixes preserve existing game behavior. Performance optimization must never change game logic.
8

Before/After Summary

Claude presents a comparison table of the project state before and after the audit.
## Before/After Summary

| Metric                  | Before | After | Change |
|------------------------|--------|-------|--------|
| Anti-pattern instances  |   X    |   X   |   -X   |
| Heartbeat connections   |   X    |   X   |   -X   |
| Potential memory leaks  |   X    |   X   |   -X   |
| Deprecated API calls    |   X    |   X   |   -X   |
| Network hotspots        |   X    |   X   |   -X   |
| Estimated part count    |   X    |   X   | (note) |

### Changes Applied
1. [File] — [What was changed and why]

### Remaining Manual Steps
1. [What the user needs to do in Studio]
If fixes were code-only suggestions (not applied automatically), Claude lists which items remain unresolved and their priority level.
For a deeper look at the specific Luau optimization techniques behind these fixes — including object pooling patterns, caching strategies, and efficient data structures — see Performance Optimization.

Build docs developers (and LLMs) love