LoginSignup
38
21

More than 3 years have passed since last update.

描画負荷がかからない透明なuGUI Imageを作る【Unity】

Last updated at Posted at 2020-02-06

はじめに

uGUIの操作を制限するため手前に透明なImageを重ねることがあると思いますが、そのままでは1枚分の描画負荷がかかってしまいます。その負荷を軽減する方法を紹介します。

方法

スクリーンショット 2020-02-06 10.05.10.png

Imageと同じGameObjectについているCanvasRendererのCull Transparent Meshをオンにしてください。

スクリーンショット 2020-02-06 10.33.17.png

SceneビューのOverdrawモードで確認すると、設定したImage部分の描画がされていないことが確認できます。

ダウンロード (1).png

StatsでもBatchesが増えていないことが確認できます。

ちなみにCanvasRendererのCull Transparent Meshで全ての描画がなくなるのは全ての画像領域が完全に透明な場合のみです。アルファ値が0.1でも残っていると描画されてしまう点に注意してください。

おまけ: 最初から描画しないスクリプトを自作する

上記の方法とほぼほぼ同じことができるスクリプトです。途中から意味ないと気がついたのですが、折角なので紹介します。raycastも当たるやつです。

スクリーンショット 2020-02-06 10.20.18.png
^先ほどと同様にいくつ置いても描画されない

スクリプト

Gist: NoRenderImage.cs

NoRenderImage.cs
using UnityEditor;

namespace UnityEngine.UI
{
    /// <summary>
    /// 描画しない透明Imageコンポーネント
    /// </summary>
    [AddComponentMenu("UI/NonRenderImage", 2004)]
    public class NoRenderImage : Graphic
    {
        protected override void OnPopulateMesh(VertexHelper vh) { vh.Clear(); }

#if UNITY_EDITOR
        [UnityEditor.CustomEditor(typeof(NoRenderImage))]
        class NonRenderImageEditor : UnityEditor.Editor
        {
            public override void OnInspectorGUI() { }

            private static Vector2 s_ImageElementSize = new Vector2(100f, 100f);

            [MenuItem("GameObject/UI/NoRender Image", false, 2004)]
            public static void CreateNoRenderImage()
            {
                var parent = Selection.activeGameObject?.transform;
                if (parent == null || parent.GetComponentInParent<Canvas>() == null)
                {
                    var canvas = new GameObject("Canvas");
                    canvas.transform.SetParent(parent);
                    canvas.AddComponent<Canvas>().renderMode = RenderMode.ScreenSpaceOverlay;
                    canvas.AddComponent<CanvasScaler>();
                    canvas.AddComponent<GraphicRaycaster>();
                    parent = canvas.transform;
                }
                var go = new GameObject("NoRenderImage");
                var rectTransform = go.AddComponent<RectTransform>();
                rectTransform.SetParent(parent);
                rectTransform.sizeDelta = s_ImageElementSize;
                rectTransform.anchoredPosition = Vector2.zero;
                Selection.activeGameObject = go;
                go.AddComponent<NoRenderImage>();
            }
        }
#endif
    }
}

メインはこの部分だけです。メッシュ描画のコールバック関数であるOnPopulateMeshをoverrideして、頂点をクリアしています。これで描画だけがされないGraphicコンポーネントが実現できました。
参考: ボタンの当たり判定(タッチ範囲)だけ広げる【Unity】【uGUI】 - (:3[kanのメモ帳]

public class NoRenderImage : Graphic
{
    protected override void OnPopulateMesh(VertexHelper vh) { vh.Clear(); }
}

他の部分は便利に使うための記述です。

スクリーンショット 2020-02-06 10.25.39.png
^[Add Component]メニューのUIカテゴリから追加できる

スクリーンショット 2020-02-06 10.26.43.png
^Createメニューからも生成できる

スクリーンショット 2020-02-06 10.28.07.png
^Canvas以下でない階層で生成すると、自動的にCanvasを作ってくれる

この辺りは別の記事でまとめておこうと思います。

余談

Textコンポーネントも描画するテキストがない場合に描画がされないので、それで良い説もありますね。

38
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
21