Unity循环长箭头加强版
需求变更
我哩个天天,需求这东西就是你做完一个又回有新的一个,做了个普通的,就会让你做高级的。
这不之前做了循环长箭头,领导就说要分段显示,怎么个分段显示咧?能够显示两种颜色的箭头,一种是你还没有走完的路,一种是已经走完的。恩,需求很简单,容我思考下人生。
看来又要学习啦
对unity的shader一直没有深入研究,到目前为止都是停留在能用就行的阶段。复杂一点的shader基本也用可视化的编辑插件进行处理,手打的也就能写写固定功能的shader。可视化的插件很方便,所见即所得,缺点是需要微调的时候就麻烦了。固定着色器功能再多也有限,到头来写Shader还是离不开HLSL和CG语言直接写。当然在Unity中,unity为我们包装了ShaderLab的壳子为我们方便的实现需要的功能,同时不至于代码过于的冗余和晦涩。
同样的Unity提供了官方文档,内容嘛,老规矩全而不细,需要的朋友出门左转,可以翻阅一下:Unity ShaderLab 官方文档
先想想问题,别急着动手
当前的需求是分段显示两种不同颜色的箭头,用于区分哪一部分是已经走过的路线,哪一部分是为走过的路线。在这个需求中需要处理两个贴图,用来表现不同的状态。
方法一:
常规情况下可以直接制作两个箭头的组件,因为在第一版的基础下已经实现了从点A到点B的箭头。分段显示只要处理点A到中间点A'和A'到B两段就行。
这样做表面上看起来没有任何问题,实际上也没有任何问题!就是有一点比较麻烦,首先,你需要处理两个箭头,其次,A'点在实际游戏中是移动的,因为人是不断移动的,你就需要不停的调整两个箭头的长度,也就是需要控制两个变量。这种虽然能有但是哪里又有点不对的感觉就好像...
对对对,特么就是这种感觉方法二:
不就是显示两个材质嘛,直接shader处理,把中间点A'当做属性值传入到shader中,然后就行判断,未到A'点的显示材质一,A'点之后的显示材质二,这样就只需要维护一个箭头,同时移动的时候只需要改shader中传入的A'参数就可以了。恩,很完美,方便使用,一般用起来方便懒的方法,写起了都有些费劲。别问我怎么知道的~~
想好了就动手做
目测原来会的固定功能shader无法实现判断的功能,需要直接写顶点着色器和片段着色器,基础有限就有恶补。涉及到图形图像shader这方面的资料少之又少,中文的就更不多了。推荐大家两个不过的博客,两位大佬也都是出过书的,大家也可以看看:
浅墨的Unity3D
candycat
Shader的实现代码不算复杂,该有的东西也都有,注释也写的很清楚,算是个不错的入门作业,需要的同学可以拿走,记得顺手点个赞哦
Shader "Custom/双色Shader"
{
//属性
Properties
{
_MainTex("MainTex(RGBA)", 2D) = "white" {} //材质1
_GrayTex("GrayTex(RGBA)",2D) = "white" {} //材质2
_CurrentPos("CurrentPos",Range(0,1)) = 1 //当前位置
}
SubShader
{
LOD 100
Cull Off Lighting Off ZWrite Off ZTest Always
Blend SrcAlpha OneMinusSrcAlpha
Tags
{
"Queue" = "Overlay"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
}
Pass{
CGPROGRAM
#pragma vertex vert //定义顶点着色器处理单元
#pragma fragment frag //定义片段着色器处理单元
#include "UnityCG.cginc"
//变量定义
uniform sampler2D _MainTex;
uniform sampler2D _GrayTex;
uniform fixed _CurrentPos;
uniform fixed4 _MainTex_ST;
//顶点输入结构
struct vertexInput {
fixed4 vertex : POSITION;
fixed4 texcoord0 : TEXCOORD0;
};
//片段输入结构(顶点输出)
struct fragmentInput {
fixed4 position : SV_POSITION;
fixed4 texcoord0 : TEXCOORD0;
fixed2 uv:_MainTex_ST;
};
//顶点着色器处理单元
fragmentInput vert(vertexInput i) {
fragmentInput o;
o.position = UnityObjectToClipPos(i.vertex); //转换物体空间到相机空间
o.texcoord0 = i.texcoord0;
o.uv = TRANSFORM_TEX(i.texcoord0, _MainTex); //应用材质的Tilling和offset属性
return o;
}
//片段着色器处理单元
fixed4 frag(fragmentInput i) : SV_Target{
//判断
if(i.texcoord0.y >= _CurrentPos)
return tex2D(_GrayTex, i.uv);
else
return tex2D(_MainTex, i.uv);
}
ENDCG
}
}
}
为了优化性能,同时游戏里的需求也不高,所有进度都为fixed,具体项目中可以更具需要进行实际修改。
结语
该学的东西还是要学,总是无法回避的,谁让选择了程序员这条路,就是一条终生学习的路。路上的兄弟共勉之。加油。