Unityでマインクラフト風の地形を作り、STYLYへアップロードするまでの手順を解説します。
本記事は以下の続きです。
前回までのまとめ
前編では地形の見た目を作成したので、後編はSTYLYにアップロードし公開するための仕上げ作業になります。
仕上げ作業は以下の3ステップで進めます。
- メッシュの結合によるパフォーマンスの改善
- 自動生成したメッシュの保存
- 保存したメッシュのPrefab化とアップロード
それでは、上記の手順を詳しく説明します。
メッシュの結合によるパフォーマンスの改善
準備
地形生成スクリプトの修正
「VoxelGround.cs」を以下のように修正します。
using UnityEngine; public class VoxelGround : MonoBehaviour { private float sizeX = 50f; private float sizeY = 10f; private float sizeZ = 50f; private float sizeW = 17f; private void Awake() { var material = this.GetComponent<MeshRenderer>().material; for (float x = 0; x < sizeX; x++) { for (float z = 0; z < sizeZ; z++) { GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube); cube.transform.SetParent(transform); cube.GetComponent<MeshRenderer>().material = material; float noise = Mathf.PerlinNoise(x / sizeW, z / sizeW); float y = Mathf.Round(sizeY * noise); cube.transform.localPosition = new Vector3(x, y, z); SetUV(cube); } } Combine(); transform.localPosition = new Vector3(-sizeX / 2, 0, -sizeZ / 2); } private void SetUV(GameObject cube) { cube.GetComponent<MeshFilter>().mesh.uv = GetBlockUVs(2, 15); if (cube.transform.position.y > sizeY * 0.3f) { cube.GetComponent<MeshFilter>().mesh.uv = GetBlockUVs(0, 15); //山 } else if (cube.transform.position.y > sizeY * 0.2f) { cube.GetComponent<MeshFilter>().mesh.uv = GetBlockUVs(1, 2); //水面 } else if (cube.transform.position.y > sizeY * 0.1f) { cube.GetComponent<MeshFilter>().mesh.uv = GetBlockUVs(15, 0); //溶岩 } } private Vector2[] GetBlockUVs(float tileX, float tileY) { float pixelSize = 16; float tilePerc = 1 / pixelSize; float umin = tilePerc * tileX; float umax = tilePerc * (tileX + 1); float vmin = tilePerc * tileY; float vmax = tilePerc * (tileY + 1); Vector2[] blockUVs = new Vector2[24]; //-X blockUVs[2] = new Vector2(umax, vmax); blockUVs[3] = new Vector2(umin, vmax); blockUVs[0] = new Vector2(umax, vmin); blockUVs[1] = new Vector2(umin, vmin); //+Y blockUVs[4] = new Vector2(umin, vmin); blockUVs[5] = new Vector2(umax, vmin); blockUVs[8] = new Vector2(umin, vmax); blockUVs[9] = new Vector2(umax, vmax); //-Z blockUVs[23] = new Vector2(umax, vmin); blockUVs[21] = new Vector2(umin, vmax); blockUVs[20] = new Vector2(umin, vmin); blockUVs[22] = new Vector2(umax, vmax); //+Z blockUVs[19] = new Vector2(umax, vmin); blockUVs[17] = new Vector2(umin, vmax); blockUVs[16] = new Vector2(umin, vmin); blockUVs[18] = new Vector2(umax, vmax); //-Y blockUVs[15] = new Vector2(umax, vmin); blockUVs[13] = new Vector2(umin, vmax); blockUVs[12] = new Vector2(umin, vmin); blockUVs[14] = new Vector2(umax, vmax); //+X blockUVs[6] = new Vector2(umin, vmin); blockUVs[7] = new Vector2(umax, vmin); blockUVs[10] = new Vector2(umin, vmax); blockUVs[11] = new Vector2(umax, vmax); return blockUVs; } private void Combine() { //メッシュ統合 MeshFilter[] meshFilters = GetComponentsInChildren<MeshFilter>(); CombineInstance[] combine = new CombineInstance[meshFilters.Length]; int i = 0; while (i < meshFilters.Length) { combine[i].mesh = meshFilters[i].sharedMesh; combine[i].transform = meshFilters[i].transform.localToWorldMatrix; meshFilters[i].gameObject.SetActive(false); i++; } transform.GetComponent<MeshFilter>().mesh = new Mesh(); transform.GetComponent<MeshFilter>().mesh.CombineMeshes(combine, true); transform.gameObject.SetActive(true); } }
結果確認
「Ctrl+P」を押して、エディター画面に以下のような地形が生成されれば成功です。
解説
スクリプトの修正について
private void Combine() { //メッシュ結合 MeshFilter[] meshFilters = GetComponentsInChildren<MeshFilter>(); //Groundオブジェクト配下にできたキューブのメッシュ CombineInstance[] combine = new CombineInstance[meshFilters.Length]; //結合するメッシュを格納用する配列 int i = 0; while (i < meshFilters.Length) { combine[i].mesh = meshFilters[i].sharedMesh; //各キューブのメッシュを結合用メッシュにコピーする combine[i].transform = meshFilters[i].transform.localToWorldMatrix; //各キューブの座標を結合用メッシュにコピーする meshFilters[i].gameObject.SetActive(false); //不要になったキューブオブジェクトを無効化しておく i++; } transform.GetComponent<MeshFilter>().mesh = new Mesh(); //Groundオブジェクトに新規メッシュを作成 transform.GetComponent<MeshFilter>().mesh.CombineMeshes(combine, true); //メッシュを結合する transform.gameObject.SetActive(true); //Groundオブジェクトを有効化する }
ここでは生成した2500個のキューブのメッシュをひとつに結合します。
実装内容の詳細はコメントに記入した通りです。
上記スクリプトにより、2500個のキューブオブジェクトをひとつのオブジェクトに統合します。
自動生成したメッシュの保存
準備
MeshSaverの導入
以下のリポジトリからMeshSaverというツールを導入します。
Unity-MeshSaver
取込ステップは簡単に3ステップ
- スクリプトフォルダ内に「Editor」というフォルダーを作成します(注意:Editor以外の名前にすると、STYLYへのアップロードに失敗します)
- Editorフォルダ内にMeshSaverEditorという名前のスクリプトを作成します
- 以下のURLからソースコードをコピペします
MeshSaverEditor
メッシュの保存
「Ctrl+P」を押して、Unityエディター上に地形を生成し、地形をクリックで選択します。
選択中のオブジェクトの「Ground(Mesh Filter)」コンポーネントのオプションの中から「Save Mesh」を選択します。
メッシュの保存先を指定します(ここではGround.Assetとして保存します)。
結果確認
一旦Unityエディタを停止し、Groundオブジェクトを選択後、 Cube(Mesh Filter)のMeshプロパティ指定ボタンをクリックします。
先ほど保存した「Ground.Asset」を選択すると、Unityエディター上に地形メッシュが表示されます。
Unityエディターが停止中でもメッシュが表示できていれば成功です。
保存したメッシュのPrefab化とアップロード
準備
Prefab化するゲームオブジェクトの作成
Prefabにするキューブをひとつ作成します。
作成したキューブを選択し、以下の2点を修正します。
- Cube(Mesh Filter)コンポーネントのMeshプロパティを「Ground」に変更する
- Mesh RendererコンポーネントのMaterialプロパティを「terrain 6.26.56 PM」に変更する
ゲームオブジェクトのPrefab化
作成したオブジェクトをPrefabsフォルダにドラッグアンドドロップします。
PrefabのSTYLYへのアップロード
PrefabをSTYLYにアップロードするには、アカウントの設定やプラグインのインストール等の準備が必要です。
詳細は以下のリンク先を参照してください。
結果確認
STYLYエディターのMyModelsフォルダを見ると、アップロードしたPrefabが選択可能です。
最後に、デフォルトの地形表示をOFF→Cubeの表示位置を調整すれば、完成です。
本記事通りの手順で作成した地形であれば、X:-25、Y:-7.5、Z:-25で以下のように配置可能です。
まとめ
以上、マインクラフト風の地形を作りSTYLYへアップロードする方法の紹介でした。
ここからさらに、 TiltBrushで洞窟や動物や植物を描いてみたり、 花火を上げてみたり、スーパーボールを爆発させてみたり、 STYLYで解説されてきた様々なアセットを組み合わせることで、さらに面白い世界が作れると思います。
Minecraft 公式製品ではありません。Mojang から承認されておらず、Mojang とは関係ありません。