【Unity】UVをスクリプトで設定する

投稿者: | 2021-02-14

メッシュをスクリプトで生成するときに、UVも設定してみました。

UVは中央に配置されるように十字形に展開して、左右にしか余白ができないようにしました。

スクリプトでは、Mesh.uvにVector2の配列を設定します。これには同じインデックスの頂点のUV座標が入っているので、要素数は頂点の配列と同じです。

また、直方体のメッシュの縦・横・高さをインスペクタで自由に設定するので、UVの辺が3つのうちどれかを確認しました。

例えば、頂点0のU座標は、M + Wにスケールを含めたものです。縦に余白を作らないなら、W + H + W + H で割ると良いと思います。

float scale = (height + width) * 2f;

UVが横長になった場合は、横にはみ出ます。

なので、実際は縦横を比較して計算方法を変えたほうがいいかもしれません。

また、これと M + W + L + W + Mが同じ長さになるときの余白(スケール前)を計算しました。横にはみ出たときはマイナスになります。

float marginX = height - length / 2f;

これらを使って、縦横高さが1のときの、頂点0~3のUVを計算しました。

// 頂点の配列
var vertices = new Vector3[24];

// uvの配列
var uvs = new Vector2[vertices.Length];

float scale = (height + width) * 2f;
float marginX = height - length / 2f;

uvs[0] = new Vector2(marginX + width, height * 2 + width) / scale;
uvs[1] = new Vector2(marginX + width, height * 2 + width * 2) / scale;
uvs[2] = new Vector2(marginX + width + length, height * 2 + width * 2) / scale;
uvs[3] = new Vector2(marginX + width + length, height * 2 + width) / scale;

for (int i = 0; i < 4; i++)
{
    Debug.Log(i + ": " + uvs[i].ToString("F3"));
}

このように、すべての頂点のUV座標を、上の図を見ながら設定しました。

using UnityEngine;

public class MeshTest : MonoBehaviour
{

    [SerializeField] float width;
    [SerializeField] float length;
    [SerializeField] float height;
    [SerializeField] Material material;

    // Start is called before the first frame update
    void Start()
    {

        // 頂点の配列
        var vertices = new Vector3[24];

        // 三角形の配列
        var tri = new int[36];

        // uvの配列
        var uvs = new Vector2[vertices.Length];

        float scale = (height + width) * 2f;
        float marginX = height - length / 2f;

        // Y
        vertices[0] = new Vector3(-length / 2, height / 2, -width / 2);
        vertices[1] = new Vector3(-length / 2, height / 2, width / 2);
        vertices[2] = new Vector3(length / 2, height / 2, width / 2);
        vertices[3] = new Vector3(length / 2, height / 2, -width / 2);

        tri[0] = 0;
        tri[1] = 1;
        tri[2] = 2;

        tri[3] = 2;
        tri[4] = 3;
        tri[5] = 0;

        uvs[0] = new Vector2(marginX + width, height * 2 + width) / scale;
        uvs[1] = new Vector2(marginX + width, height * 2 + width * 2) / scale;
        uvs[2] = new Vector2(marginX + width + length, height * 2 + width * 2) / scale;
        uvs[3] = new Vector2(marginX + width + length, height * 2 + width) / scale;


        // -Y
        vertices[4] = new Vector3(-length / 2, -height / 2, -width / 2);
        vertices[5] = new Vector3(length / 2, -height / 2, -width / 2);
        vertices[6] = new Vector3(length / 2, -height / 2, width / 2);
        vertices[7] = new Vector3(-length / 2, -height / 2, width / 2);

        tri[6] = 4;
        tri[7] = 5;
        tri[8] = 6;

        tri[9] = 6;
        tri[10] = 7;
        tri[11] = 4;

        uvs[4] = new Vector2(marginX + width, height + width) / scale;
        uvs[5] = new Vector2(marginX + width + length, height + width) / scale;
        uvs[6] = new Vector2(marginX + width + length, height) / scale;
        uvs[7] = new Vector2(marginX + width, height) / scale;

        // X
        vertices[8] = new Vector3(length / 2, height / 2, -width / 2);
        vertices[9] = new Vector3(length / 2, height / 2, width / 2);
        vertices[10] = new Vector3(length / 2, -height / 2, width / 2);
        vertices[11] = new Vector3(length / 2, -height / 2, -width / 2);

        tri[12] = 8;
        tri[13] = 9;
        tri[14] = 10;

        tri[15] = 10;
        tri[16] = 11;
        tri[17] = 8;

        uvs[8] = new Vector2(marginX + width + length, height * 2 + width) / scale;
        uvs[9] = new Vector2(marginX + width * 2 + length, height * 2 + width) / scale;
        uvs[10] = new Vector2(marginX + width * 2 + length, height + width) / scale;
        uvs[11] = new Vector2(marginX + width + length, height + width) / scale;

        // -X
        vertices[12] = new Vector3(-length / 2, height / 2, width / 2);
        vertices[13] = new Vector3(-length / 2, height / 2, -width / 2);
        vertices[14] = new Vector3(-length / 2, -height / 2, -width / 2);
        vertices[15] = new Vector3(-length / 2, -height / 2, width / 2);

        tri[18] = 12;
        tri[19] = 13;
        tri[20] = 14;

        tri[21] = 14;
        tri[22] = 15;
        tri[23] = 12;

        uvs[12] = new Vector2(marginX, height * 2 + width) / scale;
        uvs[13] = new Vector2(marginX + width, height * 2 + width) / scale;
        uvs[14] = new Vector2(marginX + width, height + width) / scale;
        uvs[15] = new Vector2(marginX, height + width) / scale;

        //Z
        vertices[16] = new Vector3(length / 2, height / 2, width / 2);
        vertices[17] = new Vector3(-length / 2, height / 2, width / 2);
        vertices[18] = new Vector3(-length / 2, -height / 2, width / 2);
        vertices[19] = new Vector3(length / 2, -height / 2, width / 2);

        tri[24] = 16;
        tri[25] = 17;
        tri[26] = 18;

        tri[27] = 18;
        tri[28] = 19;
        tri[29] = 16;

        uvs[16] = new Vector2(marginX + width + length, 0f) / scale;
        uvs[17] = new Vector2(marginX + width, 0f) / scale;
        uvs[18] = new Vector2(marginX + width, height) / scale;
        uvs[19] = new Vector2(marginX + width + length, height) / scale;

        // -Z
        vertices[20] = new Vector3(-length / 2, height / 2, -width / 2);
        vertices[21] = new Vector3(length / 2, height / 2, -width / 2);
        vertices[22] = new Vector3(length / 2, -height / 2, -width / 2);
        vertices[23] = new Vector3(-length / 2, -height / 2, -width / 2);

        tri[30] = 20;
        tri[31] = 21;
        tri[32] = 22;

        tri[33] = 22;
        tri[34] = 23;
        tri[35] = 20;

        uvs[20] = new Vector2(marginX + width, height * 2 + width) / scale;
        uvs[21] = new Vector2(marginX + width + length, height * 2 + width) / scale;
        uvs[22] = new Vector2(marginX + width + length, height + width) / scale;
        uvs[23] = new Vector2(marginX + width, height + width) / scale;

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

        // 頂点と面、UVの配列を設定
        mesh.vertices = vertices;
        mesh.triangles = tri;
        mesh.uv = uvs;

        // 法線を計算
        mesh.RecalculateNormals();

        // MeshFilterを付ける
        var mf = gameObject.AddComponent<MeshFilter>();

        // 作ったメッシュを設定
        mf.mesh = mesh;

        // MeshRendererを付ける
        var mr = gameObject.AddComponent<MeshRenderer>();

        // マテリアルを設定
        mr.material = material;

    }


}

これで、サイズを自由に変えても思ったようにUV展開されました。

コメントを残す

メールアドレスが公開されることはありません。