MRが楽しい

MRやVRについて学習したことを書き残す

Unityで面ごとにUVを設定したオブジェクトを作成する

本日は Unity の調査枠です。
Unityで面ごとにUVを設定したオブジェクトを作成する方法を確認したので記事に残します。

前回記事

本記事は以下の前回記事で調査した「面ごとにUVを設定したオブジェクト」の作成を Unity 内で行ってみた記事になります。
bluebirdofoz.hatenablog.com

Meshの動的作成

Mesh オブジェクトをスクリプトから作成する際の手順は以下の記事でも紹介しているので参考にしてください。
bluebirdofoz.hatenablog.com

面ごとにUVを設定したオブジェクトをMeshクラスで作成する

面ごとにUVを設定したオブジェクトをMeshクラスで作成するには面ごとに頂点を用意してUV座標の割り当てを行います。
このため、幾つか座標が重なる頂点が必要になります。

以下、前回記事で紹介した「面ごとにUVを設定したオブジェクト」を動的に作成するサンプルスクリプトです。
・UVMakeTest2.cs

using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class UVMakeTest2 : MonoBehaviour
{
    public Material setMaterial;

    void Start()
    {
        // メッシュを作成
        Mesh mesh = new Mesh();

        // 頂点リストを作成
        List<Vector3> vertices = new List<Vector3>
        {
            // Back方向の面
            new Vector3(0.5f, 0.0f, -0.5f),
            new Vector3(1.0f, 0.0f, -1.0f),
            new Vector3(-0.5f, 0.0f, -0.5f),
            new Vector3(-1.0f, 0.0f, -1.0f),
            
            // Right方向の面
            new Vector3(0.5f, 0.0f, 0.5f),
            new Vector3(1.0f, 0.0f, 1.0f),
            new Vector3(0.5f, 0.0f, -0.5f),
            new Vector3(1.0f, 0.0f, -1.0f),

            // Front方向の面
            new Vector3(-0.5f, 0.0f, 0.5f),
            new Vector3(-1.0f, 0.0f, 1.0f),
            new Vector3(0.5f, 0.0f, 0.5f),
            new Vector3(1.0f, 0.0f, 1.0f),

            // Left方向の面
            new Vector3(-0.5f, 0.0f, -0.5f),
            new Vector3(-1.0f, 0.0f, -1.0f),
            new Vector3(-0.5f, 0.0f, 0.5f),
            new Vector3(-1.0f, 0.0f, 1.0f),
        };

        // UV座標リストを作成
        List<Vector2> uvs = new List<Vector2>
        {
            // Back方向の面
            new Vector2(0.0f, 0.0f),
            new Vector2(0.0f, 1.0f),
            new Vector2(1.0f, 0.0f),
            new Vector2(1.0f, 1.0f),
            
            // Right方向の面
            new Vector2(0.0f, 0.0f),
            new Vector2(0.0f, 1.0f),
            new Vector2(1.0f, 0.0f),
            new Vector2(1.0f, 1.0f),
            
            // Front方向の面
            new Vector2(0.0f, 0.0f),
            new Vector2(0.0f, 1.0f),
            new Vector2(1.0f, 0.0f),
            new Vector2(1.0f, 1.0f),
            
            // Left方向の面
            new Vector2(0.0f, 0.0f),
            new Vector2(0.0f, 1.0f),
            new Vector2(1.0f, 0.0f),
            new Vector2(1.0f, 1.0f),
        };
        
        // 面を構成するインデックスリストを作成
        List<int> triangles = new List<int> {
            // Back方向の面
            0, 1, 2,
            1, 3, 2,
            
            // Right方向の面
            4, 5, 6,
            5, 7, 6,
            
            // Front方向の面
            8, 9, 10,
            9, 11, 10,
            
            // Left方向の面
            12, 13, 14,
            13, 15, 14,
        };

        // メッシュに頂点を登録する
        mesh.SetVertices(vertices);

        // メッシュにUV座標を登録する
        mesh.SetUVs(0, uvs);

        // メッシュに面を構成するインデックスリストを登録する
        mesh.SetTriangles(triangles, 0);

        // 作成したメッシュをメッシュフィルターに設定する
        MeshFilter meshFilter = this.AddComponent<MeshFilter>();
        meshFilter.mesh = mesh;
        
        // マテリアルを設定する
        MeshRenderer meshRenderer = this.AddComponent<MeshRenderer>();
        meshRenderer.material = setMaterial;
    }
}

コンポーネントをオブジェクトに設定してシーンを再生します。
以下のように Mesh オブジェクトが生成されます。

頂点が重ならないようにUVマップを展開したオブジェクトの場合

頂点が重ならないようにUVマップを展開したオブジェクトの場合のサンプルスクリプトも作成したので残しておきます。
先ほどのスクリプトと比べると、同じ形状ですが頂点数が減っていることが分かります。
・UVMakeTest.cs

using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class UVMakeTest : MonoBehaviour
{
    public Material setMaterial;

    void Start()
    {
        // メッシュを作成
        Mesh mesh = new Mesh();

        // 頂点リストを作成
        List<Vector3> vertices = new List<Vector3>
        {
            new Vector3(0.5f, 0.0f, -0.5f),
            new Vector3(1.0f, 0.0f, -1.0f),
            new Vector3(-0.5f, 0.0f, -0.5f),
            new Vector3(1.0f, 0.0f, 1.0f),
            new Vector3(-1.0f, 0.0f, -1.0f),
            new Vector3(0.5f, 0.0f, 0.5f),
            new Vector3(-0.5f, 0.0f, 0.5f),
            new Vector3(-1.0f, 0.0f, 1.0f),
        };

        // UV座標リストを作成
        List<Vector2> uvs = new List<Vector2>
        {
            new Vector2(0.25f, 0.75f),
            new Vector2(0.0f, 1.0f),
            new Vector2(0.75f, 0.75f),
            new Vector2(0.0f, 0.0f),
            new Vector2(1.0f, 1.0f),
            new Vector2(0.25f, 0.25f),
            new Vector2(0.75f, 0.25f),
            new Vector2(1.0f, 0.0f),
        };
        
        // 面を構成するインデックスリストを作成
        List<int> triangles = new List<int> {
            0, 1, 2,
            3, 1, 0,
            1, 4, 2,
            5, 3, 0,
            4, 6, 2,
            3, 5, 7,
            6, 4, 7,
            5, 6, 7, 
        };

        // メッシュに頂点を登録する
        mesh.SetVertices(vertices);

        // メッシュにUV座標を登録する
        mesh.SetUVs(0, uvs);

        // メッシュに面を構成するインデックスリストを登録する
        mesh.SetTriangles(triangles, 0);

        // 作成したメッシュをメッシュフィルターに設定する
        MeshFilter meshFilter = this.AddComponent<MeshFilter>();
        meshFilter.mesh = mesh;
        
        // マテリアルを設定する
        MeshRenderer meshRenderer = this.AddComponent<MeshRenderer>();
        meshRenderer.material = setMaterial;
    }
}