Skip to content
第10回 メッシュとシェーダーによる斬撃

1 / 4 弧状メッシュとUVの準備 ​

このステップの目的

斬撃の通り道を用意し、弧に沿った位置をUVのUで表します。

メッシュとUVの役割 ​

メッシュは頂点と三角形で作る形です。UVは、その表面のどこを描くかを示す2次元の座標です。ここでは弧の始点から終点をUの0〜1、内周から外周をVの0〜1へ対応させます。メッシュを動かさず、表示するUの範囲を変えると、光が弧に沿って走って見えます。

新しいSceneをLesson10.unityとして保存し、Main CameraをPosition (0, 0, -10)、Rotation (0, 0, 0)にします。空のGameObjectを原点へ作り、Slashと名付けます。Rotationは(0, 0, 0)、Scaleは(1, 1, 1)です。

作成用コンポーネント ​

ScriptsフォルダーへCrescentMesh.csを作り、次の全文を記述します。弧の内外へ頂点を並べ、隣の区間を三角形で結ぶ補助コードです。この回で調整する対象は、次のステップ以降のShader Graphです。まず補助コードをそのまま使って、全員が同じUVから始めます。

csharp
using UnityEngine;

[ExecuteAlways]
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class CrescentMesh : MonoBehaviour
{
    private Mesh mesh;

    private void OnEnable()
    {
        const int segments = 48;
        var vertices = new Vector3[(segments + 1) * 2];
        var uv = new Vector2[vertices.Length];
        var triangles = new int[segments * 6];
        for (int i = 0; i <= segments; i++)
        {
            float u = (float)i / segments;
            float angle = Mathf.Lerp(-120f, 120f, u) * Mathf.Deg2Rad;
            Vector3 direction = new(Mathf.Cos(angle), Mathf.Sin(angle), 0f);
            vertices[i * 2] = direction * 1.5f;
            vertices[i * 2 + 1] = direction * 2f;
            uv[i * 2] = new Vector2(u, 0f);
            uv[i * 2 + 1] = new Vector2(u, 1f);
            if (i == segments)
                continue;

            int v = i * 2;
            int t = i * 6;
            triangles[t] = v;
            triangles[t + 1] = v + 2;
            triangles[t + 2] = v + 1;
            triangles[t + 3] = v + 1;
            triangles[t + 4] = v + 2;
            triangles[t + 5] = v + 3;
        }

        mesh = new Mesh { name = "Crescent Preview", hideFlags = HideFlags.DontSave };
        mesh.vertices = vertices;
        mesh.uv = uv;
        mesh.triangles = triangles;
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();
        GetComponent<MeshFilter>().sharedMesh = mesh;
    }

    private void OnDisable()
    {
        if (mesh == null)
            return;
        if (Application.isPlaying)
            Destroy(mesh);
        else
            DestroyImmediate(mesh);
    }
}

SlashへCrescent Meshを追加すると、Mesh FilterとMesh Rendererも付きます。MaterialsフォルダーへMeshPreviewというMaterialを作り、ShaderをUniversal Render Pipeline/Unlit、Base Colorを白にしてMesh RendererのMaterialsのElement 0へ割り当てます。Gameビューに、円の一部を切り取った幅のある弧が見えることを確認します。

ExecuteAlwaysは編集モードでもメッシュを用意するための指定です。生成したMeshを独立したアセットとして保存する構成ではなく、SceneやPrefabに残すCrescent Meshコンポーネントが形を作り直します。

チェックリスト
  • Gameビューで弧の形を確認できる。
  • Uの始点・終点と、Vの内周・外周の対応を説明できる。