6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Unity】UGUI Shadersサンプルを使ったお手軽UI描画

Last updated at Posted at 2025-12-19

CYBIRD Advent Calendar 2025の20日目担当、@cy-tatsuya-sakai です。
19日目は @gumita さんの「AIにお任せしてゲームを作ってみた」でした。

はじめに

今年の3月ごろ、Unity6のuGUIでシェーダーグラフが使える & サンプル出たと記事になっていましたね、これはありがたい!
https://gamemakers.jp/article/2025_03_14_95059/

今回はこのUGUI Shadersサンプルを使ったシェーダーグラフでお手軽に、ボタンやモーダル等に使える
・角丸
・角丸以外
を描画してみようと思います!

記事の説明にはUnity6000.2.15f1Universal 2Dコアテンプレートから作成したUnityプロジェクトを使用します。

下準備

UGUI Shadersサンプルのインポート

https://discussions.unity.com/t/announcing-the-shader-graph-ugui-shaders-sample/1602836
サンプルのインポートはパッケージマネージャーから。
スクリーンショット_2025-12-16_11_52_44.png

Subgraphsフォルダ以下に便利なサブグラフが入っていて、
スクリーンショット 2025-12-16 11.53.41.png

SubgraphLibrary.shadergraphでサブグラフを一覧できます。すごい!
スクリーンショット 2025-12-16 11.54.24.png

9スライス用スプライトの準備

サンプルではスプライトを使用していないみたいでしたが、今回は普通にスプライトを使用します。
9スライス出来れば良いので、適当な極小テクスチャをスライスします。

今回は4x4のテクスチャを、中心でスライスしてみました。
Pixels Per Unitがテクスチャサイズと一致していれば何でもOKです。
スクリーンショット 2025-12-16 14.02.51.png
スクリーンショット 2025-12-16 14.03.21.png

シェーダーグラフの作成

ProjectビューからCreate > Shader Graph > URP > Canvas Shader Graphでシェーダーグラフを作成します。

スクリーンショット 2025-12-16 14.07.30.png

uGUIのImageコンポーネントに先ほどのスプライトと、作成したシェーダーグラフのマテリアルを設定すれば準備完了です:ok_hand:
スクリーンショット 2025-12-16 14.28.23.png

角丸の描画

Rectangleサブグラフ

サンプルのSDFs/RectangleノードをAlphaに繋げば、完成!
スクリーンショット 2025-12-16 15.33.44.png
スクリーンショット 2025-12-16 15.31.36.png

既存のShapes/Rounded Rectangleよりパラメータ豊富で、細かな調整ができます。

Edge Min, Edge Max

角丸の境界を滑らかに出来ます。擬似的なアンチエイリアス効果もありそう。
スクリーンショット 2025-12-16 15.30.39.png

Corner Radii

四隅それぞれに丸さを設定できます。ヘッダーやバッジ・リボン的な表現に使えそうです。
スクリーンショット 2025-12-16 15.51.12.png

Stroke

アウトラインに使えるかも?
スクリーンショット 2025-12-16 18.10.24.png
スクリーンショット 2025-12-16 18.00.23.png

SDF, SDFStoroke

角丸描画に使われた生のSigned Distance Fields(SDF)。何かに使えるかもしれない。

角丸サイズを個々に調節する

角丸サイズはシェーダーのCorner Raddiで調節するほか、ImageコンポーネントのPixels Per Unit Multiplierでも個々に調節できます。

もし角丸サイズ = 1Unitサイズにしたい場合は、Canvas ScalerReference Pixels Per Unitの値をRectTransformのWidthないしHeightで割ればOKです。
スクリーンショット_2025-12-17_13_11_45.png
大抵の場合Reference Pixels Per Unitはデフォルトの100になっていると思うので、
単純に100 / (RectTransform.Width or Height)と計算式をそのままPixels Per Unit Multiplierに入力すれば良いと思います。

Pixel Per Unit Multiplier = 1
スクリーンショット_2025-12-17_13_01_01.png

Pixel Per Unit Multiplier = 100 / RectTransform.Height
スクリーンショット_2025-12-17_13_01_58.png

角丸はSDF描画なのでジャギーは発生せず、綺麗に丸さを変えられています。グッド!

見た目のバリエーションを考える

フラットな見た目を変えてみます。

陰影を付ける

陰影を付けて立体感を出してみます。

線形グラデーション
スクリーンショット 2025-12-17 19.52.27.png
スクリーンショット 2025-12-17 19.52.44.png

縁を暗く
スクリーンショット 2025-12-17 22.39.14.png
スクリーンショット 2025-12-17 22.39.23.png

法線を使って陰影計算
Normal From HeightノードはCanvasのAdditional Shader ChannelsNormal, Tangentにチェックを入れないと動作しなさそうだったので注意)
スクリーンショット 2025-12-18 0.49.55.png
スクリーンショット 2025-12-18 1.14.29.png
スクリーンショット 2025-12-18 1.14.03.png

影色を変える

影を黒ではなく、任意の色にするとUIの印象を変えられるかも?
スクリーンショット 2025-12-18 11.34.55.png

もしImageカラーそのまま描画 & マテリアル共通にするなら、影色は頂点カラーをHSV形式でオフセットした値にすると、色違いのUI間で影色の印象を揃えられる気がしなくもないです。
スクリーンショット 2025-12-18 2.14.21.png

線形グラデーションに、彩度MAX・色相ずらして影色にするとこんな感じ。
明るい印象になったでしょうか?
スクリーンショット 2025-12-18 1.26.55.png

UI全体にグラデーションを付ける

BaseMeshEffectを継承したスクリプトで頂点情報を追加できます。
例えばUV2に9スライスしていない状態のUVを書き込めば、UI全体にグラデーションを付けることも可能です。
UV2をシェーダー側で読み取るために、CanvasのAdditional Shader ChannelsTexCoord2のチェックを忘れずに。
ちなみにUV1は書き込んでも反映されませんでした。謎。

NormalizedUV2.cs
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// UIのUV2に0〜1を設定
/// </summary>
public class NormalizedUV2 : BaseMeshEffect
{
    public override void ModifyMesh(VertexHelper vh)
    {
        if(vh.currentVertCount <= 0)
        {
            return;
        }

        UIVertex vert = new();
        Vector2 min;
        Vector2 max;
        {
            vh.PopulateUIVertex(ref vert, 0);
            min = max = vert.position;
        }

        // 頂点座標の最小、最大を計算
        for(int i = 0; i < vh.currentVertCount; i++)
        {
            vh.PopulateUIVertex(ref vert, i);
            min.x = Mathf.Min(min.x, vert.position.x);
            min.y = Mathf.Min(min.y, vert.position.y);
            max.x = Mathf.Max(max.x, vert.position.x);
            max.y = Mathf.Max(max.y, vert.position.y);
        }

        if(max.x - min.x < 0.0001f || max.y - min.y < 0.0001f)
        {
            return;
        }

        // 頂点座標の0〜1を計算
        for(int i = 0; i < vh.currentVertCount; i++)
        {
            vh.PopulateUIVertex(ref vert, i);
            var uv = new Vector2(vert.position.x, vert.position.y);
            vert.uv2 = (uv - min) / (max - min);
            vh.SetUIVertex(vert, i);
        }
    }
}

作成したスクリプトをImageのオブジェクトにアタッチして、シェーダー側でUV2を参照するとこんな感じ。どうでしょう?
スクリーンショット 2025-12-18 12.10.43.png
スクリーンショット 2025-12-18 12.11.27.png
スクリーンショット 2025-12-18 12.10.55.png

角丸以外を描画する

角丸以外の形状にしたい!

Rounded Cornersサブグラフ

角丸の丸さを決めていたCorner Raddiの内部処理は、それ単体でRounded Cornersサブグラフ化されていました。
スクリーンショット 2025-12-18 12.27.31.png

これを任意のSDFに乗算すれば、角丸以外の形状も作れそうです。

先人の知恵をお借りして、適当なSDFを作ってみます。
https://qiita.com/7CIT/items/fe33b9b341b9918b6c3d

今回はひし型のSDFを作ってみました。
スクリーンショット 2025-12-18 13.01.44.png

これを角丸と差し替えて
スクリーンショット 2025-12-18 12.58.49.png

こんな感じ!…見た目の良し悪しはさておき、一応角丸以外も作れました。
スクリーンショット 2025-12-18 12.59.05.png

おわりに

uGUIで気軽にシェーダー作れるのは素直に嬉しい!SDFで綺麗に描画できるのもポイント高いです。
この記事は地味目でしたが、UGUI Shadersサンプルにはもっと格好良い実装例もあるので、そちらもぜひチェックしてみて下さい!

明日のCYBIRD Advent Calendar 2025 21日目は、@moffunnya さんの「誰でも使えるログ調査環境についての感想(クラスメソッド様主催 ゲームクリエイターズキャンプ)」です。お楽しみに!

6
4
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
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?