0x00 背景
开发环境:win10 & unity2018.4.1f & unity5.4.6,本项目不使用HDR和抗锯齿。
项目上线了windows平台的项目(别问我为什么,咱也不敢说,咱也不敢问),由Unity5.4.6升级到Unity2018的过程中,遇到了各种各样的坑,本文为避坑指南1。由于查这几个问题查到吐血,前后用了3天的时间,本文充满了怨气,行文非常啰嗦,需要快速解决问题的,可以直接拉到最后看结论。

0x01 法线贴图

项目在unity2018出了新的android和IOS的包替换之后,想起来还有个windows平台还没有换包,同样的工程,Switch to PC,出包,然后噩梦就来了,QA反馈了新手引导战斗中一个特效变黑的问题。

unity在ios上启动黑屏的时间很长 为什么unity打开黑屏_unity在ios上启动黑屏的时间很长


查看这个特效的shader,发现计算法线的部分不规范

fixed4 frag(v2f i):COLOR
            {
                //Fragment Code
                float4 col = tex2D(_MainTex, i.texcoord);
                clip(col.a - 0.05);
                float4 mask = tex2D(_MaskTex, i.texcoord);
                float4 normalTex = tex2D(_NormalTex, i.texcoord);
                float3 normalR = UnpackNormal(normalTex);
                // 以下是原来计算法线的代码,推断是shaderforge之类的软件自动生成的,替换成unpacknormal之后显示即正常了
                // float3 normalR = float3( 2.0 * normalTex.rg - 1.0, 0.0);        
                // normalR.z = sqrt(1 - pow(dot(normalR, normalR), 2.0));

0x02 Graphics设置

QA继续反馈,下图中的矩形区域中应该显示数码兽形象而不应该是黑色。本以为还是法线惹的祸,排查之后,发现这里并没有使用法线贴图。

unity在ios上启动黑屏的时间很长 为什么unity打开黑屏_unity在ios上启动黑屏的时间很长_02


翻来覆去,发现由于unity5.4.6升级到unity2018后,Graphics设置发生了变化,pc平台下的默认设置恢复成了default(下图左),项目原本的设置应该为下图右。

unity在ios上启动黑屏的时间很长 为什么unity打开黑屏_抗锯齿_03


由于开启了HDR,颜色值的计算可能会超出[0,1]的范围,导致最终结果显示为黑色。关于HDR后续还会细说。

修改设置后,重新打包,进入游戏。It’s ok now!0x03 MSAA(多重采样抗锯齿)

QA继续反馈,进入副本会黑屏。我也很无奈…继续看问题:

unity在ios上启动黑屏的时间很长 为什么unity打开黑屏_unity黑屏_04


然而通过FrameDebugger抓drawcall发现,图中黑屏的部分已经被正确渲染出来了,不知道被什么东西挡住了

drawcall1:

unity在ios上启动黑屏的时间很长 为什么unity打开黑屏_抗锯齿_05


drawcall2:

unity在ios上启动黑屏的时间很长 为什么unity打开黑屏_msaa_06









后来看到这两篇文章:

https://forum.unity.com/threads/allow-hdr-creating-huge-decrease-in-performance.521483/https://forum.unity.com/threads/game-rendering-as-black-in-unity-2017-1-on-galaxy-s6-when-hdr-is-enabled.494102/

不由得又开始打HDR的主意,然而设置中已经关了HDR,哪里还会有呢?会不会是场景同学做的新场景的Camera中打开了HDR?于是写了个脚本查了一下,并没有。

然而却发现了一个新的嫌疑对象:MSAA,由于在设置中已经关闭了抗锯齿,可以看到下面有一行warning:告诉你,因为你关闭了抗锯齿,MSAA即使打开也没用。总觉得这里有种此地无银三百两的感觉呢?

unity在ios上启动黑屏的时间很长 为什么unity打开黑屏_unity黑屏_07


为什么怀疑MSAA呢?我也不知道,也许就是男人的第六感吧!顺手google了一下MSAA和HDR:

https://issuetracker.unity3d.com/issues/lwrp-msaa-does-not-work-when-allow-hdr-is-disabledunity在ios上启动黑屏的时间很长 为什么unity打开黑屏_unity黑屏_08

没想到你竟然是这样的MSAA,居然会在HDR生效之后,才生效!!

然而,场景上的Camera并没有Allow HDR的啊,上面用脚本检查过了。

那么问题来了,什么时候MSAA和HDR才能在一起呢?

百思不得其解,于是又开始用FrameDebugger抓drawcall玩,看到这样的图景:


这分明是3个camera的绘制结果,然而场景中只有一个camera,别的camera哪来的?

这时突然反应过来,camera除了随场景创建之外,还有另一种情况,那就是代码动态创建!!!

在项目中搜索

AddComponent<Camera>()

看到了这些结果:

unity在ios上启动黑屏的时间很长 为什么unity打开黑屏_unity黑屏_09


其中最醒目的必然是UICamera了(当前项目使用UICamera来渲染所有的2D UI)

unity在ios上启动黑屏的时间很长 为什么unity打开黑屏_msaa_10


在创建之后并没有MSAA和HDR的踪迹,难道是我的错觉?默认是false?空谈误国,实干兴邦!于是打印log查看,结果allowHDR和allowMSAA的默认值都是true.

我这里只想发黑人问号脸?Excuse me ??? 还有这样的操作?默认给开启HDR和MSAA,不可能的,我在Unity的设置中中已经关闭了,这里Camera默认值为true会生效吗?然而事实很残酷,是的,确实有效。绕过了Unity的设置。What the fuck?!!

不过好奇的我,不太明白为什么在老版本上(unity5.4.6)并没有这个问题,于是我发现:

unity在ios上启动黑屏的时间很长 为什么unity打开黑屏_抗锯齿_11


好的,unity这一波操作真的是猛如虎!!我服了。

0x04 结论

  • 检查场景中的Camera有没有同时开启HDR和MSAA,脚本拿去不谢。
[MenuItem("Assets/GameTools/检查所有的Camera", false, 10)]
    static void CheckSceneCameraEnableHDRAndMSAA()
    {
        //找到所有的场景文件
        string[] scenes = AssetDatabase.FindAssets("t:Scene", new string[] {  "Assets/ArtContent/Scene" });
        for (int i = 0; i < scenes.Length; i++)
        {
            string path = AssetDatabase.GUIDToAssetPath(scenes[i]);
            UnityEngine.SceneManagement.Scene scene =  CheckSceneReference.GetScene(path);
            
            GameObject[] gos = scene.GetRootGameObjects();
            for (int j = 0; j < gos.Length; j++)
            {
                Camera cam = gos[j].GetComponentInChildren<Camera>();
                if (cam != null && cam.allowHDR && cam.allowMSAA)
                {
                    Debug.Log("CheckSceneCameraEnableHDRAndMSAA Find GameObjects: " +  path + ", root_name: "+ gos[j].name);
                }
            }
        }
    }
  • 检查所有动态添加Camera的脚本,有没有设置
m_UICam.allowHDR = false;
         m_UICam.allowMSAA = false;