前言
项目需要,做一个简单的扇形扫描效果,在网上没搜到相关的,所以记录下,以供初学者参考。
基本思路
以一个plane为低,准备两张贴图,一张做背景,一张做扇形扫描图,定义一个半径值作为圆的限制条件,再定义两个角度值作为扇形区域的限制条件,然后先根据uv坐标与plane中心点的距离判断是否在圆形区域,再根据y值判断是否在正y轴区域,最后根据角度值判断是否在扇形区。
正文
1.先上shader,英文不好,都是随便命名,知道是哪个变量就成,主要解释都放在代码里。
Shader "Unlit/RadarWave"
{Properties{//背景图_MainTex ("Texture", 2D) = "white" {}//扇形用图_RadarTex ("Backgroud Texture",2D) = "white" {}//扇形半径,用模型坐标系,所以在0-0.5之间_RadarLengthRate ("Radar Length Rate",Range(0,0.5)) = 0.5//扇形左边界用的角度值_MaxAngle ("Max Angle",Range(0,180)) = 180//扇形角度值_DeltaAngle ("Delta Angle",Range(0,180)) = 60//扇形区域内y轴动画速度_ScanSpeed ("Scan Speed",Range(0.1,20)) = 2}SubShader{//设定Tags,考虑到要用透明效果,及方便预览,设定如下Tags { "RenderType"="Transparent" "Queue"="Transparent" "IgnoreProjector"="True" "PreviewType"="Plane"}//混合透明度Blend SrcAlpha OnePass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};sampler2D _MainTex;float4 _MainTex_ST;sampler2D _RadarTex;float _RadarLengthRate;float _MaxAngle;float _DeltaAngle;float _ScanSpeed;fixed delta(float2 uvPos){//计算uv坐标离中心点的距离float2 dir = uvPos - float2(0.5,0.5);float l = length(dir);//考虑到并行编程里少用if判断语句,所以我基本都是赋值0,1搭配lerp使用的方式,这里判断是否在圆内float s1 = l < _RadarLengthRate ? 1 : 0;//是否在正y轴区域float s2 = uvPos.y < 0.5 ? 1 : 0;//限制扇形左边界与正x轴的角度float maxAngle = _MaxAngle;maxAngle = clamp(maxAngle,_DeltaAngle,180);//限制扇形右边界与正x轴的角度float minAngle = maxAngle - _DeltaAngle;minAngle = clamp(minAngle,0,180-_DeltaAngle);//判断uv坐标是否在扇形区域float t1 = l * cos(maxAngle * 3.14 / 180) + 0.5;float t2 = l * cos(minAngle * 3.14 / 180) + 0.5;float s3 = uvPos.x < t2 && uvPos.x > t1 ? 1 : 0;//返回1或0return s1 * s2 * s3;}v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);return o;}fixed4 frag (v2f i) : SV_Target{// sample the texturefixed4 col1 = tex2D(_MainTex, i.uv);//扇形区域的y轴方向加了个动画fixed4 col2 = tex2D(_RadarTex, float2(i.uv.x,i.uv.y + _Time.y * _ScanSpeed));fixed dis = delta(i.uv);fixed4 col = lerp(col1,col2 + col1,dis);return col;}ENDCG}}
}
2.编写c#脚本,控制扫描,同样,主要解释都放在代码内。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class ScanAnim : MonoBehaviour {#region Private Variablesprivate Material myMat;private bool flag;#endregion#region Public Variablespublic float scanSpeed = 1;#endregion#region Unity Methodsvoid Start () {myMat = GetComponent<MeshRenderer>().material;float deltaAngle = myMat.GetFloat("_DeltaAngle");myMat.SetFloat("_MaxAngle", deltaAngle);}void Update () {float maxAngle = myMat.GetFloat("_MaxAngle");//控制扇形顺时针扫描if (maxAngle < 180 && !flag){myMat.SetFloat("_MaxAngle", maxAngle + scanSpeed);if (maxAngle + scanSpeed >= 180){flag = !flag;}}//控制扇形逆时针扫描if (maxAngle > 0 && flag){myMat.SetFloat("_MaxAngle", maxAngle - scanSpeed);if (maxAngle - scanSpeed <= myMat.GetFloat("_DeltaAngle")){flag = !flag;}}}#endregion
}