渋谷ほととぎす通信

「Unityをわかりやすく」初心者のためのゲーム作りブログ

Unityで3Dプログラミング基礎!三角形メッシュ(Mesh)の作り方

Unityで3Dプログラミング基礎!三角形メッシュ(Mesh)の作り方

こんにちは、エンジニアのオオバです。

お悩みさん
お悩みさん
  • 3Dプログラミングを始めたい
  • 3Dプログラミングの基礎って何?
  • Unityでメッシュを作ってみたい
  • オオバ
    オオバ
    本記事ではこれらの悩みを解決します。

    結論から話しますと、 3Dプログラミングの基礎は「三角形」 です。つまり 三角形を画面に映し出すことが3Dプログラミングの最初の第一歩 と言えます。

    ここで言う「三角形」とは三角形メッシュのことを指しています。 Unity上で表示しているオブジェクトはすべて三角形のメッシュの塊 なのです。
    つまりプログラミングでメッシュを作ることができれば表現の自由度が格段に上がります。

    まずは最初の一歩。1つの三角形を画面に映し出してみましょう。すべてはここからです。
    この記事は 3DプログラミングまたはUnity初心者向けに分かりやすく解説しています。 三角形を画面に表示し、3Dプログラミングの基礎を学ぶことができると思います。ぜひ、最後まで読んでみてください。

    👉DOTweenの教科書を読んでUnityアニメーションをプログラミングしてみよう!

    Unityのメッシュ(Mesh)とは

    最初にメッシュについて簡単に解説します。

    メッシュとは 複数の頂点を結んだ面 です。頂点とはその名のとおり「点」で、3D空間上に配置されX、Y、Z軸の座標で表現されます。

    2つの頂点で結んだものを辺、3点以上を結ぶと面、つまりメッシュになります。つまり、 メッシュを作るためには最低でも3つの頂点が必要 だということです。

    みなさんが普段目にする3Dには 「色」 が付いていますよね。単色の場合もあれば、 「画像」 が貼り付けられているパターンもあるでしょう。または光を受けて 「陰影」 をつけていることもあります。
    これらは頂点の情報やライト・画像、シェーダーを使って表現しています。

    自分が作りたいメッシュを表現するためには、さまざまな知識が必要になるというわけです。 この記事はその最初の一歩。最小単位の三角形メッシュを作っていきます。

    ちなみにシェーダーとは 「ディスプレイに映し出すためのプログラム」 です。次の記事ではシェーダーの基礎について分かりやすく解説しています。なんとなくの概念を理解することは学習において重要です。ぜひ読んでみてください。

    Unityプログラミングで三角形メッシュを作る4つの手順

    早速、具体的な作業の解説に入ります。Unityで三角形メッシュを作る手順はたったの4つです。

    Unityプログラミングで三角形メッシュを作る4つの手順

    ①Meshインスタンスの作成

    ②頂点座標データをMeshにセット

    ③頂点の順番データをMeshにセット

    ④メッシュの描画処理

    【準備】 描画する三角形の仕様の確認

    3Dプログラミングに入る前に三角形の仕様を確認しましょう。三角形を作るためには3つの頂点が必要です。以下の座標の頂点を作り、つなげるのです。

    • 座標1(0, 1, 0)
    • 座標2(1, -1, 0)
    • 座標3(-1, -1, 0)

    Unityで3Dプログラミング基礎!三角形メッシュ(Mesh)の作り方_0

    上の図のとおり「1辺2メートル」の三角形メッシュを作ります。

    ※Unityの単位は1メートル

    三角形を描画する方法はいくつかありますが、今回は最もシンプルでわかりやすい 「1つの三角形に1つのGameObjectを使う方法」 を採用します。

    👉 【Unity基礎】GameObjectの使い方(生成や削除など)全て解説

    では実際に三角形メッシュを作っていきましょう。

    Unityの単位は「1メートル」です。X座標が1だったら、それは1メートルという意味になります。
    ゲーム開発で単位を理解しておくことは実は重要で、 理解しておくことでトラブルを回避できるケースは多い です。次の記事ではUnityの単位について解説しています。ぜひ読んでみてください。

    手順①Meshインスタンスの作成

    まず最初にやるべきことは、Meshインスタンスの作成です。UnityではMeshクラスを使ってメッシュを作ります。

    Meshインスタンスの作成は 「newキーワード」 を使います。

    💻ソースコード : Meshインスタンスの作成
    // Meshインスタンスの作成  
    var mesh = new Mesh();  
    

    このように作成した Mesh に「頂点座標の配列(Vector3型の配列)」と「頂点順番の配列 (int型の配列)」の情報をセットしていきます。

    ②頂点座標データをMeshにセット

    三角形を構成する頂点数は3つ。この3点の頂点座標をMeshインスタンスにセットします。3D空間上の座標のため、頂点座標はVector3型(x, y, z)で定義。

    また3つの頂点なので「Vector3型の配列」を使います。

    MeshクラスSetVerticesメソッド で頂点座標の配列をセットします。

    💻ソースコード : 頂点座標配列をメッシュにセット
    mesh.SetVertices(  
        new Vector3[]{  
          new Vector3 (0, 1f, 0),  
          new Vector3 (1f, -1f, 0),  
          new Vector3 (-1f, -1f, 0),  
        }
    );  
    

    Meshに渡す頂点座標配列は GameObjectを原点にしたローカル座標 であることに注意してください。今回使用するサンプルコード全文は記事の後半で公開しています。

    Meshクラスの vertices プロパティも同様の処理を実装できますが、 パフォーマンスの観点でSetVerticesの使用をおすすめ します。

    ③頂点の順番データをMeshにセット

    メッシュは頂点をつないで面になります。つまり 3Dプログラミングでは「つなぐ頂点の順番」を指示する必要がある のです。

    頂点の順番とは「0、1、2」といった数字。番号が小さい順の頂点からつないでいきます。
    Meshクラスの SetTrianglesメソッド を使いましょう。

    頂点の順番を インデックス(Index) と呼び、頂点順番の配列を「インデックス配列」と呼ばれます。覚えておきましょう。

    ではMeshインスタンスにインデックス配列をセットしていきます。3頂点しかないため、使用する数字は0から2番までです。数字は0始まりであることに注意しましょう。

    💻ソースコード : インデックス配列をメッシュにセット
    mesh.SetTriangles(  
      // インデックス配列をセット  
      new int[] { 0, 1, 2 }, 0  
    );  
    

    SetTrianglesを使って「手順①Meshインスタンスの作成」で作成したMeshインスタンスにインデックス配列をセット。SetTrianglesの第2引数は「0」を代入しておいてください。今回は不要なパラメーターのため説明は割愛します。

    頂点を結ぶ順番は重要

    インデックス配列の数値は頂点を結ぶ順番です。 インデックスの値と頂点情報は結びつきます。

    Unityで3Dプログラミング基礎!三角形メッシュ(Mesh)の作り方_1

    • インデックス0番とは・・座標(0, 1f, 0)の頂点のこと
    • インデックス1番とは・・座標(1f, -1f, 0)の頂点のこと
    • インデックス2番とは・・座標(-1f, -1f, 0)の頂点のこと

    インデックス配列はメッシュを正しく表示させるためにとても重要な情報です。
    今回は三角形のため、どんな順番でも正しく表示されます が、複雑なメッシュを表現するためには必須の知識です。

    メッシュには前と後ろがある

    Unityは時計回りに頂点を結んだ面が「前」です。 メッシュには前と後ろが存在します。シェーダーの設定(カリング)がデフォルトであれば、前面にメッシュが表示されるのです。前面とは法線(面の向き)のこと。

    ・メッシュが表示されない

    ・表示がおかしい

    このようなトラブルが発生した場合は、この頂点を結ぶ「インデックス配列」または「シェーダー」を見直すと良いでしょう。

    👉 【Unity】プログラミングで球メッシュを作る方法

    頂点座標配列、インデックス配列をMeshにセットできました。これで準備は完了。これからメッシュをモニタに映し出す作業に移ります。

    ④メッシュの描画処理

    Unityでメッシュを表示するためにはレンダラーが必要 です。レンダラーとはメッシュを表示するためのコンポーネントで、Unityでは2種類のレンダラーが提供されています。

    コンポーネント名内容
    MeshRenderer頂点が動かないメッシュ
    SkinnedMeshRenderer頂点を動かすメッシュ

    2つの違いは 頂点が個別に動くかどうか です。布やキャラクタのような個別に頂点が動く場合は
    SkinnedMeshRenderer(スキンメッシュレンダラー) を使います。

    SkinnedMeshRendererを使用している例

    Unityで3Dプログラミング基礎!三角形メッシュ(Mesh)の作り方_2

    このように頂点が動くメッシュには「SkinnedMeshRenderer」を使うのです。↑ちなみにこのキャラクターアニメーションはRunner Action Animation Packです。さまざまな走る人型アニメーションが格納されて便利です。

    そして、今回は表示したいメッシュは、シンプルな三角形メッシュ1つ。もちろん動きません。だからMeshRenderer を使います。

    GameObjectにMeshRendererをAddComponent

    Unityで3Dプログラミング基礎!三角形メッシュ(Mesh)の作り方_3

    メニュー Component > Mesh > Mesh Renderer からMeshRendererをGameObjectにアタッチしましょう。

    Unityで3Dプログラミング基礎!三角形メッシュ(Mesh)の作り方_4

    上図のように MeshRenderer をAddComponentしておきます。

    MeshRendererにMeshインスタンスを渡して描画したいところですが、Unityではその前に1手間必要です。

    MeshFilterがMeshRendererにMeshを渡す

    Unityで3Dプログラミング基礎!三角形メッシュ(Mesh)の作り方_5

    Meshインスタンスは MeshFilterコンポーネント によって、MeshRendererにMeshが渡されます。つまり開発者がMeshを受け渡す先はMeshRendererではなく、MeshFilterなのです。

    Unityで3Dプログラミング基礎!三角形メッシュ(Mesh)の作り方_6

    メニュー Component > Mesh > Mesh Filter からMeshFilterをGameObjectにアタッチします。

    Unityで3Dプログラミング基礎!三角形メッシュ(Mesh)の作り方_7

    上図のようにMeshRendererがセットされたGameObjectに MeshFilter も一緒にアタッチしてされていることを確認しましょう。

    ↓MeshインスタンスをMeshFilterにわたすコードはこちらです。

    💻ソースコード : MeshFilterにメッシュをセット
    var filter = GetComponent<MeshFilter> ();  
    filter.sharedMesh = mesh;  
    

    MeshFilterのsharedMeshプロパティにMeshインスタンスを渡します。すると、Unity実行時にMeshFilterはMeshRendererにMeshが渡されます。

    【完成】三角形メッシュの描画

    Unityで3Dプログラミング基礎!三角形メッシュ(Mesh)の作り方_8

    この段階ではピンク色のになってしまいますが、無事に三角形がモニタ上に表示されました!おめでとうございます。3Dプログラミングを始めることができましたね。

    ソースコード全文は記事終盤「サンプルコードの共有と補足解説」に記載していますので、ぜひ参考にしてみてください。

    プログラミングでメッシュ(Mesh)を作る方法まとめ

    今回は3Dプログラミングの最初の一歩として、Unityプログラミングで三角形メッシュを作ってみました。記事の内容を簡単にまとめます。

    プログラミングでメッシュ(Mesh)を作る方法まとめ
    • 「new Mesh()」でMeshインスタンスを作成
    • Meshに頂点座標配列を「SetVerticesメソッド」でセット
    • Meshにインデックス配列を「SetTrianglesメソッド」でセット
    • 開発者はMeshFilterにMeshを渡す
    • MeshRendererでMeshを描画

    こんな感じです。コードは全部覚えられなくても メッシュを描画する流れ必要な情報のイメージ ができると良いでしょう。

    この基本をしっかり頭に叩き込むことが大事です。メッシュ描画のイメージができると 3Dプログラミングの幅は広がります

    次回はこの三角形に色を塗ります。簡単なシェーダーが出てきますのでお楽しみに。

    シェーダー学習の第一歩としても良いと思います。

    サンプルコードの共有と補足解説

    最後にソースコード全体を共有します。

    💻ソースコード : 三角形メッシュの生成ソース全体 DynamicCreateMesh.cs
    using UnityEngine;  
    
    // 補足説明  
    [RequireComponent(typeof(MeshRenderer))]  
    [RequireComponent(typeof(MeshFilter))]  
    public class DynamicCreateMesh : MonoBehaviour  
    {
        private void Start()  
        {
            // メッシュの作成  
            var mesh = new Mesh();  
    
            // 頂点座標配列をメッシュにセット  
            mesh.SetVertices(new Vector3[] {  
                new Vector3 (0, 1f),  
                new Vector3 (1f, -1f),  
                new Vector3 (-1f, -1f),  
            });  
    
            // インデックス配列をメッシュにセット  
            mesh.SetTriangles(new int[] {  
                0, 1, 2  
            }, 0);  
    
            // MeshFilterを通してメッシュをMeshRendererにセット  
            var filter = GetComponent<MeshFilter>();  
            filter.sharedMesh = mesh;  
        }
    }
    

    今回紹介しなかった処理について補足解説します。

    補足:事故防止のRequireComponent

    クラス定義の前に RequireComponentアトリビュート をセットしています。アトリビュートとは属性という意味で、C#では []を使って記述されたものを指します。

    RequireComponentアトリビュートとは何かというと、コンポーネントがAddComponentされたときに自動でアタッチしてくれるコンポーネントの指定です。

    [RequireComponent (typeof(MeshRenderer))]  
    [RequireComponent (typeof(MeshFilter))]  
    public class DynamicCreateMesh : MonoBehaviour  
    

    上記のコードは具体的には DynamicCreateMesh をGameObjectにAddComponentすると、自動でに MeshRendererMeshFilter が同じGameObjectにAddComponentするということです。

    👉 【保存版】Unityのコンポーネント徹底解説【Unity基礎】

    メッシュ描画に2つのコンポーネントが必要でしたね。 MeshRendererMeshFilter です。AddComponentのし忘れを防止するトラブル回避の工夫ということです。

    今回の記事は以上です。次回はこの三角形に色を塗っていきます。↓ぜひ読んでみてください。

    「Unity初心者大学」というUnity初心者向けのYouTube始めました!!
    ぜひチャンネル登録をお願いします!

    最後まで読んでいただきありがとうございました!
    すばらしい3Dプログラミングライフをお過ごしください。

    オススメ記事
    検証環境
    • Unity2020.3.31f1
    • ビルトインレンダーパイプライン