うにてぃブログ

主にUnityとC#に関する記事を書いていきます

【Unity】uGUI の透明な画像の Draw について

透明な画像を置いてタップ判定をさせたり、タップをさせなくしたりすることがあるが 透明な画像でも無駄にDraw Call が発生していることがある

調査

uGUI で透明 (アルファが0) の画像のみを置いておき
Frame Debug を利用して Draw Call を見てみる

f:id:hacchi_man:20200209003337p:plain

Canvasのみの場合の Drawが以下になる

f:id:hacchi_man:20200209003651p:plain

透明の画像がある状態だと以下になる

f:id:hacchi_man:20200209003859p:plain

透明の画像なので描画されないかと思いきや、透明が描画されている
透明なのに描画されるのは無駄なので対応する必要がある

対応方法

対応する方法は2つある ・描画はしないがタップ判定を取れるコンポーネントを作成する ・CanvasRenderer の cullTransparentMesh を true にする (Unity2018.2以降でのみ可能)

UnityEngine.EventSystems は Rect の領域でチェックをするので
描画するしない関係なくイベントをハンドルできます

描画はしないがタップ判定を取れるコンポーネント

Graphic を継承し頂点情報を削除することで描画されないが イベントをハンドルできるコンポーネントを作成できる

using UnityEngine.EventSystems;
using UnityEngine.UI;

public class TapHandler : Graphic, IPointerDownHandler, IPointerUpHandler
{
    private bool isPointerDown;
    
    public void OnPointerDown(PointerEventData eventData)
    {
        isPointerDown = true;
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        if (!isPointerDown)
            return;
        
        // タップ処理
        isPointerDown = false;
    }

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

CanvasRenderer の cullTransparentMesh を true にする

CanvasRenderer-cullTransparentMesh - Unity スクリプトリファレンス
公式リファレンスを見てもらえればわかるように、 これを true にすると透明な場合描画をスキップすることができる