zoukankan      html  css  js  c++  java
  • unity游戏开发之NGUI的UISprite染色



          游戏的UI开发中常常会遇到染色问题。比如button失效变灰的效果,同一个道具通过策划表配的颜色值染上红绿蓝紫等颜色,效果例如以下



           最笨最挫的方法当然是让美术多出几个资源图。这种一个缺点是浪费资源,在手游上资源的大小显得尤为重要。并且不好维护和复用。改动一个资源须要同一时候改动其它颜色的多个同类资源。一种比較好的解决方式是通过更换渲染的材质,用染色材质取代原来的材质。然后把原来材质的主纹理和透明纹理赋值给新的材质。这样就能够实现用程序动态切换颜色。并且仅仅须要一个基础资源。节省资源大小。easy维护。

    以下给出这个解决方式的流程图。例如以下图所看到的



           以下写一个样例,通过按r键,g键。b键。y键来动态切换染红色,染绿色。染蓝色,灰化效果。项目的GameObject图例如以下


    染色普通颜色的材质相应的shader例如以下

    [plain]
    1. Shader "Winter/ChangeColor" {  
    2.     Properties {  
    3.         _MainTex ("Base (RGB)", 2D) = "white" {}  
    4.         _Color ("Main Color", Color) = (1,1,1,1)  
    5.           
    6.     }  
    7.     SubShader {  
    8.         Tags { "Queue" = "Transparent+10" }  
    9.         LOD 200  
    10.          Pass  
    11.          {  
    12.          ZWrite On  
    13.          ZTest Off  
    14.   
    15.   
    16.             Blend SrcAlpha OneMinusSrcAlpha  
    17.             Lighting Off  
    18.             //Cull Off  
    19.             CGPROGRAM  
    20.             #pragma vertex vert  
    21.             #pragma fragment frag  
    22.   
    23.             #include "UnityCG.cginc"  
    24.   
    25.             sampler2D _MainTex;  
    26.             fixed4 _Color;  
    27.             float _ColorCtrl;  
    28.   
    29.             struct v2f   
    30.             {  
    31.                 float4  pos : SV_POSITION;  
    32.                 float2  uv : TEXCOORD0;  
    33.             };  
    34.   
    35.             float4 _MainTex_ST;  
    36.   
    37.             v2f vert (appdata_base v)  
    38.             {  
    39.                 v2f o;  
    40.                 o.pos = mul (UNITY_MATRIX_MVP, v.vertex);  
    41.                 o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);  
    42.                 return o;  
    43.             }  
    44.   
    45.             fixed4 frag (v2f i) : COLOR  
    46.             {  
    47.                 fixed4 texcol = tex2D (_MainTex, i.uv);  
    48.                 result = texcol * _Color;  
    49.                 result.a = texcol.a;  
    50.   
    51.                 return result;  
    52.             }  
    53.             ENDCG  
    54.          }  
    55.     }   
    56. }  

           不同颜色要创建不同的材质,而且设置其颜色值,例如以下

       

    灰化效果比較特殊,颜色值不能弄成(0,0,0,1)或者(1,1,1,1)。

    须要用到灰化函数

    终于颜色的r = (原图r+原图g+原图b)*0.33

    终于颜色的g = (原图r+原图g+原图b)*0.33 

    终于颜色的b = (原图r+原图g+原图b)*0.33

    终于颜色的透明值 = 原图的透明值

    依据上面。有以下的灰化shader

    [plain]
    1. Shader "Winter/Gray"   
    2. {  
    3.     Properties   
    4.     {  
    5.          _MainTex ("Base (RGB)", 2D) = "white" { }  
    6.     }  
    7.     SubShader  
    8.     {  
    9.   
    10.          Tags  
    11.          {  
    12.             "Queue" = "Transparent+10"  
    13.          }  
    14.          Pass  
    15.          {  
    16.             Lighting Off  
    17.             ZTest Off  
    18.             Cull Off  
    19.             Blend SrcAlpha OneMinusSrcAlpha  
    20.             CGPROGRAM  
    21.             #pragma vertex vert  
    22.             #pragma fragment frag  
    23.   
    24.             #include "UnityCG.cginc"  
    25.   
    26.             sampler2D _MainTex;  
    27.             sampler2D _AlphaTex;  
    28.             half4 _Color;  
    29.           
    30.             struct v2f   
    31.             {  
    32.                 float4  pos : SV_POSITION;  
    33.                 float2  uv : TEXCOORD0;  
    34.             };  
    35.   
    36.             half4 _MainTex_ST;  
    37.             half4 _AlphaTex_ST;  
    38.   
    39.             v2f vert (appdata_base v)  
    40.             {  
    41.                 v2f o;  
    42.                 o.pos = mul (UNITY_MATRIX_MVP, v.vertex);  
    43.                 o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);  
    44.                 return o;  
    45.             }  
    46.   
    47.             half4 frag (v2f i) : COLOR  
    48.             {  
    49.                 half4 texcol = tex2D (_MainTex, i.uv);  
    50.                 half4 result = half4((texcol.r + texcol.g + texcol.b) * 0.33f,(texcol.r + texcol.g + texcol.b) * 0.33f,(texcol.r + texcol.g + texcol.b) * 0.33f,texcol.a);  
    51.                 return result;  
    52.             }  
    53.             ENDCG  
    54.          }  
    55.     }  
    56. }   

           接着就是要改动Ngui的UISprite源代码。加入一个渲染的材质WinterMaterial, 在读取material值的时候。假设有自己定义的渲染材质,则须要读取自己定义渲染材质

    [csharp]
    1. public override Material material  
    2.     {  
    3.         get  
    4.         {  
    5.             Material mat = base.material;  
    6.   
    7.             if (mat == null)  
    8.             {  
    9.                 mat = (mAtlas != null) ?

       mAtlas.spriteMaterial : null;  

    10.                 mSprite = null;  
    11.                 material = mat;  
    12.                 if (mat != null) UpdateUVs(true);  
    13.             }  
    14.               
    15.             if (WinterMaterial!=null)  
    16.             {  
    17.                 return WinterMaterial;  
    18.             }  
    19.             else  
    20.             {  
    21.                 return mat;  
    22.             }  
    23.         }  
    24.     }  

    然后。加入下面几个染色函数

    [csharp]
    1. public void ShowAsRed()  
    2. {  
    3.     ShowAsColor("file:///D:/u3dAB/WinterRedMat.assetbundle", WinterRedMat);  
    4. }  
    5.   
    6. public void ShowAsGreen()  
    7. {  
    8.     ShowAsColor("file:///D:/u3dAB/WinterGreenMat.assetbundle", WinterGreenMat);  
    9. }  
    10.   
    11. public void ShowAsBlue()  
    12. {  
    13.     ShowAsColor("file:///D:/u3dAB/WinterBlueMat.assetbundle", WinterBlueMat);  
    14. }//须要加入染色值的,则须要加入材质和染色函数  
    15. public void ShowAsGray()  
    16. {  
    17.     StartCoroutine(<span style="font-family: Arial, Helvetica, sans-serif;">//自己定义的www函数</span>  
    [csharp]
    1.         IzUtils.LoadAB("file:///D:/u3dAB/WinterGrayMat.assetbundle", (w) =>  
    2.         {//assetbundle是打包好的材质  
    3.             Material mat = w.assetBundle.mainAsset as Material;  
    4.             mat.mainTexture = material.mainTexture;  
    5.             WinterMaterial = mat;  
    6.             w.assetBundle.Unload(false);  
    7.             RefreshPanel(gameObject);      
    8.         })  
    9.     );   
    10. }  
    11. private void ShowAsColor(string matName, Material colorMaterial)  
    12. {  
    13.     if (WinterMaterial == null || colorMaterial != WinterMaterial)  
    14.     {  
    15.         if (colorMaterial == null)  
    16.         {  
    17.             StartCoroutine(  
    18.                 IzUtils.LoadAB(matName, (w) =>  
    19.                 {  
    20.                     Material mat = w.assetBundle.mainAsset as Material;  
    21.              mat.mainTexture = material.mainTexture;  
    22.                     colorMaterial = mat;  
    23.                     WinterMaterial = mat;  
    24.                     w.assetBundle.Unload(false);      
    25.                     RefreshPanel(gameObject);  
    26.     })  
    27.             );  
    28.         }  
    29.         else  
    30.         {  
    31.             WinterMaterial = colorMaterial;  
    32.             RefreshPanel(gameObject);  
    33.         }  
    34.     }  
    35. }  
    36. GameObject GetMostClosePanel(Transform rootTrans)  
    37. {  
    38.     if (rootTrans.GetComponent<UIPanel>() != null)  
    39.     {  
    40.         return rootTrans.gameObject;  
    41.     }  
    42.     else if (rootTrans.parent == null)  
    43.     {  
    44.         return null;  
    45.     }  
    46.     else  
    47.     {  
    48.         return GetMostClosePanel(rootTrans.parent);  
    49.     }  
    50. }  
    51.   
    52. GameObject panelObj = null;  
    53. public bool selfRefresh = true;  
    54.   
    55. void RefreshPanel(GameObject go)  
    56. {  
    57.     if (!selfRefresh)  
    58.         return;  
    59.   
    60.     if (panelObj == null)  
    61.     {  
    62.         panelObj = GetMostClosePanel(go.transform);  
    63.     }  
    64.   
    65.     if (panelObj != null)  
    66.     {  
    67.         panelObj.GetComponent<UIPanel>().enabled = false;  
    68.         panelObj.GetComponent<UIPanel>().enabled = true;  
    69.         go.SetActive(false);  
    70.         go.SetActive(true);  
    71.     }  
    72. }  


    主程序调用方法

    [csharp]
    1. using UnityEngine;  
    2. using System.Collections;  
    3.   
    4. public class ChangeColorExample : MonoBehaviour {  
    5.         private UISprite m_kSprite;  
    6.     void Start ()   
    [csharp]
    1.    {  
    2.         GameObject obj = GameObject.Find("Root/Camera/Anchor/Panel/Sprite");  
    3.         m_kSprite = obj.GetComponent<UISprite>();  
    4.   
    5.   
    6. void Update()  
    7. {  
    8.     if (Input.GetKeyUp(KeyCode.R))  
    9.     {  
    10.         m_kSprite.ShowAsRed();  
    11.     }  
    12.     else if (Input.GetKeyUp(KeyCode.G))  
    13.     {  
    14.         m_kSprite.ShowAsGreen();  
    15.     }  
    16.     else if (Input.GetKeyUp(KeyCode.B))  
    17.     {  
    18.         m_kSprite.ShowAsBlue();  
    19.     }  
    20.     else if (Input.GetKeyUp(KeyCode.Y))  
    21.     {  
    22.         m_kSprite.ShowAsGray();  
    23.     }  
    24. }  

    核心的代码部分如上图所看到的,这样就能够通过按键rgby来切换染红绿蓝灰的效果。

    效果如上面第一幅图所看到的。

           总结,用程序来实现动态染色能够高度复用资源,节省空间大小。

    可是资源的划分须要注意的一点是,假设在一个UIPanel里面有两个不同图集须要用同一个材质进行染色,那么会出现当中的一个出现纹理错乱的现象。眼下的解决方式是做多一个颜色值同样的材质。不同的图集用不同的染色材质,这样能够解决上面说的纹理错乱现象。

    还有一个方法是设法把不同的图集弄到一块。这样也能够避免这个问题。


  • 相关阅读:
    深入浅出JavaScript (一)初识
    “0”基础让你学会 GridView (一)
    VS 中PageLayout 属性设置
    ASP.NET Forms身份认证
    教务系统数据库设计 (一)
    深入浅出Javascript(三)创建自定义对象以及属性、方法
    .NET 中的Cache
    深入浅出JavaScript (二) 代码放置位置与执行顺序
    触发器特殊的存储过程
    ASP.NET与JavaScript轻松实现输入信息验证
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/6893801.html
Copyright © 2011-2022 走看看