Unity循環長箭頭加強版

需求變更

我哩個天天,需求這東西就是你做完一個又回有新的一個,做了個普通的,就會讓你做高級的。
這不之前做了循環長箭頭,領導就說要分段顯示,怎么個分段顯示咧?能夠顯示兩種顏色的箭頭,一種是你還沒有走完的路,一種是已經走完的。恩,需求很簡單,容我思考下人生。

看來又要學習啦

對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,具體項目中可以更具需要進行實際修改。

結語

該學的東西還是要學,總是無法回避的,誰讓選擇了程序員這條路,就是一條終生學習的路。路上的兄弟共勉之。加油。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容