roblox-building

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Building 3D in Roblox via MCP

通过MCP在Roblox中构建3D内容

Use this skill when the AI is creating physical geometry in Roblox Studio through an MCP connection (execute_luau / run_code). Covers single objects, room-scale structures, and multi-zone maps.
当AI通过MCP连接(execute_luau / run_code)在Roblox Studio中创建物理几何结构时,请使用本技能。涵盖单个对象、房间规模的结构以及多区域地图。

MCP Statelessness (CRITICAL)

MCP无状态性(至关重要)

MCP code execution is stateless. Every call is a blank slate.
  1. Variables don't persist between calls.
  2. Object references are lost between calls.
  3. Fix: Re-acquire references at the start of EVERY call.
luau
-- MUST be at the start of every MCP call
local model = workspace:FindFirstChild("MyBuild")
if not model then
    model = Instance.new("Model")
    model.Name = "MyBuild"
    model.Parent = workspace
end
Ground Truth Rule: Never guess coordinates from chat history. If you need the position/size of a previously created part, READ it from workspace first:
luau
local existing = model:FindFirstChild("TableTop")
if existing then
    print(existing.CFrame, existing.Size) -- read before calculating offsets
end
MCP代码执行是无状态的。每次调用都是全新的环境。
  1. 变量不会在调用之间持久化
  2. 对象引用会在调用之间丢失
  3. 解决方法:在每次调用开始时重新获取引用。
luau
-- 必须放在每个MCP调用的开头
local model = workspace:FindFirstChild("MyBuild")
if not model then
    model = Instance.new("Model")
    model.Name = "MyBuild"
    model.Parent = workspace
end
基本原则:永远不要从聊天记录中猜测坐标。如果需要获取之前创建部件的位置/尺寸,请先从workspace中读取:
luau
local existing = model:FindFirstChild("TableTop")
if existing then
    print(existing.CFrame, existing.Size) -- 计算偏移前先读取
end

Player Scale Reference

玩家比例参考

  • Player height: ~5 studs
  • Doorway: 4 wide × 7 tall
  • Ceiling height: 10-14 studs (rooms), 16+ (halls)
  • Table/counter top: 3.5-4 studs from floor
  • Seat height: ~1.5 studs from floor
  • Paths: minimum 6 studs wide (10+ for main roads)
  • Stair step: 1 stud rise, 1.5 stud run
  • 玩家身高:约5 studs
  • 门口:宽4 × 高7 studs
  • 天花板高度:房间为10-14 studs,走廊为16+ studs
  • 桌子/柜台高度:距离地面3.5-4 studs
  • 座椅高度:距离地面约1.5 studs
  • 路径:最小宽度6 studs(主路建议10+ studs)
  • 楼梯台阶:高度1 stud,深度1.5 stud

Build Process

构建流程

Objects (single Model)

对象(单个Model)

  1. Assess — Do you know the components, scale, and style? If not, ask.
  2. Plan — Declare dimensions as named variables. Choose an anchor part.
  3. Build — Generate parts with relative positioning. Split across calls if >20 parts.
  4. Verify — Run validation (check Anchored, below-floor, default colors).
  1. 评估 — 你是否了解组件、比例和风格?如果不了解,请询问。
  2. 规划 — 将尺寸声明为命名变量。选择一个锚定部件。
  3. 构建 — 生成带有相对定位的部件。如果部件超过20个,拆分到多个调用中。
  4. 验证 — 运行验证(检查是否锚定、是否低于地面、是否使用默认颜色)。

Maps (multi-zone)

地图(多区域)

  1. Layout — Define total size, zone breakdown, gameplay type. If any is vague, ask.
  2. Ground — Floor planes, boundaries, Origin anchor, folder hierarchy.
  3. Zone shells — Floor sections, walls, dividers per zone.
  4. Landmarks — Orientation structures (towers, fountains, trees).
  5. Fill — Props, furniture, vegetation per zone.
  6. Environment — Lighting, Atmosphere, SpawnLocations.
  1. 布局 — 定义总尺寸、区域划分、游戏玩法类型。如果有任何模糊之处,请询问。
  2. 地面 — 地面平面、边界、原点锚点、文件夹层级。
  3. 区域框架 — 每个区域的地面部分、墙壁、分隔物。
  4. 地标 — 定位结构(塔楼、喷泉、树木)。
  5. 填充 — 每个区域的道具、家具、植被。
  6. 环境 — 光照、大气、SpawnLocations。

Spatial Patterns

空间模式

Geometric Manifest (named dimensions, no magic numbers)

几何定义(命名尺寸,无魔法数字)

luau
local Def = {
    Width = 6.0,
    Depth = 3.0,
    Height = 2.8,
    TopThickness = 0.2,
    LegSize = 0.3,
    LegInset = 0.1,
}
luau
local Def = {
    Width = 6.0,
    Depth = 3.0,
    Height = 2.8,
    TopThickness = 0.2,
    LegSize = 0.3,
    LegInset = 0.1,
}

Relative Positioning (anchor pattern)

相对定位(锚定模式)

All sub-parts position relative to an anchor part's CFrame. Never use hardcoded world coordinates.
luau
local top = Instance.new("Part")
top.Size = Vector3.new(Def.Width, Def.TopThickness, Def.Depth)
top.CFrame = CFrame.new(0, Def.Height - Def.TopThickness / 2, 0)
top.Anchored = true
top.Parent = model

-- Legs relative to top
local legH = Def.Height - Def.TopThickness
local leg = Instance.new("Part")
leg.Size = Vector3.new(Def.LegSize, legH, Def.LegSize)
local ox = Def.Width / 2 - Def.LegSize / 2 - Def.LegInset
local oz = Def.Depth / 2 - Def.LegSize / 2 - Def.LegInset
leg.CFrame = top.CFrame * CFrame.new(ox, -(Def.TopThickness / 2 + legH / 2), oz)
leg.Anchored = true
leg.Parent = model
所有子部件的位置都相对于锚定部件的CFrame。永远不要使用硬编码的世界坐标。
luau
local top = Instance.new("Part")
top.Size = Vector3.new(Def.Width, Def.TopThickness, Def.Depth)
top.CFrame = CFrame.new(0, Def.Height - Def.TopThickness / 2, 0)
top.Anchored = true
top.Parent = model

-- 相对于桌面的桌腿
local legH = Def.Height - Def.TopThickness
local leg = Instance.new("Part")
leg.Size = Vector3.new(Def.LegSize, legH, Def.LegSize)
local ox = Def.Width / 2 - Def.LegSize / 2 - Def.LegInset
local oz = Def.Depth / 2 - Def.LegSize / 2 - Def.LegInset
leg.CFrame = top.CFrame * CFrame.new(ox, -(Def.TopThickness / 2 + legH / 2), oz)
leg.Anchored = true
leg.Parent = model

Grid Snapping

网格对齐

Snap dimensions to consistent increments (0.125, 0.25, or 0.5 studs). Avoid arbitrary decimals like 0.333 or 1.17 which compound into visible gaps.
将尺寸对齐到一致的增量(0.125、0.25或0.5 studs)。避免使用0.333或1.17这类任意小数,它们会导致可见的间隙。

CSG (Union / Subtract)

CSG(合并/减法)

The Epsilon Rule

微小偏移规则(Epsilon Rule)

Cutters MUST slightly overlap boundaries they cut through. Coplanar surfaces cause Z-fighting or leave microscopic skins.
luau
local EPSILON = 0.05

-- Hole through a 1-stud thick wall
local wall = Instance.new("Part")
wall.Size = Vector3.new(10, 10, 1)

local cutter = Instance.new("Part")
-- Add EPSILON*2 to the axis passing through the wall
cutter.Size = Vector3.new(2, 2, 1 + EPSILON * 2)
cutter.CFrame = wall.CFrame
切割部件必须与要切割的边界轻微重叠。共面表面会导致Z轴冲突或留下微小的残留面。
luau
local EPSILON = 0.05

-- 在1 stud厚的墙上开孔
local wall = Instance.new("Part")
wall.Size = Vector3.new(10, 10, 1)

local cutter = Instance.new("Part")
-- 向穿过墙壁的轴添加EPSILON*2的尺寸
cutter.Size = Vector3.new(2, 2, 1 + EPSILON * 2)
cutter.CFrame = wall.CFrame

Safe CSG Wrapper

安全CSG包装器

CSG operations are async and can fail. Always pcall, verify, and clean up.
luau
local success, result = pcall(function()
    return basePart:SubtractAsync({cutterPart})
end)

if success and result and result:IsA("BasePart") then
    result.CFrame = basePart.CFrame -- preserve exact transform
    result.UsePartColor = true
    result.Color = basePart.Color
    result.Material = basePart.Material
    result.Name = basePart.Name
    result.Anchored = true
    result.Parent = basePart.Parent

    basePart:Destroy()
    cutterPart:Destroy()
else
    warn("CSG failed:", result)
    cutterPart:Destroy()
end
CSG操作是异步的,可能会失败。始终使用pcall、验证并清理。
luau
local success, result = pcall(function()
    return basePart:SubtractAsync({cutterPart})
end)

if success and result and result:IsA("BasePart") then
    result.CFrame = basePart.CFrame -- 保留精确变换
    result.UsePartColor = true
    result.Color = basePart.Color
    result.Material = basePart.Material
    result.Name = basePart.Name
    result.Anchored = true
    result.Parent = basePart.Parent

    basePart:Destroy()
    cutterPart:Destroy()
else
    warn("CSG failed:", result)
    cutterPart:Destroy()
end

CSG Rules

CSG规则

  • Keep CSG trees shallow. Don't subtract from a part that was already unioned multiple times.
  • Perform complex CSG near origin (0,0,0), then PivotTo() the final model to its destination. Floating-point precision degrades far from origin.
  • GeometryService only supports Part and PartOperation. NOT MeshPart or Terrain.
  • Set
    CollisionFidelity = Enum.CollisionFidelity.Box
    on decorative unions for performance.
  • 保持CSG树结构浅。不要对已经多次合并的部件执行减法操作。
  • 在原点(0,0,0)附近执行复杂的CSG操作,然后使用PivotTo()将最终模型移动到目标位置。远离原点时浮点精度会下降。
  • GeometryService仅支持Part和PartOperation。不支持MeshPart或Terrain。
  • 为装饰性合并部件设置
    CollisionFidelity = Enum.CollisionFidelity.Box
    以提升性能。

Platform Quirks

平台特性

Cylinder Orientation

圆柱体方向

Cylinders extend along the X-axis by default. To stand one upright:
luau
local pillar = Instance.new("Part")
pillar.Shape = Enum.PartType.Cylinder
pillar.Size = Vector3.new(10, 2, 2) -- Length, Diameter, Diameter
pillar.CFrame = CFrame.new(0, 5, 0) * CFrame.Angles(0, 0, math.pi / 2)
圆柱体默认沿X轴延伸。要使其直立:
luau
local pillar = Instance.new("Part")
pillar.Shape = Enum.PartType.Cylinder
pillar.Size = Vector3.new(10, 2, 2) -- 长度,直径,直径
pillar.CFrame = CFrame.new(0, 5, 0) * CFrame.Angles(0, 0, math.pi / 2)

WedgePart Orientation

WedgePart方向

The zero-height edge (tip) points toward +Z by default.
Desired tip directionRotation
Up (+Y)
CFrame.Angles(-math.pi/2, 0, 0)
Down (-Y)
CFrame.Angles(math.pi/2, 0, 0)
Forward (+Z)none
Backward (-Z)
CFrame.Angles(math.pi, 0, 0)
零高度边缘(尖端)默认指向+Z方向。
期望尖端方向旋转角度
向上(+Y)
CFrame.Angles(-math.pi/2, 0, 0)
向下(-Y)
CFrame.Angles(math.pi/2, 0, 0)
向前(+Z)
向后(-Z)
CFrame.Angles(math.pi, 0, 0)

Neon Material

Neon材质

Neon glows visually but does NOT cast light on surroundings. Add a PointLight/SpotLight as a child for actual illumination.
Neon材质会发光,但不会对周围环境投射光线。需添加PointLight/SpotLight作为其子对象以实现实际照明。

Default Part Properties

默认部件属性

Always set explicitly:
  • Anchored = true
    (defaults to false!)
  • CanCollide = true
    (false for small decorative clutter)
  • CastShadow = true
    (false for invisible triggers)
始终显式设置:
  • Anchored = true
    (默认值为false!)
  • CanCollide = true
    (小型装饰杂物可设为false)
  • CastShadow = true
    (不可见触发器可设为false)

Anti-Patterns

反模式

  • Guessing coordinates — Read from workspace, don't rely on chat memory.
  • Unanchored parts — They fall. Always set Anchored = true.
  • Hardcoded world positions — Use relative offsets from anchor CFrame.
  • Block-only for organic shapes — Use CSG, Cylinders, Spheres, WedgeParts.
  • Silent CSG failures — Always pcall and verify result is BasePart.
  • Building everything in one call — Split by phase. 20-30 parts per call max.
  • Floating geometry — All structures must connect to ground or parent structure.
  • Default colors — Always set explicit Color and Material. Default gray = unfinished.
  • 猜测坐标 — 从workspace读取,不要依赖聊天记忆。
  • 未锚定部件 — 它们会掉落。始终设置Anchored = true。
  • 硬编码世界位置 — 使用相对于锚定CFrame的偏移量。
  • 仅用方块构建有机形状 — 使用CSG、圆柱体、球体、WedgePart。
  • CSG失败无提示 — 始终使用pcall并验证结果是否为BasePart。
  • 一次调用构建所有内容 — 按阶段拆分。每次调用最多20-30个部件。
  • 悬空几何结构 — 所有结构必须连接到地面或父结构。
  • 默认颜色 — 始终设置明确的Color和Material。默认灰色代表未完成。

Validation Script

验证脚本

Run after building to catch common issues:
luau
local TARGET = "MyBuild" -- change to your model/folder name
local root = workspace:FindFirstChild(TARGET)
if not root then print("[ERROR] " .. TARGET .. " not found"); return end

local errors, warnings, parts = 0, 0, 0
for _, desc in ipairs(root:GetDescendants()) do
    if desc:IsA("BasePart") then
        parts += 1
        if not desc.Anchored then
            print("[ERROR] " .. desc:GetFullName() .. " not Anchored")
            errors += 1
        end
        if desc.Position.Y - desc.Size.Y / 2 < -0.5 then
            print("[WARN] " .. desc.Name .. " below floor")
            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/material")
            warnings += 1
        end
    end
end
print(string.format("Parts: %d | Errors: %d | Warnings: %d", parts, errors, warnings))
If any errors: fix and re-verify. Warnings are advisory.
构建完成后运行以捕获常见问题:
luau
local TARGET = "MyBuild" -- 改为你的模型/文件夹名称
local root = workspace:FindFirstChild(TARGET)
if not root then print("[ERROR] " .. TARGET .. " not found"); return end

local errors, warnings, parts = 0, 0, 0
for _, desc in ipairs(root:GetDescendants()) do
    if desc:IsA("BasePart") then
        parts += 1
        if not desc.Anchored then
            print("[ERROR] " .. desc:GetFullName() .. " not Anchored")
            errors += 1
        end
        if desc.Position.Y - desc.Size.Y / 2 < -0.5 then
            print("[WARN] " .. desc.Name .. " below floor")
            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/material")
            warnings += 1
        end
    end
end
print(string.format("Parts: %d | Errors: %d | Warnings: %d", parts, errors, warnings))
如果有任何错误:修复后重新验证。警告为建议性内容。

Map Folder Structure

地图文件夹结构

workspace/
  MapName/                  (Folder)
    Origin                  (invisible anchor at 0,0,0)
    Terrain/                (ground planes)
    Zone_Spawn/
      Floor
      Walls/
      Props/
    Zone_Arena/
    Landmarks/
    Lighting/               (PointLights, SpotLights)
    Spawns/                 (SpawnLocation instances)
workspace/
  MapName/                  (Folder)
    Origin                  (位于0,0,0的不可见锚点)
    Terrain/                (地面平面)
    Zone_Spawn/
      Floor
      Walls/
      Props/
    Zone_Arena/
    Landmarks/
    Lighting/               (PointLights, SpotLights)
    Spawns/                 (SpawnLocation实例)