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」を押して、エディター画面に以下のような地形が生成されれば成功です。

2500個のキューブをひとつのメッシュに結合
解説
スクリプトの修正について
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

MeshSaverの導入
メッシュの保存
「Ctrl+P」を押して、Unityエディター上に地形を生成し、地形をクリックで選択します。

地形を選択
選択中のオブジェクトの「Ground(Mesh Filter)」コンポーネントのオプションの中から「Save Mesh」を選択します。

Save Mesh
メッシュの保存先を指定します(ここではGround.Assetとして保存します)。

メッシュの保存先を指定
結果確認
一旦Unityエディタを停止し、Groundオブジェクトを選択後、 Cube(Mesh Filter)のMeshプロパティ指定ボタンをクリックします。

Meshプロパティを開く
先ほど保存した「Ground.Asset」を選択すると、Unityエディター上に地形メッシュが表示されます。
Unityエディターが停止中でもメッシュが表示できていれば成功です。

保存した地形メッシュを指定する
保存したメッシュのPrefab化とアップロード
準備
Prefab化するゲームオブジェクトの作成
Prefabにするキューブをひとつ作成します。

Prefabにするキューブ
作成したキューブを選択し、以下の2点を修正します。
- Cube(Mesh Filter)コンポーネントのMeshプロパティを「Ground」に変更する
- Mesh RendererコンポーネントのMaterialプロパティを「terrain 6.26.56 PM」に変更する

メッシュとマテリアルを変更する
ゲームオブジェクトのPrefab化
作成したオブジェクトをPrefabsフォルダにドラッグアンドドロップします。

キューブをPrefab化する
PrefabのSTYLYへのアップロード
PrefabをSTYLYにアップロードするには、アカウントの設定やプラグインのインストール等の準備が必要です。
詳細は以下のリンク先を参照してください。
結果確認
STYLYエディターのMyModelsフォルダを見ると、アップロードしたPrefabが選択可能です。

アップロードしたPrefabの確認
最後に、デフォルトの地形表示をOFF→Cubeの表示位置を調整すれば、完成です。
本記事通りの手順で作成した地形であれば、X:-25、Y:-7.5、Z:-25で以下のように配置可能です。

STYLYに取り込んだマインクラフト風の地形
まとめ
以上、マインクラフト風の地形を作りSTYLYへアップロードする方法の紹介でした。
ここからさらに、 TiltBrushで洞窟や動物や植物を描いてみたり、 花火を上げてみたり、スーパーボールを爆発させてみたり、 STYLYで解説されてきた様々なアセットを組み合わせることで、さらに面白い世界が作れると思います。
Minecraft 公式製品ではありません。Mojang から承認されておらず、Mojang とは関係ありません。

