平らなサーフェスを表現するために、Unity にはシーンでインスタンス化できる Plane (平面) と Quad (クアッド) という プリミティブなゲームオブジェクト が含まれています。ただし、スクリプトを使用して自分で四辺形メッシュを作成する方法を理解しておくと役立ちます。これは手続き型のメッシュの生成に不可欠です。
ノート: Unity はジオメトリを処理して、四角形ではなく三角形で表示します。これは、クアッドのプリミティブが 2 つの三角形から成ることを意味します。
まず最初に、形状が使用する頂点の配列を設定します。
この例では、クアッドが x 軸と y 軸にあり、スクリプトに width (幅) と height (高さ) の変数が含まれていると仮定しています。
Vector3[] vertices = new Vector3[4]
{
new Vector3(0, 0, 0),
new Vector3(width, 0, 0),
new Vector3(0, height, 0),
new Vector3(width, height, 0)
};
mesh.vertices = vertices;
この例は、以下の順序で頂点を供給しています。 Bottom-left Bottom-right Top-left Top-right
Unity が Mesh データのプロパティを取得する方法ゆえに、独自の配列にデータを設定し、配列をプロパティ (例えば、Mesh.vertices
や Mesh.normals
) に割り当てる方が、個々の要素によってプロパティ配列にアクセスするよりはるかに効率的です。
次に、三角形を設定する必要があります。クアッドは、それぞれが以前に作成した頂点配列の 3 つの点で構成される 2 つの三角形で構成されます。点を指定するには、各三角形を頂点配列の 3 つのインデックスとして定義します。例えば、このクアッドの左下の三角形は、頂点配列座標 (0, 0, 0)、(0, height, 0)、(width, 0, 0) に対応するインデックス 0、2、1 を使用します。コーナーは右回りに並べる必要があるため、順序は重要です。右上の三角形はインデックス 2、3、1 を使用します。
int[] tris = new int[6]
{
// 左下の三角形
0, 2, 1,
// 右上の三角形
2, 3, 1
};
mesh.triangles = tris;
頂点と三角形を持つメッシュはシーンに表示されますが、まだ法線がないため Unity は正しく処理できません。この例の法線は、すべて同一であるため単純です。すべての法線の点は、クアッドのローカル空間の負の Z 軸の向きを指します。法線を追加すると、Unity はクアッドを正しくシェーディングしますが、効果を表示するにはシーンにライトが必要です。
Vector3[] normals = new Vector3[4]
{
-Vector3.forward,
-Vector3.forward,
-Vector3.forward,
-Vector3.forward
};
mesh.normals = normals;
法線をご自分で定義しない場合は、Mesh.RecalculateNormals() を使用できます。
最後に、メッシュのマテリアルにテクスチャを正しく表示するには、メッシュにテクスチャ座標を加えます。 テクスチャ座標は 0 と 1 の間です。メッシュの各頂点は、マテリアルのテクスチャのどこからサンプルするかを指定するテクスチャ座標を持っています。クアッド全体のテクスチャすべてを表示するには、各頂点のテクスチャ座標値をすべて 0 または 1 にして、クアッドの各角がテクスチャの角に対応するようにします。
Vector2[] uv = new Vector2[4]
{
new Vector2(0, 0),
new Vector2(1, 0),
new Vector2(0, 1),
new Vector2(1, 1)
};
mesh.uv = uv;
下のスクリプトは、上記のすべてを組み合わせて、シーンにクアッドを作成します。使用するには、以下のようにします。まず、新しい C# スクリプトを作成し (Assets > Create > C# Script)、QuadCreator という名前を付けます。QuadCreator スクリプトを開き、サンプルコードをコピーして、スクリプトを保存します。エディターに戻り、シーンに新しいゲームオブジェクトを作成します (GameObject > Create Empty)。インスペクターで、Add Component > Scripts > Quad Creator を選択します。シーン内の好きな場所にそのゲームオブジェクトを配置します。再生モードにします。シーンビューまたはゲームビューにクアッドが表示されない場合は、正しい側から表示していることを確認してください。Unity は、このメッシュの背面をレンダリングしません。
using UnityEngine;
public class QuadCreator : MonoBehaviour
{
public float width = 1;
public float height = 1;
public void Start()
{
MeshRenderer meshRenderer = gameObject.AddComponent<MeshRenderer>();
meshRenderer.sharedMaterial = new Material(Shader.Find("Standard"));
MeshFilter meshFilter = gameObject.AddComponent<MeshFilter>();
Mesh mesh = new Mesh();
Vector3[] vertices = new Vector3[4]
{
new Vector3(0, 0, 0),
new Vector3(width, 0, 0),
new Vector3(0, height, 0),
new Vector3(width, height, 0)
};
mesh.vertices = vertices;
int[] tris = new int[6]
{
// 左下の三角形
0, 2, 1,
// 右上の三角形
2, 3, 1
};
mesh.triangles = tris;
Vector3[] normals = new Vector3[4]
{
-Vector3.forward,
-Vector3.forward,
-Vector3.forward,
-Vector3.forward
};
mesh.normals = normals;
Vector2[] uv = new Vector2[4]
{
new Vector2(0, 0),
new Vector2(1, 0),
new Vector2(0, 1),
new Vector2(1, 1)
};
mesh.uv = uv;
meshFilter.mesh = mesh;
}
}
ノート: このサンプルコードは Start 関数内にあります。つまり、再生モードに入ると 1 回実行され、メッシュはアプリケーション全体で変更されません。ただし、Update 関数にコードを加えて、メッシュをフレームごとに変更することができます。これにより、メッシュ生成のリソースの負担が大幅に増加することに注意してください。