Unity | UI用のテンプレートコンポーネント

Imageなどの既存のコンポーネントを使用せずに、Graphicクラスを継承したUI用のスクリプトを自作する記事です。

テンプレートコンポーネント

このテンプレートではImage相当の長方形を描画します。

テンプレート

UIRendererTemplate:三角形二つで四角形を描画(派生用のテンプレート)
UIRendererTemplate:三角形二つで四角形を描画(派生用のテンプレート)

以下は単純なメッシュを描画するテンプレートを使用した説明です。

テンプレートスクリプト

using UnityEngine;
using UnityEngine.UI;
namespace BlueBreath
{
    [RequireComponent(typeof(CanvasRenderer))]
    [ExecuteInEditMode]
    public class UIRendererTemplate : Graphic
    {
        protected override void OnPopulateMesh(VertexHelper vh)
        {
            vh.Clear();
            this.RectCache();
            this.Draw(vh);
        }
        private void Draw(VertexHelper vh)
        {
            UIVertex vertex = UIVertex.simpleVert;
            vertex.color = this.color;
            /* Add Vert */
            vertex.position = new Vector3(nRectLeft, nRectTop);
            vh.AddVert(vertex);//0
            vertex.position = new Vector3(nRectRight, nRectTop);
            vh.AddVert(vertex);//1
            vertex.position = new Vector3(nRectLeft, nRectBottom);
            vh.AddVert(vertex);//2
            vertex.position = new Vector3(nRectRight, nRectBottom);
            vh.AddVert(vertex);//3
            /* Add Triangle */
            vh.AddTriangle(0, 1, 2);
            vh.AddTriangle(1, 2, 3);
        }
        /* RectTransform Cache */
        float anchorLeft, anchorBottom, anchorTop, anchorRight;
        float pivotX, pivotY;
        float posX, posY, posZ;
        float width, height;
        float paddingTop, paddingBottom, paddingLeft, paddingRight;
        //Extensions
        float pCLeft, pCBottom, pCTop, pCRight;
        float nRectLeft, nRectBottom, nRectTop, nRectRight;
        private void RectCache()
        {
            //Anchors
            anchorLeft   = rectTransform.anchorMin.x;
            anchorBottom = rectTransform.anchorMin.y;
            anchorTop    = rectTransform.anchorMax.y;
            anchorRight  = rectTransform.anchorMax.x;
            //pivots
            pivotX = rectTransform.pivot.x;
            pivotY = rectTransform.pivot.y;
            //width & height
            width = rectTransform.rect.width;
            height = rectTransform.rect.height;
            //一致したアンカーとピボットの位置の差
            posX = rectTransform.position.x;
            posY = rectTransform.position.y;
            posZ = rectTransform.position.z;
            //アンカーから内部方向へのパディング
            paddingLeft   = rectTransform.offsetMin.x;
            paddingRight  = rectTransform.offsetMax.x;
            paddingTop    = rectTransform.offsetMax.y;
            paddingBottom = rectTransform.offsetMin.y;
            //ピボット中央に合わせる場合のUIVertex矩形座標
            pCLeft   = - width  / 2f;
            pCBottom = - height / 2f;
            pCTop    =   height / 2f;
            pCRight  =   width  / 2f;
            //ピボットに影響されないUIVertex矩形座標
            nRectLeft   = - pivotX * width;
            nRectRight  = (1 - pivotX) * width;
            nRectTop    = (1 - pivotY) * height;
            nRectBottom = - pivotY * height;
        }
    }
}

テンプレート作成基礎として、次の3点の説明になります。

  • Graphic:UIコンポーネント基本クラス(メッシュ生成コールバックを呼び出す)
  • VertexHelper:メッシュの生成(頂点情報を追加)
  • UIVertex:頂点情報

Graphic:UIコンポーネントの基本クラス

名前空間

using UnityEngine.UI;

継承

Graphic

コールバック関数(OnpopulateMesh)

        protected override void OnPopulateMesh(VertexHelper vh)
        {
            vh.Clear();
            this.RectCache();
            this.Draw(vh);
        }

コールバック関数OnPopulateMeshでは、VertexHelperユーティリティーを用いてUIメッシュを生成します。

※テンプレート内RectCache()は、RectTransformと矩形の表示を一定に保つ値のキャッシュです。不要な場合削除できます。

VertexHelper:UIのメッシュを生成するために使用するユーティリティークラス

VertexHelperを使用したメッシュ作成
VertexHelperを使用したメッシュ作成

作成を行う手順

  1. VertexHelperをリセットする(vh.Clear)
  2. 頂点の情報を作成する(UIVertex vertex)
  3. 頂点情報をVertexHelperに追加する(vh.AddVert(vertex))
  4. 3つの頂点から三角形を作る(vh.AddTriangle)
  5. 三角形の固まりで表現する

名前空間

using UnityEngine.UI;

Clear:メッシュ情報をリセットする

AddVert、AddTriangleの前に呼び出して、VertexHelper内の頂点、メッシュの情報をリセットします。

AddVert:頂点の情報を追加

public void AddVert(UIVertex v)

1つの頂点情報を追加します。

頂点情報については次のUIVertexで管理します。

挿入順によって0から「頂点の番号」が割り当てられます。

AddTriangle:頂点から三角形を描画

public void AddTriangle (int idx0, int idx1, int idx2);

positions配列のインデックスを3点与え、三角形を描画します。

idx0, idx1, idx2の値はそれぞれ、AddVertの挿入順「頂点の番号」と対応しています。

UIVertex:頂点情報を管理する構造体

名前空間

using UnityEngine;

UIVertexの座標

UIVertex.positionはpivotの位置を(0, 0)としている為、他のUIコンポーネントのように(テンプレートキャッシュ内)

例1)pivot(0.5, 0.5)で中央に描画する場合は幅と高さの半分ずらします。

例2)nRectの値は、青のドットで囲われているGizmoと同じ場所を示します。

            //ピボット中央(0.5, 0.5)に合わせる場合のUIVertex矩形座標
            pCLeft   = - width  / 2f;
            pCBottom = - height / 2f;
            pCTop    =   height / 2f;
            pCRight  =   width  / 2f;
            //ピボットに影響されないUIVertex矩形座標
            nRectLeft   = - pivotX * width;
            nRectRight  = (1 - pivotX) * width;
            nRectTop    = (1 - pivotY) * height;
            nRectBottom = - pivotY * height;

編集中にUIを表示する属性

[ExecuteInEditMode]

ExecuteInEditModeはスクリプトのインスタンスをEditモードで実行する属性です。

通常Playモードでなければ表示されませんが、これを付加する事によってコンポーネントの配置を可視化します。

プレハブが考慮されておらず廃止される可能性があります。

※無くとも動作する場合があり、その際は削除可能です。

代替属性としてPlayモードの一部として常に実行する、

[ExecuteAlways]

が存在します。

この属性を使用する場合は、Editモードであっても値が書き換わるため、

Application.IsPlaying

を使用した条件分岐によって、編集中と実行中の処理を分ける必要があります。

ワイヤフレームの表示

ワイヤフレームの表示
ワイヤフレームの表示

AddTriangleで正常に三角形が追加されている事を確認します。

SceneタブのShading ModeをShaded Wireframeに変更する事で表示されます。

参考・その他

参考

Unity DOCUMENTATION

資料

感想

スクリプト書く系はリファレンスくらいしか参考が無かったので、メジャーなやり方では無いかもです。

コメント

タイトルとURLをコピーしました