能量盾 受击波纹 小测试
表现:受击是会产生一个受击波纹向四周扩散
shader:
Shader "Unlit/NewUnlitShader"
{
Properties
{
_ShieldColor ("Shield Color", Color) = (0.5,0.5,0.5,0)
_BaseTex ("Base Texture", 2D) = "white" {}
_HitMaskTex ("Hit Mask Tex", 2D) = "white" {}
_HitU ("Hit U", Range(0, 1)) = 0.5
_HitV ("Hit V", Range(0, 1)) = 0.5
_HitOffset ("Hit Offset", Range(0, 2)) = 0.5
_HitU2 ("Hit U2", Range(0, 1)) = 0.5
_HitV2 ("Hit V2", Range(0, 1)) = 0.5
_HitOffset2 ("Hit Offset2", Range(0, 2)) = 0.5
}
SubShader
{
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
Blend SrcAlpha One
Cull Off Lighting Off ZWrite Off
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
fixed4 _ShieldColor;
sampler2D _BaseTex;
float4 _BaseTex_ST;
sampler2D _HitMaskTex;
float4 _HitMaskTex_ST;
fixed _HitU;
fixed _HitV;
fixed _HitOffset;
fixed _HitU2;
fixed _HitV2;
fixed _HitOffset2;
fixed luminance(fixed3 color) {
return 0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b;
}
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 baseuv : TEXCOORD0;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.baseuv = TRANSFORM_TEX(v.uv, _BaseTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed lum = luminance(tex2D(_BaseTex, i.baseuv));
fixed3 baseCol = _ShieldColor * lum;
fixed dis = distance(fixed2(_HitU, _HitV), i.baseuv);
dis = abs(dis - _HitOffset);
dis = luminance(tex2D(_HitMaskTex, dis));
fixed3 hitCol = _ShieldColor * dis;
dis = distance(fixed2(_HitU2, _HitV2), i.baseuv);
dis = abs(dis - _HitOffset2);
dis = luminance(tex2D(_HitMaskTex, dis));
fixed3 hitCol2 = _ShieldColor * dis;
return fixed4(baseCol + hitCol + hitCol2, lum);
}
ENDCG
}
}
}
C#
using UnityEngine;
using System.Collections;
public class HitShieldTest : MonoBehaviour
{
Material ShieldMaterial;
Vector3 oriPos;
Vector3 extents;
float hitTime;
float hitTime2;
void Awake()
{
ShieldMaterial = GetComponent<MeshRenderer>().material;
Collider collider = GetComponent<Collider>();
extents = collider.bounds.extents;
oriPos = transform.position + extents;
ShieldMaterial.SetFloat("_HitOffset", 2);
ShieldMaterial.SetFloat("_HitOffset2", 2);
hitTime = float.MinValue;
hitTime2 = float.MinValue;
}
// Update is called once per frame
void Update()
{
if (ShieldMaterial == null)
{
return;
}
if (Input.GetKeyDown(KeyCode.Mouse0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
Vector3 dis = oriPos - hit.point;
dis = dis / (2 * extents.x); //方形
if (Time.time - hitTime > 0.5f)
{
hitTime = Time.time;
ShieldMaterial.SetFloat("_HitU", dis.x);
ShieldMaterial.SetFloat("_HitV", dis.y);
}
else if (Time.time - hitTime2 > 0.5f)
{
hitTime2 = Time.time;
ShieldMaterial.SetFloat("_HitU2", dis.x);
ShieldMaterial.SetFloat("_HitV2", dis.y);
}
}
}
if (Time.time - hitTime <= 2)
{
ShieldMaterial.SetFloat("_HitOffset", Time.time - hitTime);
}
if (Time.time - hitTime2 <= 2)
{
ShieldMaterial.SetFloat("_HitOffset2", Time.time - hitTime2);
}
}
}
优化一下 支持帧动画,实际表现也不是很好
再优化的话,考虑在程序中吧受击点定位到最相近的格子的中心点,动画的叠加表现就会很好
Shader "Unlit/NewUnlitShader"
{
Properties
{
_ShieldColor ("Shield Color", Color) = (0.5,0.5,0.5,0)
_BaseTex ("Base Texture", 2D) = "white" {}
//圆形用渐变贴图的方式
_HitMaskTex ("Hit Mask Tex", 2D) = "white" {}
//帧动画的方式
_HitAniTex ("Hit Animation Tex", 2D) = "white" {}
_HitAniHorAmount ("Horizontal Amount", float) = 1
_HitAniVerAmount ("Vertical Amount", float) = 1
//受击点信息
_HitU ("Hit U", Range(0, 1)) = 0.5
_HitV ("Hit V", Range(0, 1)) = 0.5
_HitOffset ("Hit Offset", Range(0, 2)) = 0.5
_HitU2 ("Hit U2", Range(0, 1)) = 0.5
_HitV2 ("Hit V2", Range(0, 1)) = 0.5
_HitOffset2 ("Hit Offset2", Range(0, 2)) = 0.5
}
SubShader
{
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
Blend SrcAlpha One
Cull Off Lighting Off ZWrite Off
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
fixed4 _ShieldColor;
sampler2D _BaseTex;
float4 _BaseTex_ST;
sampler2D _HitMaskTex;
float4 _HitMaskTex_ST;
sampler2D _HitAniTex;
float4 _HitAniTex_ST;
fixed _HitAniHorAmount;
fixed _HitAniVerAmount;
fixed _HitU;
fixed _HitV;
fixed _HitOffset;
fixed _HitU2;
fixed _HitV2;
fixed _HitOffset2;
fixed luminance(fixed3 color) {
return 0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b;
}
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 baseuv : TEXCOORD0;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.baseuv = TRANSFORM_TEX(v.uv, _BaseTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed lum = luminance(tex2D(_BaseTex, i.baseuv));
fixed3 baseCol = _ShieldColor * lum;
fixed dis = distance(fixed2(_HitU, _HitV), i.baseuv);
dis = abs(dis - _HitOffset);
dis = luminance(tex2D(_HitMaskTex, dis));
fixed3 hitCol = _ShieldColor * dis;
dis = distance(fixed2(_HitU2, _HitV2), i.baseuv);
dis = abs(dis - _HitOffset2);
dis = luminance(tex2D(_HitMaskTex, dis));
fixed3 hitCol2 = _ShieldColor * dis;
//return fixed4(baseCol + hitCol + hitCol2, lum);
//帧动画受击
//单帧的uv值
half2 aniuv = i.baseuv + half2(0.5 - _HitU, 0.5 - _HitV);
aniuv = 2 * (aniuv - half2(0.5, 0.5)) + half2(0.5, 0.5);
aniuv.x = saturate(aniuv.x);
aniuv.y = saturate(aniuv.y);
//单帧位置(行列)
float idx = floor(_Time.y * _HitAniHorAmount * _HitAniVerAmount);
idx = idx % (_HitAniHorAmount * _HitAniVerAmount);
float row = floor(idx / _HitAniHorAmount);
float col = idx - row * _HitAniHorAmount;
//转化为全图的uv值
aniuv = aniuv + half2(col, _HitAniVerAmount - 1 - row);
aniuv.x /= _HitAniHorAmount;
aniuv.y /= _HitAniVerAmount;
fixed4 aniCol = tex2D(_HitAniTex, aniuv);
aniCol.rgb = luminance(aniCol) * _ShieldColor;
aniCol.rgb *= aniCol.a;
return fixed4(baseCol + aniCol, lum);
}
ENDCG
}
}
}