Unity循环长箭头加强版

作者: 玄猫大人 | 来源:发表于2017-06-19 15:37 被阅读221次

    需求变更

    我哩个天天,需求这东西就是你做完一个又回有新的一个,做了个普通的,就会让你做高级的。
    这不之前做了循环长箭头,领导就说要分段显示,怎么个分段显示咧?能够显示两种颜色的箭头,一种是你还没有走完的路,一种是已经走完的。恩,需求很简单,容我思考下人生。

    看来又要学习啦

    对unity的shader一直没有深入研究,到目前为止都是停留在能用就行的阶段。复杂一点的shader基本也用可视化的编辑插件进行处理,手打的也就能写写固定功能的shader。可视化的插件很方便,所见即所得,缺点是需要微调的时候就麻烦了。固定着色器功能再多也有限,到头来写Shader还是离不开HLSL和CG语言直接写。当然在Unity中,unity为我们包装了ShaderLab的壳子为我们方便的实现需要的功能,同时不至于代码过于的冗余和晦涩。

    同样的Unity提供了官方文档,内容嘛,老规矩全而不细,需要的朋友出门左转,可以翻阅一下:Unity ShaderLab 官方文档

    先想想问题,别急着动手

    当前的需求是分段显示两种不同颜色的箭头,用于区分哪一部分是已经走过的路线,哪一部分是为走过的路线。在这个需求中需要处理两个贴图,用来表现不同的状态。

    方法一:
    常规情况下可以直接制作两个箭头的组件,因为在第一版的基础下已经实现了从点A到点B的箭头。分段显示只要处理点A到中间点A'和A'到B两段就行。

    灵魂画手A->B 灵魂画手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,具体项目中可以更具需要进行实际修改。

    结语

    该学的东西还是要学,总是无法回避的,谁让选择了程序员这条路,就是一条终生学习的路。路上的兄弟共勉之。加油。

    相关文章

      网友评论

      • karma085:一般来说,中间点的uv坐标是0.5, 所以如果这样的话,可以直接用uv.x的值来判断左右就行了
        玄猫大人:实际使用中这个点是需要让程序可以中Tween中控制的,因为箭头分段是为了显示人物移动的情况。至于是uv.x还是uv.y,就看美术出的箭头图的方向了,原理都是一样的

      本文标题:Unity循环长箭头加强版

      本文链接:https://www.haomeiwen.com/subject/iyhmqxtx.html