roblox-world-building について
Roblox 開発者向けのコードによるワールド構築ガイドです。シーン、ライティング、地形、プロシージャルモデル、実行時エフェクトを扱い、性能と安全面の注意点も説明します。
主な機能
- 01Part と Model の作成・整理
- 02ライティングと昼夜サイクルの設定
- 03地形の生成と編集
- 04GeometryService によるジオメトリ操作
- 05プロシージャルモデルと実行時メッシュの構築
- 06パーティクル、ビームなどの追加
活用シーン
- 01Luau で静的なシーンを構築
- 02シード付きのプロシージャル地形を生成
- 03破壊可能な壁や破砕エフェクトを実装
- 04実行時にメッシュや画像を編集
MCP 対応
Studio MCP の `generate_procedural_model` を使って ProceduralModel を生成できると説明しています。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ el4cteo/ roblox-skills --skill roblox-world-buildingインストール後、Claude Code で/roblox-world-buildingを入力して読み込まれたか確認します。
詳細
コードを使ったワールド構築
パーツとモデル
--!strict
local function makePart(size: Vector3, cframe: CFrame, props: { [string]: any }?): Part
local part = Instance.new("Part")
part.Anchored = true
part.Size = size
part.CFrame = cframe
part.TopSurface = Enum.SurfaceType.Smooth
part.BottomSurface = Enum.SurfaceType.Smooth
for key, value in props or {} do
(part :: any)[key] = value
end
return part -- caller sets Parent last
end
local floor = makePart(Vector3.new(64, 1, 64), CFrame.new(0, 0, 0), {
Material = Enum.Material.Slate,
Color = Color3.fromRGB(90, 90, 100),
})
local model = Instance.new("Model")
model.Name = "Arena"
floor.Parent = model
model.WorldPivot = floor.CFrame
model.Parent = workspace
model:PivotTo(CFrame.new(0, 10, 0) * CFrame.Angles(0, math.rad(45), 0))
- プロパティを先に設定し、親は最後に設定します(レプリケーション/物理演算の挿入を1回に抑えます)。静的なジオメトリは固定します。
PivotTo/GetPivotでモデルを移動・回転します。Model.WorldPivot/PrimaryPartでピボットを定義します。- 論理的に関連するパーツは、巨大なコンテナではなくModelにまとめます(ストリーミング、LOD、
ModelStreamingMode)。 - 装飾用パーツでは、
CanCollide/CanTouch/CanQuery = falseにし、小さなディテールではCastShadow = falseにします。 - マテリアル:
Enum.Material.*を使用します。MaterialServiceのMaterialVariant(part.MaterialVariant = "Name"を設定)またはMeshPart上のSurfaceAppearance(PBR)でカスタムの見た目を実現できます。Decal.TextureはColorMapContentに置き換えられています。 - 同一のメッシュを多数使う場合は低コストです(インスタンス化されます)。固有のメッシュやユニオンを多数使う場合は低コストではありません。
ライティング
| プロパティ | 指針 |
|---|---|
Lighting.LightingStyle | 自然な表現にはRealistic、スタイライズされた表現にはSoftを使用します。廃止されたLighting.Technologyに代わるものです。 |
Lighting.PrioritizeLightingQuality | 低性能デバイスでのパフォーマンスより、品質(例:Softでのシャドウマップ)を優先します。 |
ClockTime / GeographicLatitude | 太陽の位置を設定します。昼夜の切り替えにはClockTimeをアニメーションさせます。 |
Brightness、ExposureCompensation、Ambient/OutdoorAmbient | 全体的な露出とフィルライトを設定します。 |
EnvironmentDiffuseScale/EnvironmentSpecularScale | スカイボックスがライティングと反射に与える影響を設定します。 |
| 子要素 | Atmosphere(霧の代わりとなる霞・密度)、Sky、Clouds(Terrain内)、BloomEffect、ColorCorrectionEffect、ColorGradingEffect、DepthOfFieldEffect、SunRaysEffect、BlurEffect。 |
--!strict
-- Server: smooth day/night cycle (one full day every 20 minutes).
local Lighting = game:GetService("Lighting")
local RunService = game:GetService("RunService")
local DAY_LENGTH_SECONDS = 20 * 60
RunService.Heartbeat:Connect(function(deltaTime)
Lighting.ClockTime = (Lighting.ClockTime + deltaTime * 24 / DAY_LENGTH_SECONDS) % 24
end)
フレームごとの視覚的な変更では、各クライアントでworkspace:GetServerTimeNow()を使ってClockTimeを計算する方法がおすすめです(レプリケーションの通信が発生せず、完全に滑らかです)。ローカルライトにはPointLight、SpotLight、SurfaceLightを使い、Shadows = trueにするものは少数にします。
Terrain
--!strict
local terrain = workspace.Terrain
terrain:FillBlock(CFrame.new(0, -10, 0), Vector3.new(512, 20, 512), Enum.Material.Grass)
terrain:FillBall(Vector3.new(0, 0, 0), 24, Enum.Material.Air) -- carve a crater
terrain:FillBlock(CFrame.new(40, -2, 0), Vector3.new(30, 4, 30), Enum.Material.Water)
terrain:FillCylinder(CFrame.new(-40, 5, 0), 20, 8, Enum.Material.Rock)
- 大規模な生成:
:ExpandToGrid(4)に合わせたRegion3を作成し、マテリアル/占有率の配列とReadVoxels/WriteVoxelsを使って、チャンク単位で処理します。チャンク間では処理を譲ります(4スタッドのボクセル)。 terrain:Clear()でクリアします。水の見た目はTerrain.WaterColor、WaterWaveSizeなどで設定します。- プロシージャルなハイトマップ:オクターブを使って
math.noise(x * scale, z * scale, seed)をサンプリングします。再現性のあるワールドにはRandom.new(seed)を使います。サーバー上で生成するか、負荷の高い計算にはParallel Luauを使います。
ゲーム内のソリッドモデリングと破壊(GeometryService)
--!strict
local GeometryService = game:GetService("GeometryService")
-- Punch a hole through a wall (e.g. explosions, building games).
local function carve(wall: BasePart, cutter: BasePart): { Instance }?
local ok, results = pcall(function()
return GeometryService:SubtractAsync(wall, { cutter }, {
CollisionFidelity = Enum.CollisionFidelity.Default,
RenderFidelity = Enum.RenderFidelity.Automatic,
SplitApart = true, -- disconnected pieces become separate parts
})
end)
if not ok or not results then
return nil
end
for _, piece in results do
if piece:IsA("BasePart") then
piece.Anchored = wall.Anchored
piece.Parent = wall.Parent
end
end
wall:Destroy()
return results
end
return carve
UnionAsync、IntersectAsync、SubtractAsyncは親が設定されていない新しいパーツを返します。FragmentAsync(part, sites)はGenerateFragmentSitesで生成した点を使ってパーツを破砕します(ボロノイ分割)。SweepPartAsyncはパーツをCFrameに沿って押し出します。CalculateConstraintsToPreserveは、パーツの置き換え時に溶接や拘束を維持します。- 処理コストが高いため、サーバー上で実行し、レートを制限して、破片をプール化またはクリーンアップします。
ProceduralModel(パラメーター駆動型モデル)
ProceduralModelインスタンスは、Attributes(パラメーター)とOnGenerate(params, targetContainer)を公開するジェネレーターModuleScriptから内容を再生成します。編集時(元に戻す/やり直す、Team Create)と実行時の両方で動作します。Studio、Assistant、またはStudio MCP(generate_procedural_model)から生成できます。Creator Storeのプロシージャルモデルは自動的にサンドボックス化されます。
実行時のメッシュと画像
AssetService:CreateEditableMesh()/CreateEditableMeshAsync(content)およびCreateEditableImageを使うと、実行時にジオメトリとピクセルを編集できます(変形可能なTerrainチャンク、ペイント、カスタムアバターなど)。公開済みのゲームでは、オーナーがID確認済みの13歳以上であり、Creator DashboardでEnable Mesh / Image APIsを有効にしている必要があります。クライアントのメモリ予算には厳しい制限があります。読み込めるのは、ゲームのオーナーが所有するアセット、またはゲームのオーナーと共有されているアセットのみです。AssetService:CreateMeshPartAsync(Content.fromObject(editableMesh))で表示します。頂点や面が多数ある場合は、要素ごとの呼び出しではなく、EditableMeshのバッチAPIと並列クエリ(公開済みのライブゲームで利用可能)を使用します。
エフェクト
ParticleEmitter(バーストには:Emit(n)を使用)、Beam(アタッチメント間。レーザーやロープ)、Trail(剣、発射物)、Highlight(アウトライン/塗りつぶし。数に制限あり)、Explosion(物理を誘発します — 見た目のみにするにはDestroyJointRadiusPercent = 0とBlastPressure = 0を設定します)。- 装飾的なエフェクトはクライアント側で生成し、破棄またはプールしてください(
Debris:AddItem(obj, seconds)で問題ありません)。
関連スキル
roblox-performance(レンダリングコスト、ストリーミング)、roblox-architecture(ストリーミング設定)、
roblox-studio-mcp(MCP 経由で Studio 内に構築)、roblox-physics(コンストレイント、破壊物理)。