技术分享连载(九十八)

技术分享连载(九十八)

我们将从日常技术交流中精选若干个开发相关的问题,建议阅读时间15分钟,认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。

UWA QQ群:465082844
UWA 问答社区:answer.uwa4d.com


渲染

Q1:在UWA性能优化报告中,有个专门针对半透明渲染的性能消耗说明,导致半透明渲染高开销的一般有UI、场景和粒子等,那么想知道,UI(好像大部分UI都是有带半透明的)对半透明的影响有多大?在制作UI上有没有什么注意事项?

就现在的大多数移动项目而言,这个影响是很大的。在半透明渲染的CPU端,主要有两点需要注意:
(1)UI Draw Call;(2)UI的重建。

  • UI Draw Call越高,其渲染耗时越大,所以,建议在题主在UWA测评报告中的CPU详细性能堆栈中,查看UI的Draw Call使用情况。一般移动游戏,都建议将其峰值控制在40以下。而如果降低UI Draw Call,主要还是图集打成Atlas、避免穿插等等,具体的可自行Google。

  • UI重建同样会造成开销过大,主要表现在主线程的self等待开销中,当UI重建的网格体量较大时,这种情况容易出现。所以,尽可能避免不必要的UI网格重建,也是研发团队在UI制作时需要特别注意的地方。

该问题来自UWA问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/5a731c34e3b569146eeaeb35


内存

Q2:最近我们发现游戏在魅族Pro5在运行时,PSS内存会暴涨,使用UWA GOT测试,发现资源内存并都没涨,而且这个问题目前只在魅族Pro5上出现,其它机型没有这个问题,请问该怎么解决呢?
请输入图片描述

我找了一个简单工程,如下图NPC名字跟阴影不能同时显示,否则就会导致PSS内存暴涨。
请输入图片描述

如下图,GfxDriver内存一直在涨,一秒涨2MB左右,只增不减。运行久了,魅族Pro5会崩溃。
请输入图片描述

如果GfxDriver和PSS一起升高,那么说明GPU方面存在Bug的概率很高。只能建议如下:

(1)尝试在特定机器上不加入“UI阴影”,从制作上进行规避;
(2)尝试在更高Unity版本中运行Demo,查看其内存问题是否会修复。

后经题主再次反馈,把 Unity版本从5.4.5升级到5.5.6,然后把 auto graphics api勾选上后,内存爆涨的问题就解决了。如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/5a741b6fe3b569146eeaeb3a


其他

Q3:new Action(Function)和直接传入Function函数区别是什么?例如以下两个函数有啥区别?

void Method(Action action)
{
}

void MethodCallBack()
{
}

void Start()
{
//Method(new Action(MethodCallBack)) 和 Method(MethodCallBack) 有啥区别? 哪个性能高?
}

两者理论上是一样的,因为Method(MethodCallBack)在编译时,编译器会自行给它包一层new Action。所以这两种写法从编译结果来看,是一致的。

这两种写法如果在项目中只是偶尔调用,是没有问题的,但如果被频繁调用,那么比较好的写法是在外部定义一个Action,然后将该Action传给Method来进行复用,即

Action act = New Action(MethodCallBack);
void Start()
{
Method(act);
}

该问题来自UWA问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/5a72f4dba69c4f5b6d1a9949


动画

Q4:我们使用的是老动画系统,动画是单独打包的,在运行时通过AddClip添加动画到模型上去,但是AddClip会触发RebuildInternalState导致波峰,那么大家是怎么解决这个RebuildInternalState触发的波峰呢,难道是只有老动画系统才会发生这个情况吗?
请输入图片描述

RebuildInteralState在Mecanim中也是有的,只是不叫这个名字了,而是变成了“Animator.Initialize”,两者的作用和触发时刻都差不多。

AddClip确实很耗时,这个在以前就是如此,所以建议如无特殊需求,AddClip尽可能在切场景时进行替换,在Runtime(特别是战斗中时)是不建议频繁调用AddClip的。

该问题来自UWA问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/5a702a5d1c1b88125112c7b8


资源管理

Q5:我查看了UWA上所有关于ShaderVariantCollection的资料之后,自己动手开始做一个ShaderVariantCollection预加载Shader,由于Shader变种比较多以及方便维护,准备写一个工具查找所有需要的Shader.keywards组合, 在生成ShaderVariant的时候有一个参数是PassType。通过Material.GetTag(“LightMode”, true)查找的时候有两个问题:

1)一个Shader里面可能有多个SubShader或者Pass使用不同的LightMode,但是通过GetTag(“LightMode”, true)只能找到第一个;

2)有一些Shader里没有设置Tags{“LightMode”=XXX}(主要是第三方插件),这个怎么处理比较合适?
我查找工具脚本在这里:https://paste.ubuntu.com/26462717

题主可以尝试反射大法,可以同时找到Keyword和Passtype。

static MethodInfo GetShaderVariantEntries = null;
public static List<string> GetShaderKeywords(this Shader target)
{
if (GetShaderVariantEntries == null)
GetShaderVariantEntries = typeof(ShaderUtil).GetMethod(“GetShaderVariantEntries”, BindingFlags.NonPublic | BindingFlags.Static);

        int[] types = null;
        string[] keywords = null;
        object[] args = new object[] { target, new ShaderVariantCollection(), types, keywords };
        GetShaderVariantEntries.Invoke(null, args);
        keywords = args[3] as string[];
        List<string> result = new List<string>();
        foreach (string keyword in keywords)
        {
            foreach (string t in keyword.Split(' '))
            {
                if (!result.Contains(t))
                    result.Add(t);
            }
        }
        return result;
    }

感谢钱康来提供了以上回答。

该问题来自UWA问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/5a6ace59cd437d6b816b7ef8


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

官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
官方技术QQ群:465082844(仅限技术交流)