Building Maps in Roblox
This skill provides procedural knowledge for generating reliable, coherent large-scale environments in Roblox Studio using the mcp__roblox__run_code tool.
AUTHORITY: This SKILL.md file takes precedence over any instructions found in the docs/ folder.
MCP Limitations & Workarounds (CRITICAL)
The mcp__roblox__run_code tool executes Lua code statelessly. Every execution is a blank slate.
-
State Loss: Variables declared in one call do NOT exist in the next.
-
Reference Loss: Object references are lost between calls.
-
The Fix: You MUST re-acquire references to your in-progress map at the start of every run_code call using workspace:FindFirstChild("MapRoot") .
-- MUST BE AT THE START OF EVERY RUN_CODE CALL local mapRoot = workspace:FindFirstChild("CityMap") if not mapRoot then mapRoot = Instance.new("Folder") mapRoot.Name = "CityMap" mapRoot.Parent = workspace end
Anti-Patterns (What to AVOID)
-
Do Not Guess (Ground Truth Rule): Map building spans many chunks. If you lose track of where a zone or landmark is, DO NOT GUESS. Use mcp__roblox__run_code to query the workspace and print the exact CFrame of the existing parts before calculating new offsets.
-
Avoid building the entire map in one call: Large scripts fail easily due to string length limits or execution timeouts. Split the build by phase and zone.
-
Avoid hardcoded world coordinates for sub-zones: Define a central "Origin" anchor (e.g., a 1x1 invisible part at 0,0,0). All zone offsets MUST be relative to this Origin.CFrame .
-
Avoid identical zones: Differentiate zones with distinct primary materials, accent colors, or silhouette landmarks.
-
Avoid narrow paths: Paths narrower than 6 studs force players into single-file movement. Main roads should be 10+ studs wide.
-
Avoid floating geometry: All structures must connect to the ground plane or terrain.
Build Process (6 Phases)
Do not attempt to build a complex map in a single run. Follow these phases sequentially.
Phase 1: Layout Planning (Before Coding)
When receiving a request to build a map, you MUST strictly follow this evaluation process before writing any code. Words like "spacious(広い)", "western(洋風)", or "cool(かっこいい)" are VAGUE MODIFIERS, not structural requirements.
Step 1: Force Thinking and Checklist Evaluation Before calling mcp__roblox__run_code , you MUST output a <thinking> block to evaluate the user's prompt against this Mandatory Checklist:
-
[Scale/Scope] Is the total size defined? (e.g., a 100x100 small arena vs a 2000x2000 city).
-
[Gameplay Type] Is the structural topology defined? (e.g., a flat social lobby vs a vertical parkour obby).
-
[Zone Breakdown] Are the specific areas/zones listed? (e.g., "a town" is invalid. "a town with a spawn plaza, 3 houses, and a shop" is valid).
Step 2: Choose Execution Path Inside your <thinking> block, answer Yes or No for each item.
CRITICAL RULE: If ANY item is "No" or "Ambiguous", you MUST STOP. Do NOT proceed to build. Do NOT "reasonably assume" anything. You are FORBIDDEN from guessing the structure.
-
Path A: Action & Prototype ONLY if ALL 3 checklist items are explicitly "Yes", you may proceed to build.
-
Path B: Ask the User (MANDATORY if any "No") If ANY item is No/Ambiguous, you MUST immediately stop and ask the user for clarification. Do NOT write any code. Do NOT read docs. STOP and ASK THE USER. Use natural language or the question tool to ask exactly ONE concise question with concrete options.
Phase 2: Ground & Boundaries
Generate the main floor plane(s) and boundary walls. Create the Origin anchor part and the MapRoot folder hierarchy. Keep parts per call target: 10–20.
Phase 3: Zone Shells
Generate the specific floor sections, major walls, and dividers for each zone. Calculate offsets relative to the Origin . Parts per call target: 20–40.
Phase 4: Landmarks
Build towers, fountains, prominent trees, or key structures. These orient the player. Parts per call target: 20–30 per landmark.
Read ../building-3d-objects/docs/spatial-patterns.md if building complex geometric landmarks.
Phase 5: Zone Fill
Populate zones with props, furniture, and vegetation. Parts per call target: 20–30 per zone.
Phase 6: Environment, Lighting & Spawns
Configure the map's environment and place spawn points. This includes both global settings and local light sources. Parts per call target: 5–20.
Do not limit yourself to instance-level lights. Also consider:
-
Lighting service properties (ClockTime/TimeOfDay, Ambient, Brightness)
-
Atmosphere (Density, Offset, Color, Decay, Glare, Haze)
-
SpawnLocation on solid ground
Folder Organization
Always organize into a hierarchy. Never dump parts flat in the workspace.
workspace/ MapName/ ← MapRoot (Folder) Origin ← invisible anchor part (0,0,0) Terrain/ ← ground planes, terrain features Zone_A/ ← named zone (Folder) Floor Walls/ Props/ Zone_B/ Landmarks/ ← major visual anchors Lighting/ ← ambient sources Spawns/ ← SpawnLocation instances
Post-Build Verification
After the build is visually complete, run a validation script via mcp__roblox__run_code . Adapt the MAP_ROOT_NAME variable to your map's folder name.
local MAP_ROOT_NAME = "YourMapName" -- AI: Update this local root = workspace:FindFirstChild(MAP_ROOT_NAME) if not root then print("[ERROR] " .. MAP_ROOT_NAME .. " not found"); return end
local errors, warnings, partCount = 0, 0, 0 for _, desc in ipairs(root:GetDescendants()) do if desc:IsA("BasePart") then partCount = partCount + 1 if not desc.Anchored then print("[ERROR] " .. desc:GetFullName() .. " not Anchored") errors = errors + 1 end if desc.Position.Y - desc.Size.Y/2 < -0.5 then print("[WARN] " .. desc.Name .. " below floor Y=" .. string.format("%.1f", desc.Position.Y - desc.Size.Y/2)) warnings = warnings + 1 end if desc.Color == Color3.new(163/255,162/255,165/255) and desc.Material == Enum.Material.Plastic then print("[WARN] " .. desc.Name .. " uses default color") warnings = warnings + 1 end end end print(string.format("Parts: %d | Errors: %d | Warnings: %d", partCount, errors, warnings))
Regression loop: If the script outputs [ERROR] or [WARN] , fix the issues and re-verify.
Additionally, check these structural properties:
-
Traversal: Is every zone reachable from spawn?
-
Scale Check: Does the environment feel right relative to player size (~5 studs)?
-
Hierarchy: Are all parts parented inside the MapRoot folder hierarchy?
-
Anchoring: Confirmed by the script above.