world について
3Dゲーム開発者向けのワールド構築スキルです。地形、距離感、環境の密度、スケール、描画の仕上げを扱い、フレームレートに配慮しながら一貫性のある広い空間を作る指針を示します。
主な機能
- 01移動方法に応じたワールドサイズの選定
- 02一貫したノイズによる地形形成
- 03地平線、霧、遠景の設定
- 04InstancedMeshによる反復オブジェクトの配置
- 05スケールの維持と描画の仕上げ
活用シーン
- 01広大な屋外ゲームマップの構築
- 02距離感の演出による描画範囲端の隠蔽
- 03反復する小道具の効率的な配置
- 04地形の形状に合わせた衝突判定の設定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ drawcall-ai/ skills --skill worldインストール後、Claude Code で/worldを入力して読み込まれたか確認します。
詳細
ワールドのスケールと距離
ワールドが小さく感じられる原因は、修正可能なものが3つあります。物理的に小さいこと、目に見える端で終わっていること、遠くに何もないことです。「大きなマップ」とは、あらゆる地平線上に何かがある数百メートル規模のマップを意味します。何もない空間の先に広がる150mほどの区画ではありません。
体験に合わせたサイズ
プレイヤーの移動方法を基準にワールドのサイズを決めます。1分ほど走って横断する三人称視点のシューティングゲームのマップなら、幅はおよそ300〜1000mで、約150mではありません。ポイント・オブ・インタレストは、間を移動するのに実際に時間がかかる程度の距離を空けて配置します。
地形に起伏をつける
屋外の地面が平坦なことはほとんどありません。テクスチャのない灰色の地面に次いで、平面は「未完成のプロトタイプ」だと最もわかりやすく感じさせます。地形に本物の起伏をつけます。細分化した平面の頂点をレイヤー化したノイズで変位させて丘、斜面、谷を作るか、高さマップから生成します。ノイズには連続性が必要です。頂点ごとにMath.random()を使うと、丘ではなくギザギザしたノイズになります。Three.jsにはノイズ関数が組み込まれていないため、simplex-noiseパッケージを追加し、複数のオクターブを合成します(各オクターブで振幅を半分、周波数を2倍にします)。こうすると、大きな丘に小さな起伏を加えられます。尾根、盆地、高台など、見てわかるランドマークを作り、戦術的な変化を空間に持たせます。その後、geometry.computeVertexNormals()を呼び出して、ライティングが地形の形状に沿うようにします。コリジョンとナビメッシュは、下にある別の平坦な床ではなく、起伏をつけた地形に合わせます。
地形もほかの面と同様に、単色ではなく適切なマテリアルが必要です(materialsスキルを参照)。タイル状の地面テクスチャを適用します。大きなマップでは、傾斜と標高に応じてブレンドし(平地には草、急斜面には岩や崖、海岸には砂)、マップ全体が平坦な緑のシートのように見えないようにします。
ワールドに奥行きを持たせる
目は奥行きの手がかりからスケールを読み取ります。ワールドが端ではなく地平線まで続いて見えるよう、次の3つをすべて用意します。
- 地平線: スカイボックスや環境背景、または遠くの地形のシルエットを配置し、地面がくっきりした線で途切れないようにします。
- フォグ:
scene.fog = new Fog(skyColor, near, far)を設定し、遠くのジオメトリが空に溶け込むよう調整します。これにより奥行きが生まれると同時に、描画距離の端を隠せます。フォグの色は空の色に合わせます。 - 遠景のディテール: プレイヤーが見られるものの、たどり着くことはないかもしれない、大きな背景の地形、尾根、構造物を配置します。
何も突然現れないように、カメラのfar面はフォグの遠距離より先に設定し、深度精度を保つためにnearは妥当な値(例:0.1)にします。
フレームレートを落とさずに配置する
密度がワールドに信憑性を与えます。少数の小道具の間に何もない地面が広がっていると、プロトタイプのように見えます。草の茂み、岩、低木、瓦礫などの細かなディテールを地形全体に密に散らし、小道具は均等に点在させるのではなく、場所(前哨基地や木立など)にまとめて配置します。単純に複製するとフレームレートが低下するため、繰り返し配置するディテールにはInstancedMeshを使います。
読み込んだ小道具が単一のメッシュであることはほとんどありません。glTFでは1つのモデルが階層として表現され、複数のマテリアルを持つパーツ(木の幹と葉、岩の石部分と苔など)は、プリミティブごとに分かれた複数のメッシュとして読み込まれます。InstancedMeshでインスタンス化できるのはジオメトリとマテリアルのペアです。そのため、最初に見つかったメッシュを取得してインスタンス化すると、ほかのプリミティブがすべて気づかないうちに抜け落ち、木ではなく幹だけが散らばってしまいます。それぞれのプリミティブを別のInstancedMeshでインスタンス化し、すべてに同じインスタンスごとの変換を使うか、モデルのプリミティブを先に1つのジオメトリに統合します。THREE.LODは距離に応じてオブジェクト全体を切り替えるもので、インスタンスごとには動作しない点に注意してください。そのため、インスタンスをLODで囲むのではなく、遠くのインスタンスを省くか、近距離用と遠距離用のインスタンスプールを分けるなどして、自分で距離によるカリングを行います。
スケールを統一する
キャラクターの身長(約1.8m)を基準に、すべてをメートル単位で作成します。プレイヤーと同じ大きさの木や、家ほどの大きさの木箱は、ほかの何よりも早く場所の感覚を損ないます。
画像を仕上げる
正しいジオメトリをそのままレンダリングしただけでは、まだ平坦に見えます。軽いポストプロセス(控えめなブルーム、オブジェクトに接地感を与えるアンビエントオクルージョン、穏やかなカラーグレーディング(postprocessing スキルを参照))を加えるだけで、「洗練されたゲーム」と「技術デモ」の違いが生まれることがよくあります。シーンが正しく見えるようになってから追加し、先に追加しないでください。