2019.2版本UI耗时异常分析

侑虎科技

1)2019.2版本UI耗时异常分析
2)如何保留stencil buffer的值
3)Unity使用HTTPS POST的问题
4)透明度混合Alpha值的算法问题
5)场景设置雾效异常


Profiler

Q:我使用UWA GOT Online测试我自己打的Unity Android APK包,版本是Unity 2019.2.6f1 (64-bit),当我勾选多线程渲染和不勾选多线程渲染的情况下,UWA网站分析的BuildBatch CPU均值不同。但是理论上勾选多线程渲染,BuildBatch CPU均值应该低,性能更好才是,但是我勾选了多线程渲染,评测出来的BuildBatch CPU均值反而增高了,这是为什么呢?


开启了多线程渲染


未开启多线程渲染

A:我们测试了空场景下一个文本每秒钟更新的case,在小米5X上测试,发现确实会有很高的BuildBatch耗时。

通过查看Profiler的Timeline视图发现,BuildBatch对应的是上一帧RenderThread的Gfx.PresentFrame,并非UI自身耗时。

而在BuildBatch耗时低的其它帧,这里等待的时间被统计在WaitForTargetFPS中。

相对应的,在BuildBatch耗时高的这一帧,WaitForTargetFPS耗时只有0.01ms。

因此我们认为是Unity在这个版本中出现了Bug,导致的统计异常问题。
该回答由UWA提供


Rendering

Q:请问Unity中Camera的OnRenderImage调用前是不是把stencil buffer的值清掉了?

A:对,Stencil buffer是Depth buffer后8位,opacity画完了就清了。如果你不想清空,有几个办法:

  • OnRenderImage逻辑放到Onpostrender里
  • OnRenderImage逻辑放到Command buffer里
  • 用Command buffer把Depth buffer的内容提前Copy一份暂存(这个套路画Volumetric fog,毛发之类的经常用)

感谢张言丰@UWA问答社区提供了回答


Network

Q:大家有没有2018以前版本的HTTPS POST的解决方案?

现在测试的情况是,使用UnityWebRequest在编辑器上可以过,但是会被降级为HTTP,高版本Android会被ClearText阻止,并且有部分机型在Android添加ClearText权限也无法绕开。

使用C#原生的HttpWebRequest API,Post会收到400错误。确认流里面参数无误,使用UnityWebRequest读参数,然后直接把Uploader里面的bytes复制给HttpWebRequest的上传流,也会收到400。

测试过使用.NET 2.0,没有效果。不知道大家如何解决高版本Android的HTTPS问题?

A:亲测可用:
public static string Post(string url, string obj, int timeoutSeconds = 15)
    {


        if (string.IsNullOrWhiteSpace(url))
            return "";

        Encoding encode = Encoding.UTF8;
        HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url);
        myRequest.ContentType = "application/json;charset=utf-8";
        myRequest.Method = "POST";// HttpUtil.UrlMethod.POST.ToString();
        if (timeoutSeconds < 3)
            timeoutSeconds = 3;

        byte[] bs = null;
        myRequest.Timeout = timeoutSeconds * 1000;
        if (obj != null)
        {
            bs = Encoding.UTF8.GetBytes(obj);
            myRequest.ContentLength = bs.Length;
        }
        else
            myRequest.ContentLength = 0;


        using (Stream reqStream = myRequest.GetRequestStream())
        {
            if (obj != null)
                reqStream.Write(bs, 0, bs.Length);
            reqStream.Close();
        }
        try
        {
            using (HttpWebResponse response = (HttpWebResponse)myRequest.GetResponse())
            {
                using (StreamReader reader = new StreamReader(response.GetResponseStream(),encode))
                {
                    var responseData = reader.ReadToEnd().ToString();
                    return responseData;
                }
            }
        }
        catch (WebException ex)
        {
            throw ex;
        }
    }
感谢郑骁@UWA问答社区提供了回答

Rendering

Q:我比较关心Alpha值的算法。

假如有两个颜色,S=1,0,0,0.5,D=0,0,0,1。按照PS里的透明度算法Oa=1-(1-Sa)(1-Da)来算,最终颜色O的Alpha值为1-(1-0.5)(1-1)=1,如图1。

按照Shader中的Alpha blended的算法,Oa=Sa*Sa+Da(1-Sa),最终颜色O的Alpha值为0.25+0.5=0.75,不知道是不是我自己哪里算错了。

总之,经过实际测试,PS和Unity里模拟出的效果是一致的,如图2。也就是说按照Alpha blended混合方式混合出来的Alpha值也应该是1才对。

Unity中的Shader以及颜色设置没有任何问题,两个颜色的绘制顺序也是正确的,如果有问题,是不会跟PS里的效果一样的。只是我自己计算的时候,不知道哪里出了问题。


图1


图2

A1:一般颜色混合只针对RGB,Alpha并不参与混合公式的计算。也就是说对于Alpha,你Shader输出是多少就是多少。ScreenBuffer的Alpha并不会因为把它设置为0.5,就变成半透明,所以有很多效果可以hack这个Alpha通道来传递数据。
感谢fubbi1000@UWA问答社区提供了回答

A2:Shader中的Alpha的输出是可以自己定义的,你可以看看Blend那一行是不是有逗号,逗号后就是Alpha通道的计算方式:
Blend SrcAlpha OneMinusSrcAlpha, One One
感谢王宇@UWA问答社区提供了回答


Rendering

Q:场景设置雾效开启状态,通过AssetBundle包加载的资源没有雾的效果。Graphics里的fog的配置也试过了,没效果;在PC上是正常的,手机上没效果。

A:Graphics里的fog的配置只能保证变体不会被这里剔除,并不能保证你打AssetBundle的时候变体一定不丢失。修改了Graphics之后,一定要删除所有AssetBundle,重新打包才能生效,增量打包AssetBundle无效。其次,最好使用ShaderVariants,保证打包Shader的时候,变体一定存在(勾选相关fog宏定义)。
感谢郑骁@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5e1336c01bf6ab772c8bb3a2

今天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,我们早已在UWA问答网站上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。

官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
UWA学堂:edu.uwa4d.com
官方技术QQ群:793972859(原群已满员)

阅读 559

简单优化,优化简单~

13 声望
4 粉丝
0 条评论
你知道吗?

简单优化,优化简单~

13 声望
4 粉丝
宣传栏