unity游戏开发之NGUI的UISprite染色

欢迎来到unity学习unity培训、unity企业培训教育专区,这里有很多U3D资源U3D培训视频U3D教程U3D常见问题U3D项目源码,我们致力于打造业内unity3d培训、学习第一品牌。

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

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

下面给出这个解决方案的流程图,如下图所示

下面写一个例子,通过按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. SubShader {
  7. Tags { "Queue" = "Transparent+10" }
  8. LOD 200
  9. Pass
  10. {
  11. ZWrite On
  12. ZTest Off
  13. Blend SrcAlpha OneMinusSrcAlpha
  14. Lighting Off
  15. //Cull Off
  16. CGPROGRAM
  17. #pragma vertex vert
  18. #pragma fragment frag
  19. #include "UnityCG.cginc"
  20. sampler2D _MainTex;
  21. fixed4 _Color;
  22. float _ColorCtrl;
  23. struct v2f
  24. {
  25. float4  pos : SV_POSITION;
  26. float2  uv : TEXCOORD0;
  27. };
  28. float4 _MainTex_ST;
  29. v2f vert (appdata_base v)
  30. {
  31. v2f o;
  32. o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
  33. o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
  34. return o;
  35. }
  36. fixed4 frag (v2f i) : COLOR
  37. {
  38. fixed4 texcol = tex2D (_MainTex, i.uv);
  39. result = texcol * _Color;
  40. result.a = texcol.a;
  41. return result;
  42. }
  43. ENDCG
  44. }
  45. }
  46. }

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

 
 

灰化效果比较特殊,颜色值不能弄成(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. Tags
  10. {
  11. "Queue" = "Transparent+10"
  12. }
  13. Pass
  14. {
  15. Lighting Off
  16. ZTest Off
  17. Cull Off
  18. Blend SrcAlpha OneMinusSrcAlpha
  19. CGPROGRAM
  20. #pragma vertex vert
  21. #pragma fragment frag
  22. #include "UnityCG.cginc"
  23. sampler2D _MainTex;
  24. sampler2D _AlphaTex;
  25. half4 _Color;
  26. struct v2f
  27. {
  28. float4  pos : SV_POSITION;
  29. float2  uv : TEXCOORD0;
  30. };
  31. half4 _MainTex_ST;
  32. half4 _AlphaTex_ST;
  33. v2f vert (appdata_base v)
  34. {
  35. v2f o;
  36. o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
  37. o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
  38. return o;
  39. }
  40. half4 frag (v2f i) : COLOR
  41. {
  42. half4 texcol = tex2D (_MainTex, i.uv);
  43. 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);
  44. return result;
  45. }
  46. ENDCG
  47. }
  48. }
  49. }

接着就是要修改Ngui的UISprite源码,添加一个渲染的材质WinterMaterial, 在读取material值的时候,如果有自定义的渲染材质,则需要读取自定义渲染材质

[csharp]

  1. public override Material material
  2. {
  3. get
  4. {
  5. Material mat = base.material;
  6. if (mat == null)
  7. {
  8. mat = (mAtlas != null) ? mAtlas.spriteMaterial : null;
  9. mSprite = null;
  10. material = mat;
  11. if (mat != null) UpdateUVs(true);
  12. }
  13. if (WinterMaterial!=null)
  14. {
  15. return WinterMaterial;
  16. }
  17. else
  18. {
  19. return mat;
  20. }
  21. }
  22. }

然后,添加以下几个染色函数

[csharp]

  1. public void ShowAsRed()
  2. {
  3. ShowAsColor("file:///D:/u3dAB/WinterRedMat.assetbundle", WinterRedMat);
  4. }
  5. public void ShowAsGreen()
  6. {
  7. ShowAsColor("file:///D:/u3dAB/WinterGreenMat.assetbundle", WinterGreenMat);
  8. }
  9. public void ShowAsBlue()
  10. {
  11. ShowAsColor("file:///D:/u3dAB/WinterBlueMat.assetbundle", WinterBlueMat);
  12. }//需要添加染色值的,则需要添加材质和染色函数
  13. public void ShowAsGray()
  14. {
  15. 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. GameObject panelObj = null;
  52. public bool selfRefresh = true;
  53. void RefreshPanel(GameObject go)
  54. {
  55. if (!selfRefresh)
  56. return;
  57. if (panelObj == null)
  58. {
  59. panelObj = GetMostClosePanel(go.transform);
  60. }
  61. if (panelObj != null)
  62. {
  63. panelObj.GetComponent<UIPanel>().enabled = false;
  64. panelObj.GetComponent<UIPanel>().enabled = true;
  65. go.SetActive(false);
  66. go.SetActive(true);
  67. }
  68. }

主程序调用方法

[csharp]

  1. using UnityEngine;
  2. using System.Collections;
  3. public class ChangeColorExample : MonoBehaviour {
  4. private UISprite m_kSprite;
  5. void Start ()

[csharp]

  1. {
  2. GameObject obj = GameObject.Find("Root/Camera/Anchor/Panel/Sprite");
  3. m_kSprite = obj.GetComponent<UISprite>();
  4. void Update()
  5. {
  6. if (Input.GetKeyUp(KeyCode.R))
  7. {
  8. m_kSprite.ShowAsRed();
  9. }
  10. else if (Input.GetKeyUp(KeyCode.G))
  11. {
  12. m_kSprite.ShowAsGreen();
  13. }
  14. else if (Input.GetKeyUp(KeyCode.B))
  15. {
  16. m_kSprite.ShowAsBlue();
  17. }
  18. else if (Input.GetKeyUp(KeyCode.Y))
  19. {
  20. m_kSprite.ShowAsGray();
  21. }
  22. }

核心的代码部分如上图所示,这样就可以通过按键rgby来切换染红绿蓝灰的效果。效果如上面第一幅图所示。

总结,用程序来实现动态染色可以高度复用资源,节省空间大小。但是资源的划分需要注意的一点是,如果在一个UIPanel里面有两个不同图集需要用同一个材质进行染色,那么会出现其中的一个出现纹理错乱的现象。目前的解决方案是做多一个颜色值相同的材质,不同的图集用不同的染色材质,这样可以解决上面说的纹理错乱现象。另一个方法是设法把不同的图集弄到一块,这样也可以避免这个问题。

更多精彩请点击 http://www.gopedu.com/

时间: 2024-11-08 10:22:42

unity游戏开发之NGUI的UISprite染色的相关文章

Unity3D游戏开发之Unity打包APK

Unity3D游戏开发之Unity打包APK 1.安装JDK 2.配置JDK 3.在Paht的变量值后面加分号,把D:\android\adt-bundle-windows-x86-20131030\sdk\tools放在Path后面.[狗刨学习网] 4.点击菜单栏中的Edit-->Preferences 看Android SDK Location这个选项 浏览你的模拟器路径. 5.点击 File-Build Settings 然后再 点击Add Current 添加你的场景.再 点击Switc

[Unity3D]Unity3D游戏开发之Lua与游戏的不解之缘(下)

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 喜欢我的博客请记住我的名字:秦元培,我的博客地址是blog.csdn.net/qinyuanpei. 转载请注明出处,本文作者:

Unity3D游戏开发之Lua与游戏的不解之缘终结篇:UniLua热更新完全解读

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 喜欢我的博客请记住我的名字:秦元培,我的博客地址是blog.csdn.net/qinyuanpei. 转载请注明出处,本文作者:

[Unity3D]Unity3D游戏开发之从Unity3D到Eclipse

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 喜欢我的博客请记住我的名字:秦元培,我的博客地址是blog.csdn.net/qinyuanpei. 转载请注明出处,本

Unity3D游戏开发之Unity3D动画与Mecanim动画系统

Unity3D游戏开发之Unity3D动画与Mecanim动画系统 欢迎来到unity学习.unity培训.unity企业培训教育专区,这里有很多U3D资源.U3D培训视频.U3D教程.U3D常见问题.U3D项目源码,[狗刨学习网]unity极致学院,致力于打造业内unity3d培训.学习第一品牌. Mecanim是Unity新增的动画系统,其功能强大而灵活,让人类和非人类角色栩栩如生.Mecanim的重定向极大的提供了工作效率,而且占用极少CPU周期.使用从Unity资源商店找到的动画资源,或

[Unity3D]Unity3D游戏开发之Lua与游戏的不解之缘(中)

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 喜欢我的博客请记住我的名字:秦元培,我的博客地址是blog.csdn.net/qinyuanpei. 转载请注明出处,本文作者:

Unity3D游戏开发之3DMAX 灯光

Unity3D游戏开发之3DMAX 灯光 欢迎来到unity学习.unity培训.unity企业培训教育专区,这里有很多U3D资源.U3D培训视频.U3D教程.U3D常见问题.U3D项目源码,[狗刨学习网]unity极致学院,致力于打造业内unity3d培训.学习第一品牌. 一.3DMAX 五种光源 1.Ommi Light 泛光灯:可以从一点向四周均匀照射的点光源. 2.Target Spotlight 目标聚光灯:一种投射光束,影响光束内被照射的物体,可以投影 阴影,照射范围可以指定. 3.

iOS游戏开发之UIDynamic

iOS游戏开发之UIDynamic 简介 什么是UIDynamic UIDynamic是从iOS 7开始引入的一种新技术,隶属于UIKit框架 可以认为是一种物理引擎,能模拟和仿真现实生活中的物理现象重力.弹性碰撞等现象 物理引擎的价值 广泛用于游戏开发,经典成功案例是“愤怒的小鸟” 让开发人员可以在远离物理学公式的情况下,实现炫酷的物理仿真效果 提高了游戏开发效率,产生更多优秀好玩的物理仿真游戏 知名的2D物理引擎 Box2d Chipmunk 使用步骤 要想使用UIDynamic来实现物理仿

Cocos2d-x游戏开发之lua编辑器 subime 搭建,集成cocos2dLuaApi和自有类

Sublime Text http://baike.baidu.com/view/10701920.htm?from_id=8130415&type=syn&fromtitle=Sublime&fr=aladdin 简介 Sublime Text 是一个代码编辑器(Sublime Text 2是收费软件,但可以无限期试用),也是HTML和散文先进的文本编辑器.Sublime Text是由程序员Jon Skinner于2008年1月份所开发出来,它最初被设计为一个具有丰富扩展功能的V