【填坑】关于 Unity UGUI 发布到安卓上UI丢失的问题
前言:
最近遇到一个及其灵异的问题,那就是工程发布成apk之后,UI(一部分)没了!就如下面这个问题描述得一样:
https://bbs.csdn.net/topics/392404062?page=1
还有一个 同学也遇到了一样的问题:
https://zhidao.baidu.com/question/501322232914356804.html
都是UI丢失了,有的 丢了一部分,有的全丢了;也都是发布到安卓有问题,在编辑器下 屁事没有。这个就 很灵异啊,和逻辑上想得不一致啊。而且更为诡异的是,我发现我丢失的UI其实并不是真的“没有”了。因为那些UI控件都是存在的,比如某个按钮,点击他还是能点击到的,就是看不见,就像隐身了一样。
是不是很神奇?更神奇的是,我的现象是第一次安装的时候无比正常,而退出后再进就会出现上述问题,必现。这个神奇的Bug 一直困扰了我很久。毕竟这个问题不报错,编辑器下也无法复现。
正文:
1、问题分析
后来经过分析(按钮的点击事件可以响应但是并不能看到),怀疑是因为UI的材质球(Shader)的问题。我发现丢失的UI都是没有使用材质球的,而存在的UI都是使用了我自定义的材质球。理论上在UI不使用材质球的时候,Unity会给他一个Default UI Material 的材质球。但是如果这个机制没有生效,或者赋值给的材质球变成了standard,那么就算在编辑器下也会出现同样的问题了。
后来实验了几次,发现确实是这样。如果使用自定义的材质球,就不会有这个问题。而如果不使用材质球,他就一如既往地消失了。值得一提的是,如果直接把官网上的UI/Defaut Shader 拷贝下来做成材质球来使用,上述问题依然存在。 所以肯能是因为其某几行判定的关系才 导致这样的问题。但是把这个Shader稍作改造使用的话,确实能修复这个问题。只能说真的很神奇。
2、修复策略
到这里就有方法了:在UI丢失的部分,将他们的材质球全部更换成我们自定义的,与UI/Defaut功能类似的材质球即可。
3、自定义材质球
创建一个材质球,然后让他使用我们自定义的Shader:
[code]Shader "UI/UIDefault" { Properties { [PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {} _Color("Tint", Color) = (1,1,1,1) _ColorMask("Color Mask", Float) = 15 } SubShader { Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane" "CanUseSpriteAtlas" = "True" } Cull Off Lighting Off ZWrite Off ZTest Off Blend SrcAlpha OneMinusSrcAlpha ColorMask[_ColorMask] Pass { Name "Default" CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 2.0 #include "UnityCG.cginc" #include "UnityUI.cginc" struct appdata_t { float4 vertex : POSITION; float4 color : COLOR; float2 texcoord : TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; fixed4 color : COLOR; float2 texcoord : TEXCOORD0; float4 worldPosition : TEXCOORD1; }; fixed4 _Color; fixed4 _TextureSampleAdd; float4 _ClipRect; v2f vert(appdata_t IN) { v2f OUT; OUT.worldPosition = IN.vertex; OUT.vertex = UnityObjectToClipPos(OUT.worldPosition); OUT.texcoord = IN.texcoord; OUT.color = IN.color * _Color; return OUT; } sampler2D _MainTex; fixed4 frag(v2f IN) : SV_Target { half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color; return color; } ENDCG } } }
之后把这个东西赋值给会丢失的UI上面就可以了。
4、自动化脚本
当然发现的时候有点晚,所以有很多UI需要替换。当然自己做 太麻烦了,所以写了个脚本来自动化他。
[code] using UnityEngine; using UnityEngine.UI; /// <summary> /// UI 的编辑器帮助类,用于各种的自动化编辑; /// </summary> public class UIEditorHelper : MonoBehaviour { /// <summary> /// UI默认的材质; /// </summary> [ContextMenuItem("替换UI材质球", "SetDefautMat")] public Material UIDefaultMat; /// <summary> /// 设置成默认材质; /// </summary> [ExecuteInEditMode] public void SetDefautMat() { if (UIDefaultMat == null) { Debug.LogError("选择的默认材质球为空!"); return; } //获取所有的图片和文本; Image[] mArrImg = transform.GetComponentsInChildren<Image>(); Text[] mArrText = transform.GetComponentsInChildren<Text>(); Debug.Log("图片数量:" + mArrImg.Length); Debug.Log("文本数量:" + mArrText.Length); //如果他们身上没有材质球(使用的默认材质球),那么替换成我们选定的材质球; for (int i = 0; i < mArrImg.Length; i++) { var img = mArrImg[i]; if (img.material == img.defaultMaterial) { //Mask不能用这个材质球,所以跳过; if (img.transform.GetComponent<Mask>() == null) img.material = UIDefaultMat; } } for (int i = 0; i < mArrText.Length; i++) { var text = mArrText[i]; if (text.material == text.defaultMaterial) { text.material = UIDefaultMat; } } Debug.Log("替换完成!"); } }
然后在 编辑器下把这个脚本挂载在需要替换的UI的父对象上面,在选定刚才的材质球之后右键替换。这样就能一次性替换所有的没有设定材质球的UI控件了。
这样就完成了!替换之后的UI在真机上运转就正常了。
后记:
这个Bug真的是神奇,对于某一个安装包,他是必现的。但是并不是每一次出的包都有这个问题,有时几周前出的版本就 没有这个问题,而且使用的材质球也是Unity默认的。我记得上一次出现这个Bug的时候还是在几个月前,之后不知道怎么弄的又 没有了。最近 又出现了,这次虽然修复了看似一劳永逸,但实际上问题 还是蛮多的。
而且并不是所有不使用材质球的UI都有这个问题,有的UI同样没有 使用任何材质球,也没有这个问题。但是没有使用材质球却“隐身”的UI可以用这个办法来修复。Emmmmm……总之很奇怪。
阅读更多- 关于高通AR vuforia 4.2.3在UNITY5.0中发布到安卓白屏的问题
- 关于Unity5.5+中的UGUI的ImageMask组件在安卓设备不能正常显示的问题的解决方案
- 关于cocos2d 发布安卓版本中 遇到的问题
- 关于Unity中的UGUI优化,你可能遇到这些问题
- Unity UGUI —— 鼠标穿透UI问题(Unity官方的解决方法)
- 关于Unity里面UGUI的Text字体无法显示以及尺寸无法改变的问题
- 关于Unity发布Webgl在chrome中打开报错的问题
- <Unity UGUI><EasyTouch> 使用EasyTouch, 摇杆在Dynamic模式下,点击UI控件也会弹出的问题解决
- Unity UGUI 鼠标穿透UI问题
- 关于Unity5 发布到安卓后帧数低的问题
- 关于Unity发布iOS平台代码混淆问题
- 关于unity发布的一些问题
- Unity发布安卓包之后出现dll无法调用问题
- [转]UGUI —— 鼠标穿透UI问题(Unity官方的解决方法)
- unity 关于手机客户端的本地文件储存问题 文件路径--适用于安卓手机
- win10 64位 unity2018.1.18版本 安装安卓SDK 解决安卓SDK无法更新和发布apk诸多问题解决心得
- Unity UGUI —— 鼠标穿透UI问题(Unity官方的解决方法)
- Unity发布安卓包之后出现dll无法调用问题
- 关于 Unity UI 中 GraphicRaycaster.Raycast 数量巨大的问题
- Unity UGUI —— 鼠标穿透UI问题(Unity官方的解决方法)