おもちゃラボ

Unityで遊びを作ってます

【Unity】四角形のポリゴンを作ってテクスチャを貼る

UnityにはPlaneなど、板ポリ用のポリゴンが用意されています。大概の場合はこれらのポリゴンを利用すれば十分ですが、ゲーム実行時に動的にポリゴンを作りたい場合にはスクリプトから作ることもできます。

ここではスクリプトを使って四角形のポリゴンを作成し、そこにテクスチャを貼る方法を紹介したいと思います。想像よりかは面倒だと思います(笑)ただ、応用すれば(そして、頑張れば・・・)板ポリゴンだけでなく、3Dモデルも作れるようになったりします。

四角形のポリゴンを作るのに必要な事前知識

御存知のとおり、ゲームで使う3Dモデルの最小単位は三角形のポリゴンです。四角形ポリゴンを書く場合も三角形のポリゴンを2つ描くことになります。

f:id:nn_hokuson:20180213185922p:plain:w300

ポリゴンを描くために必要な情報は次の3つです。

  • 頂点座標
  • UV座標
  • インデックス

頂点座標

ひとつ目の頂点座標は名前の通りポリゴンに使われている頂点の座標です。この頂点座標を頂点数ぶん配列で用意します。四角形なら4個ですね。

UV座標

ふたつ目UV座標はテクスチャの座標になります。頂点ごとにテクスチャのどの部分を使うかをテクスチャ座標(UV座標)を使って指定します。UV座標は0〜1の範囲で指定します。こちらも頂点数ぶん必要になります。

f:id:nn_hokuson:20180213194517p:plain:w400

ちなみに・・・モデルはキイロイトリです。北海道の雪の上で撮影しました(笑)

インデックス

最後のインデックスは聞き慣れないかもしれません(OpenGLやWebGL、DirectXなどを使っていた方にはおなじみですが・・・)頂点配列の何番目のデータを使ってポリゴンを描くかを指定します。

四角形を描く場合、三角形ごとに頂点座標を指定した場合、指定しなければいけない頂点座標は6点必要になります。

f:id:nn_hokuson:20180213190042p:plain:w400

2頂点ぶんはデータがかぶってしまいますね。これではメモリの無駄遣いなので、頂点配列は4頂点ぶんだけ用意して、その中の何番目のデータを使用するかだけを指定する方式がよく使われます。この使用する頂点データの番号をインデックスとして指定します。

f:id:nn_hokuson:20180213190104p:plain:w500

四角形のポリゴンを作成する

まずは四角形ポリゴンを描画するためのGameObjectを作りましょう。ヒエラルキーウインドウからCreate→Empty Objectを選択して空のゲームオブジェクトを作ります。名前はQuadに変更しておきましょう。

f:id:nn_hokuson:20180213190122p:plain:w300

Unityでポリゴンを表示するためにはMesh FilterとMesh Rendererコンポーネントが必要になります。インスペクタからAdd Componentでこれらのコンポーネントを追加してください。

f:id:nn_hokuson:20180213190133p:plain:w420

続いて四角形ポリゴンを動的に生成するためのスクリプトを作成しましょう。プロジェクトウィンドウで右クリックしてCreate→Script→C# Scriptを選択し、ファイル名をQuadGen.csに変更しましょう。

スクリプトファイルが作成できたら、次のスクリプトを入力してください。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Quad : MonoBehaviour 
{
    public Material mat;

    void Start () 
    {
    Mesh mesh = new Mesh ();
    mesh.vertices = new Vector3[] {
        new Vector3 (-1.2f, -1.2f, 0),
        new Vector3 (-1.2f,  1.2f, 0),       
        new Vector3 (1.2f , -1.2f, 0),
        new Vector3 (1.2f ,  1.2f, 0),
    };

    mesh.uv = new Vector2[] {
        new Vector2 (0, 0),
        new Vector2 (0, 1),
        new Vector2 (1, 0),              
        new Vector2 (1, 1),
    };

    mesh.triangles = new int[] {
        0, 1, 2, 
        1, 3, 2,
    };
    GetComponent<MeshFilter> ().sharedMesh = mesh;
    GetComponent<MeshRenderer> ().material = mat;
    }
}

このスクリプトでは頂点座標を格納するvertices配列、UV座標を格納するuv配列、インデックスを格納するindex配列を用意しています。

ここでは次のように(-1.2f,-1.2f)から(1.2f, 1.2f)まで、2.4m四方の正方形のポリゴンになるように座標を指定しています。ここでは、頂点座標は「左下」→「左上」→「右下」→「右上」の順番(ピンク色のインデックス)で宣言しています。

f:id:nn_hokuson:20180213190330p:plain:w300

uv配列には頂点座標と対応したUV座標を指定します。ここでは次のような対応になるようにUV座標を指定しました。UV座標の順番は各頂点の宣言の順番と対応するように「左下」→「左上」→「右下」→「右上」の順番で宣言していることに注意してください。

f:id:nn_hokuson:20180213191626j:plain:w300

またまた登場、キイロイトリ(笑)
[asin:B01LL52EI8:detail]


最後にインデックス配列です。今回は次のように2つの三角形を作ります。ひとつ目の三角形のインデックスは「0, 1, 2」、2つめの三角形のインデックスは「1, 3, 2」になります。

f:id:nn_hokuson:20180213195308p:plain:w300

ここでふたつ目の三角形のインデックスを「1,2,3」ではなく「1,3,2」としていることに注意してください。

インデックスは必ず「時計回り」になるように指定する必要があります。反時計回りで指定すると法線が逆向きのポリゴンが生成されて、表示されていないように見えてしまうので注意してください。

f:id:nn_hokuson:20180213190655p:plain:w500

最後に頂点座標・UV座標・インデックスの3つの情報をMeshオブジェクトにセットし、MeshFilterコンポーネントのshaderedMesh変数に登録しています。同時に表示するテクスチャのマテリアルも登録しています。

四角形のポリゴンを表示してみる

ここまでで四角形のポリゴンを作成するスクリプトができました。一旦動作を確認するために、QuadGen.csスクリプトをヒエラルキーウインドウのQuadにドラッグ&ドロップしてください。

f:id:nn_hokuson:20180213192614j:plain

実行すると次のようにピンク色の四角形が表示されると思います。これはまだテクスチャを指定していないことが原因です。

f:id:nn_hokuson:20180213192639p:plain:w350

テクスチャをセットして表示する

そこで、テクスチャを指定したマテリアルを作りましょう。プロジェクトウィンドウでCreate→Materialを選択し、インスペクタのShaderを「Unit/Texture」に変更して、使用するTextureをドラッグ&ドロップしてください。

f:id:nn_hokuson:20180213193013j:plain

最後に作成したテクスチャのマテリアルをQuadGen.csに指定します。ヒエラルキーウインドウでQuadを選択して、インスペクタからQuadGenスクリプトのmat欄を探します。そこに作成したテクスチャのマテリアルをドラッグ&ドロップしてください。

f:id:nn_hokuson:20180213193221j:plain

実行するとちゃんとテクスチャが表示されているのが確認できるはずです。

f:id:nn_hokuson:20180213193245p:plain:w350

キイロイトリ、めっちゃカワイイですね(もうええっちゅーねん)

[asin:B077WH3HBY:detail]

対策とまとめ

もしもうまく表示されていないときは・・・

  • UV座標の順番は頂点座標と対応しているか
  • インデックスの指定順序は正しいか
  • インデックスは時計回りに指定したか

などを確認してみてください。

今回はスクリプトを使って四角形の板ポリゴンを作成してみました。使う機会は多くないかもしれませんが、動的にポリゴンを作りたい場合に役に立つので覚えておきたいですね!