質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

2回答

3599閲覧

ボタン画像を周期的に光らせる演出

hogefugapiyo

総合スコア3302

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

1クリップ

投稿2020/04/16 02:45

お世話になっております。
現在、UI画面の作成を進めているのですが押して貰うボタンをより強調して表示するためのビジュアル的な演出を考えています。

#やりたいこと
下記Gif動画のボタンで行われている演出です
イメージ説明
・ボタンが周期的に拡縮する
・ボタンの上を光る画像が左から右へ流れていく

上記2点のうち、前者はDotweenを利用してスケールを拡縮させることで実現できました。
しかし、ボタンの上の光る画像がスクロールする方法で頭を悩ませています。
この表現をなんと呼ぶのかわからず、いまいち検索でも欲しい情報がが出てこなかったので、この表現技法についてご存知の方がいればアプローチについてヒントをいただければ幸いです。

#やってみたこと
・白い斜線画像を上にのせて左右にスクロールする
ボタンの内側が光っているというよりは、ボタンの外側からテクスチャが横断しているような不自然な見え方をする

・ビルトインシェーダをベースに、他の画像を表示するテストをしてみる
ボタンの画像がsliceなのが原因なのか、表示のされかたがおかしくなる

使用したテクスチャ
イメージ説明

下記Shaderを適用したMaterialのAddTextureに上記画像をためしに入れてみた場合
イメージ説明
上にのせるための画像が崩れる

cs

1// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 3Shader "Custom/TwinkleGUI" 4{ 5 Properties 6 { 7 [PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {} 8 _AddTex("Add Texture", 2D) = "white" {} 9 _Color("Tint", Color) = (1,1,1,1) 10 11 _StencilComp("Stencil Comparison", Float) = 8 12 _Stencil("Stencil ID", Float) = 0 13 _StencilOp("Stencil Operation", Float) = 0 14 _StencilWriteMask("Stencil Write Mask", Float) = 255 15 _StencilReadMask("Stencil Read Mask", Float) = 255 16 17 _ColorMask("Color Mask", Float) = 15 18 19 [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip("Use Alpha Clip", Float) = 0 20 } 21 22 SubShader 23 { 24 Tags 25 { 26 "Queue" = "Transparent" 27 "IgnoreProjector" = "True" 28 "RenderType" = "Transparent" 29 "PreviewType" = "Plane" 30 "CanUseSpriteAtlas" = "True" 31 } 32 33 Stencil 34 { 35 Ref[_Stencil] 36 Comp[_StencilComp] 37 Pass[_StencilOp] 38 ReadMask[_StencilReadMask] 39 WriteMask[_StencilWriteMask] 40 } 41 42 Cull Off 43 Lighting Off 44 ZWrite Off 45 ZTest[unity_GUIZTestMode] 46 Blend SrcAlpha OneMinusSrcAlpha 47 ColorMask[_ColorMask] 48 49 Pass 50 { 51 Name "Default" 52 CGPROGRAM 53 #pragma vertex vert 54 #pragma fragment frag 55 #pragma target 2.0 56 57 #include "UnityCG.cginc" 58 #include "UnityUI.cginc" 59 60 #pragma multi_compile_local _ UNITY_UI_CLIP_RECT 61 #pragma multi_compile_local _ UNITY_UI_ALPHACLIP 62 63 struct appdata_t 64 { 65 float4 vertex : POSITION; 66 float4 color : COLOR; 67 float2 texcoord : TEXCOORD0; 68 UNITY_VERTEX_INPUT_INSTANCE_ID 69 }; 70 71 struct v2f 72 { 73 float4 vertex : SV_POSITION; 74 fixed4 color : COLOR; 75 float2 texcoord : TEXCOORD0; 76 float4 worldPosition : TEXCOORD1; 77 UNITY_VERTEX_OUTPUT_STEREO 78 }; 79 80 sampler2D _MainTex; 81 sampler2D _AddTex; 82 fixed4 _Color; 83 fixed4 _TextureSampleAdd; 84 float4 _ClipRect; 85 float4 _MainTex_ST; 86 87 v2f vert(appdata_t v) 88 { 89 v2f OUT; 90 UNITY_SETUP_INSTANCE_ID(v); 91 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); 92 OUT.worldPosition = v.vertex; 93 OUT.vertex = UnityObjectToClipPos(OUT.worldPosition); 94 95 OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); 96 97 OUT.color = v.color * _Color; 98 return OUT; 99 } 100 101 fixed4 frag(v2f IN) : SV_Target 102 { 103 half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color; 104 half4 color2 = (tex2D(_AddTex, IN.texcoord) + _TextureSampleAdd) * IN.color; 105 #ifdef UNITY_UI_CLIP_RECT 106 color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect); 107 #endif 108 109 #ifdef UNITY_UI_ALPHACLIP 110 clip(color.a - 0.001); 111 #endif 112 113 return color2; // 一旦テストのため載せるテクスチャだけ表示 114 } 115 ENDCG 116 } 117 } 118}

なにかお知恵をお持ちの方がいらっしゃいましたら、よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

こういう光沢表現はなんて言うんでしょうかね...すみませんが一般的な呼称は分からないです。
おっしゃるように、texcoordを使ってテクスチャをサンプリングした場合はSliceのために見た目が崩れるのだろうと思います。
下記のように、_AddTexのサンプリング位置としてworldPositionを使ってみてはいかがでしょうか?

ShaderLab

1// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 3Shader "Custom/TwinkleGUI" 4{ 5 Properties 6 { 7 [PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {} 8 _AddTex("Add Texture", 2D) = "white" {} 9 _Color("Tint", Color) = (1,1,1,1) 10 11 _StencilComp("Stencil Comparison", Float) = 8 12 _Stencil("Stencil ID", Float) = 0 13 _StencilOp("Stencil Operation", Float) = 0 14 _StencilWriteMask("Stencil Write Mask", Float) = 255 15 _StencilReadMask("Stencil Read Mask", Float) = 255 16 17 _ColorMask("Color Mask", Float) = 15 18 19 [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip("Use Alpha Clip", Float) = 0 20 } 21 22 SubShader 23 { 24 Tags 25 { 26 "Queue" = "Transparent" 27 "IgnoreProjector" = "True" 28 "RenderType" = "Transparent" 29 "PreviewType" = "Plane" 30 "CanUseSpriteAtlas" = "True" 31 } 32 33 Stencil 34 { 35 Ref[_Stencil] 36 Comp[_StencilComp] 37 Pass[_StencilOp] 38 ReadMask[_StencilReadMask] 39 WriteMask[_StencilWriteMask] 40 } 41 42 Cull Off 43 Lighting Off 44 ZWrite Off 45 ZTest[unity_GUIZTestMode] 46 Blend SrcAlpha OneMinusSrcAlpha 47 ColorMask[_ColorMask] 48 49 Pass 50 { 51 Name "Default" 52 CGPROGRAM 53 #pragma vertex vert 54 #pragma fragment frag 55 #pragma target 2.0 56 57 #include "UnityCG.cginc" 58 #include "UnityUI.cginc" 59 60 #pragma multi_compile_local _ UNITY_UI_CLIP_RECT 61 #pragma multi_compile_local _ UNITY_UI_ALPHACLIP 62 63 struct appdata_t 64 { 65 float4 vertex : POSITION; 66 float4 color : COLOR; 67 float2 texcoord : TEXCOORD0; 68 UNITY_VERTEX_INPUT_INSTANCE_ID 69 }; 70 71 struct v2f 72 { 73 float4 vertex : SV_POSITION; 74 fixed4 color : COLOR; 75 float2 texcoord : TEXCOORD0; 76 float4 worldPosition : TEXCOORD1; 77 UNITY_VERTEX_OUTPUT_STEREO 78 }; 79 80 sampler2D _MainTex; 81 sampler2D _AddTex; 82 fixed4 _Color; 83 fixed4 _TextureSampleAdd; 84 float4 _ClipRect; 85 float4 _MainTex_ST; 86 float4 _AddTex_ST; // _AddTexのタイリング・オフセットを受け取る 87 88 v2f vert(appdata_t v) 89 { 90 v2f OUT; 91 UNITY_SETUP_INSTANCE_ID(v); 92 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); 93 OUT.worldPosition = v.vertex; 94 OUT.vertex = UnityObjectToClipPos(OUT.worldPosition); 95 96 OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); 97 98 OUT.color = v.color * _Color; 99 return OUT; 100 } 101 102 fixed4 frag(v2f IN) : SV_Target 103 { 104 half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color; 105 106 // worldPositionのx、yを使ってサンプリングしてみる 107 // TRANSFORM_TEXを通してやれば、マテリアルのインスペクターにある「Tiling」と「Offset」が効果を発揮すると思われます 108 // UIに適用するのであれば、TilingはUIテクスチャのPixels Per Unitの逆数...100ならば0.01くらいが妥当ではないでしょうか 109 // Offsetもテクスチャのつなぎ目が不自然にならないよう適宜調整してやるといいでしょう 110 // スクリプトからOffsetを操作してやれば、光沢のアニメーションも可能だろうと思います 111 half4 color2 = (tex2D(_AddTex, TRANSFORM_TEX(IN.worldPosition.xy, _AddTex)) + _TextureSampleAdd) * IN.color; 112 113 #ifdef UNITY_UI_CLIP_RECT 114 color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect); 115 #endif 116 117 #ifdef UNITY_UI_ALPHACLIP 118 clip(color.a - 0.001); 119 #endif 120 121 // return color2; // 一旦テストのため載せるテクスチャだけ表示 122 123 // ベースの色に対してcolor2を加算合成してみる 124 color.rgb += color2.rgb * color2.a; 125 return color; 126 } 127 ENDCG 128 } 129 } 130}

オフセット操作時の見た目は下図のようになりました。なお、光沢テクスチャのWrap ModeはClampにしています。

図

worldPositionを使うことによる弊害として、光沢のかかり方が画面上のボタンの位置によって変化してしまう点が挙げられそうです。スクリプト側でボタンの座標に応じてOffsetを調整するなどの工夫が必要かもしれません。
ボタンが少数なら、ボタンごとにマテリアルオブジェクトを生成させて個別にOffsetをコントロールするのでもいいかもしれませんが、大量のボタンがある場合は、ずらし量をMaterialPropertyBlockで与えてやった方が効率的かもしれませんね。

あるいは、ボタンの位置によって光沢の位置が変化してしまうことは許容した上で、Wrap ModeがRepeatでも見た目が破綻しないような光沢テクスチャを使うのも一案だと思います。
たとえば下図のような光沢テクスチャを使用すると(teratail上だと真っ白に見えるかもしれませんがすみません)...

図2

下図のようにワールド空間全域に光沢が通り過ぎるような見た目になるでしょう。

図3

投稿2020/04/16 22:21

Bongo

総合スコア10807

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hogefugapiyo

2020/04/20 00:27

まさに求めていた通りの挙動となりました。 Shaderの中身を拝見し、勉強させていただきたいと思います。ありがとうございました。
guest

0

アニメGIFでいいのでは。

投稿2020/04/16 02:48

y_waiwai

総合スコア87747

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問