こんにちは、エンジニアのオオバです。
結論から話しますと、 3Dプログラミングの基礎は「三角形」 です。つまり 三角形を画面に映し出すことが3Dプログラミングの最初の第一歩 と言えます。
ここで言う「三角形」とは三角形メッシュのことを指しています。 Unity上で表示しているオブジェクトはすべて三角形のメッシュの塊 なのです。
つまりプログラミングでメッシュを作ることができれば表現の自由度が格段に上がります。
まずは最初の一歩。1つの三角形を画面に映し出してみましょう。すべてはここからです。
この記事は 3DプログラミングまたはUnity初心者向けに分かりやすく解説しています。 三角形を画面に表示し、3Dプログラミングの基礎を学ぶことができると思います。ぜひ、最後まで読んでみてください。
👉DOTweenの教科書を読んでUnityアニメーションをプログラミングしてみよう!
Unityのメッシュ(Mesh)とは
最初にメッシュについて簡単に解説します。
メッシュとは 複数の頂点を結んだ面 です。頂点とはその名のとおり「点」で、3D空間上に配置されX、Y、Z軸の座標で表現されます。
2つの頂点で結んだものを辺、3点以上を結ぶと面、つまりメッシュになります。つまり、 メッシュを作るためには最低でも3つの頂点が必要 だということです。
みなさんが普段目にする3Dには 「色」 が付いていますよね。単色の場合もあれば、 「画像」 が貼り付けられているパターンもあるでしょう。または光を受けて 「陰影」 をつけていることもあります。
これらは頂点の情報やライト・画像、シェーダーを使って表現しています。
自分が作りたいメッシュを表現するためには、さまざまな知識が必要になるというわけです。 この記事はその最初の一歩。最小単位の三角形メッシュを作っていきます。
ちなみにシェーダーとは 「ディスプレイに映し出すためのプログラム」 です。次の記事ではシェーダーの基礎について分かりやすく解説しています。なんとなくの概念を理解することは学習において重要です。ぜひ読んでみてください。
Unityプログラミングで三角形メッシュを作る4つの手順
早速、具体的な作業の解説に入ります。Unityで三角形メッシュを作る手順はたったの4つです。
①Meshインスタンスの作成
②頂点座標データをMeshにセット
③頂点の順番データをMeshにセット
④メッシュの描画処理
【準備】 描画する三角形の仕様の確認
3Dプログラミングに入る前に三角形の仕様を確認しましょう。三角形を作るためには3つの頂点が必要です。以下の座標の頂点を作り、つなげるのです。
- 座標1(0, 1, 0)
- 座標2(1, -1, 0)
- 座標3(-1, -1, 0)
上の図のとおり「1辺2メートル」の三角形メッシュを作ります。
三角形を描画する方法はいくつかありますが、今回は最もシンプルでわかりやすい 「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」を代入しておいてください。今回は不要なパラメーターのため説明は割愛します。
頂点を結ぶ順番は重要
インデックス配列の数値は頂点を結ぶ順番です。 インデックスの値と頂点情報は結びつきます。
- インデックス0番とは・・座標(0, 1f, 0)の頂点のこと
- インデックス1番とは・・座標(1f, -1f, 0)の頂点のこと
- インデックス2番とは・・座標(-1f, -1f, 0)の頂点のこと
インデックス配列はメッシュを正しく表示させるためにとても重要な情報です。
今回は三角形のため、どんな順番でも正しく表示されます が、複雑なメッシュを表現するためには必須の知識です。
Unityは時計回りに頂点を結んだ面が「前」です。 メッシュには前と後ろが存在します。シェーダーの設定(カリング)がデフォルトであれば、前面にメッシュが表示されるのです。前面とは法線(面の向き)のこと。
・メッシュが表示されない
・表示がおかしい
このようなトラブルが発生した場合は、この頂点を結ぶ「インデックス配列」または「シェーダー」を見直すと良いでしょう。
頂点座標配列、インデックス配列をMeshにセットできました。これで準備は完了。これからメッシュをモニタに映し出す作業に移ります。
④メッシュの描画処理
Unityでメッシュを表示するためにはレンダラーが必要 です。レンダラーとはメッシュを表示するためのコンポーネントで、Unityでは2種類のレンダラーが提供されています。
コンポーネント名 | 内容 |
---|---|
MeshRenderer | 頂点が動かないメッシュ |
SkinnedMeshRenderer | 頂点を動かすメッシュ |
2つの違いは 頂点が個別に動くかどうか です。布やキャラクタのような個別に頂点が動く場合は
SkinnedMeshRenderer(スキンメッシュレンダラー) を使います。
このように頂点が動くメッシュには「SkinnedMeshRenderer」を使うのです。↑ちなみにこのキャラクターアニメーションはRunner Action Animation Packです。さまざまな走る人型アニメーションが格納されて便利です。
そして、今回は表示したいメッシュは、シンプルな三角形メッシュ1つ。もちろん動きません。だからMeshRenderer を使います。
GameObjectにMeshRendererをAddComponent
メニュー Component > Mesh > Mesh Renderer
からMeshRendererをGameObjectにアタッチしましょう。
上図のように MeshRenderer をAddComponentしておきます。
MeshRendererにMeshインスタンスを渡して描画したいところですが、Unityではその前に1手間必要です。
MeshFilterがMeshRendererにMeshを渡す
Meshインスタンスは MeshFilterコンポーネント によって、MeshRendererにMeshが渡されます。つまり開発者がMeshを受け渡す先はMeshRendererではなく、MeshFilterなのです。
メニュー Component > Mesh > Mesh Filter
からMeshFilterをGameObjectにアタッチします。 上図のようにMeshRendererがセットされたGameObjectに MeshFilter も一緒にアタッチしてされていることを確認しましょう。
↓MeshインスタンスをMeshFilterにわたすコードはこちらです。
💻ソースコード : MeshFilterにメッシュをセット
var filter = GetComponent<MeshFilter> ();
filter.sharedMesh = mesh;
MeshFilterのsharedMeshプロパティにMeshインスタンスを渡します。すると、Unity実行時にMeshFilterはMeshRendererにMeshが渡されます。
この段階ではピンク色のになってしまいますが、無事に三角形がモニタ上に表示されました!おめでとうございます。3Dプログラミングを始めることができましたね。
ソースコード全文は記事終盤「サンプルコードの共有と補足解説」に記載していますので、ぜひ参考にしてみてください。
プログラミングでメッシュ(Mesh)を作る方法まとめ
今回は3Dプログラミングの最初の一歩として、Unityプログラミングで三角形メッシュを作ってみました。記事の内容を簡単にまとめます。
- 「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すると、自動でに MeshRenderer 、 MeshFilter が同じGameObjectにAddComponentするということです。
👉 【保存版】Unityのコンポーネント徹底解説【Unity基礎】
メッシュ描画に2つのコンポーネントが必要でしたね。 MeshRenderer と MeshFilter です。AddComponentのし忘れを防止するトラブル回避の工夫ということです。
今回の記事は以上です。次回はこの三角形に色を塗っていきます。↓ぜひ読んでみてください。
この記事が気に入ったらフォローしよう
「Unity初心者大学」というUnity初心者向けのYouTube始めました!!
ぜひチャンネル登録をお願いします!
最後まで読んでいただきありがとうございました!
すばらしい3Dプログラミングライフをお過ごしください。
- Unity2020.3.31f1
- ビルトインレンダーパイプライン