完成図
考え方
1) 床のマテリアルに円を書くようなShaderを実装します
2) キャラクターの位置にその円がくるようスクリプトからパラメータを変更します
あまり言及することはないのですが、強いて言うならShaderのプロパティをスクリプトから変更する、というのが新しい点で今回のポイントです。
実装
まず、Shaderから見ていきます。
Shader "Custom/RadiusShader" { Properties { _MainTex ("Albedo (RGB)", 2D) = "white" {} _Center("Center", Vector) = (200,0,200,0) _Radius("Radius", Float) = 1 _RadiusColor("Radius Color", Color) = (1,0,0,1) _RadiusWidth("Radius Width", Float) = 0.5 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf Standard fullforwardshadows #pragma target 3.0 sampler2D _MainTex; float3 _Center; float _Radius; fixed4 _RadiusColor; float _RadiusWidth; struct Input { float2 uv_MainTex; float3 worldPos; }; void surf(Input IN, inout SurfaceOutputStandard o) { float d = distance(_Center, IN.worldPos); if ((d > _Radius) && (d < (_Radius + _RadiusWidth))) { o.Albedo = _RadiusColor; } else { o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb; } } ENDCG } FallBack "Diffuse" }
SurfaceFunctionの実装を見ていきます。非常にシンプルですね。 _Centerが円の中心としたい場所なので、その値と現在参照されている位置のワールド座標との距離によって、テクスチャを貼るか円の色を塗るかを決定しています。 条件もとてもシンプルなので特に解説するところはないですね。
次はスクリプトです。こちらも非常にシンプルです。
[ExecuteInEditMode] public class SetRadiusProperties : MonoBehaviour { public Material[] radiusMaterials; public float radius = 1; public Color color = Color.white; void Update() { foreach(Material radiusMaterial in radiusMaterials) { radiusMaterial.SetVector("_Center", transform.position); radiusMaterial.SetFloat("_Radius", radius); radiusMaterial.SetColor("_RadiusColor", color); } } }
円を書きたいマテリアルを入れておいて、それらのプロパティにtransform.position
を入れることで動かしているだけになります。
床のマテリアルにRadiusShaderを使用し、動かすキャラクターにSetRadiusPropertiesをアタッチすると動作確認ができるかと思います。
おわりに
シンプルに実用性の高そうなShaderが実装できました。 次からライティングモデルを勉強していきたいなーと思います。