なごるふ

UnityとかArduinoとか気になったことを

【Unity】Editor拡張から3DモデルのMeshデータを作成する

複雑なモデルを作成する場合、MayaやMaxのような3D制作ソフトを使うことが多いと思いますが、ちょっとしたモデルはUnityのEditor拡張から作れると便利です。

Mesh新規生成と保存

新規生成するだけであれば、以下のコードで作成できます。

MeshのAsset拡張子は.meshになります。

// 新規メッシュを作成.
var mesh = new Mesh();

// アセットとして保存.
AssetDatabase.CreateAsset(mesh, "Assets/sample.mesh");

// Editor更新.
AssetDatabase.Refresh();

これだと保存先のパスに同名のアセットが存在する場合、別のアセットファイルとして上書き保存されてしまうため、参照が外れる原因になります。

そのため、更新まで考慮すると「アセットが存在する場合:更新」「存在しない場合:新規生成」の2つの処理が必要です。

Meshの取得と新規生成

var isNew = false;

// 既存アセットの取得.
var mesh = AssetDatabase.LoadAssetAtPath<Mesh>("Assets/sample.mesh");
if (mesh != null)
{
    // ある場合はMeshを一度クリア.
    mesh.Clear();
}
else
{
    // ない場合は新規作成.
    mesh = new Mesh();
    isNew = true;
}

Meshの更新と保存

// 新規の場合は生成.
if (isNew)
{
    AssetDatabase.CreateAsset(mesh, "Assets/sample.mesh");
}
else
{
    // 更新の場合は変更を保存.
    AssetDatabase.SaveAssets();
}

// Editor更新.
AssetDatabase.Refresh();

Meshの頂点情報を作成

頂点座標と三角形を作るための頂点のindex番号を用意すれば最低限のモデルが作成できます。

var vertices = new List<Vector3>();
var triangles = new List<int>();

// 頂点座標.
vertices.Add(new Vector3(-1f, -1f, 0f));
vertices.Add(new Vector3(-1f,  1f, 0f));
vertices.Add(new Vector3( 1f,  1f, 0f));

// index.
triangles.Add(0);
triangles.Add(1);
triangles.Add(2);

// Meshに頂点情報を設定.
mesh.SetVertices(vertices);
mesh.SetTriangles(triangles, 0);

コード

最後にコード全文です。

Project View上で右クリックからCreateMeshを選択するとMeshが生成されます。

public class MeshCreator
{
    // メッシュ保存先.
    private const string MeshPath = "Assets/sample.mesh";

    [MenuItem("Assets/CreateMesh")]
    private static void CreateMesh()
    {
        var isNew = false;

        // 既存アセットの取得.
        var mesh = AssetDatabase.LoadAssetAtPath<Mesh>(MeshPath);
        if (mesh != null)
        {
            // ある場合はMeshを一度クリア.
            mesh.Clear();
        }
        else
        {
            // ない場合は新規作成.
            mesh = new Mesh();
            isNew = true;
        }

        var vertices = new List<Vector3>();
        var triangles = new List<int>();

        vertices.Add(new Vector3(-1f, -1f, 0f));
        vertices.Add(new Vector3(-1f,  1f, 0f));
        vertices.Add(new Vector3( 1f,  1f, 0f));

        triangles.Add(0);
        triangles.Add(1);
        triangles.Add(2);

        mesh.SetVertices(vertices);
        mesh.SetTriangles(triangles, 0);

        // 新規の場合は生成.
        if (isNew)
        {
            AssetDatabase.CreateAsset(mesh, MeshPath);
        }
        else
        {
            // 更新の場合は変更を保存.
            AssetDatabase.SaveAssets();
        }

        // Editor更新.
        AssetDatabase.Refresh();
    }
}