开发WebGL项目,你需要了解这些...

开发WebGL项目,你需要了解这些...

这是第122篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。

UWA 问答社区:answer.uwa4d.com
UWA QQ群:465082844(仅限技术交流)


WebGL

Q1:目前我们有一个采用Spine的2D项目需要转换成H5游戏,请问直接使用Unity开发WebGL的项目,性能上会有哪些注意事项呢?

看题主的意思是想在移动设备上跑。我们项目(竞速类)曾尝试了直接用Unity 5转为页游版本,但是是运行在PC平台上的,手机上简单了解过别人的项目,当时得出的初步结论是在移动设备上中重度的3D性能扛不住,这个没有经过亲自验证。

我列下我们在Unity5转PC页游踩的坑供你参考下:
1)WebGL中不支持多线程和C#网络,可以用协程、Websocket代替;
2)我们有些协程用法写得有问题,在协程函数中用了While(1)这种死循环等待资源加载完成,在其它平台下没问题,但是在WebGL中会死循环,大概跟WebGL不支持多线程有关;
3)在游戏加载资源过程中,随着占用内存增大,偶尔会内存溢出,这主要是我们资源没有优化好导致的。我们在跟一个成熟的页游团队交流时,对方建议页游内存不要超过256MB,需要很细致地控制资源的加载和释放;
4)建议使用LZ4压缩格式,WebGL不支持多线程,LZMA压缩的Bundle会导致主线程解压缩时的卡顿;
5)单个资源体积不宜过大,建议控制在1MB以下,尽量做资源依赖打包,要不加载时间过长,很影响体验;
6)WebGL不支持中文输入,我们用原生的方式实现了中文输入;
7)PC端一些浏览器直接不支持,我们测试支持的浏览器有:

  • Google Chrome 9+
  • 2.Mozilla Firefox 4+
  • Safari 5.1+(仅限Mac OS X操作系统,不包括Windows)
  • Opera 12 alpha以及以上版本
  • IE9+,但是IE并不支持WebGL,不过你可以通过下载并安装IEWebGL这个插件
  • QQ 360 搜狗

8)资源如果没有实例化使用,在Editor下不会闪退,但是打出的PC包和导出的WebGL版本都会闪退。

感谢赵林@UWA问答社区提供了回答,欢迎大家转至社区进一步交流:
https://answer.uwa4d.com/question/5b3a27bd3ab9166bb3e84927


堆内存

Q2:从理论上来说,Mono堆内存是越小越好(UWA是建议控制在40MB以内),分配频率越低越好。那单次比较大的内存分配和频率很高的(比如每帧)小内存分配,在性能影响上谁更大呢?单次GC的耗时,是受总体堆大小影响较大,还是受堆内引用对象数量的影响较大?简单来说,是要优先优化那些每帧分配的小内存还是单次较大的内存分配?GC对机器发热的影响大吗?

优先优化那些每帧都分配的小内存。这个对于GC到来的影响比较大。频繁GC对于运行流畅性的影响比较大,从整体上来说,GC对于能耗的影响不大,比常规开销(渲染模块、UI模块等)要小很多。
单次较高的堆内存分配,建议要注意2MB以上的分配,查看其分配是否合理,尽可能避免8MB以上的分配。它主要的麻烦点在于撑大Mono堆内存峰值,一旦上去了就下不来。
该回答由UWA提供

Mono堆内存峰值高,最大的影响是会撑大Mono内存的占用量,而Mono向系统申请的内存是只增不减的。直白说就是游戏内存占用上升,风险是低内存设备上更容易闪退。
感谢Walker@UWA问答社区提供了回答

GC耗时肯定会受到影响。目前来讲,无论是IL2CPP还是Mono,GC都不分代,这也就意味着,回收的时候会遍历所有的节点。
感谢凯奥斯@UWA问答社区提供了回答

欢迎大家转至社区进一步交流:
https://answer.uwa4d.com/question/5b5bd3471e88b37d34e6517d


资源管理

Q3:大家是怎么做代码分离的?游戏项目由于有多个部门需要共同访问,为了保护源代码,希望做到非技术部门在游戏工程只拿到加密后的DLL文件。

最初的想法是,各个部门都是拿同一个游戏工程,其中技术部直接获取源码,其他部门拿到DLL文件,技术编写完成后生成DLL给其他部门更新。但发现Unity中挂脚本组件是通过GUID+FileID的方式去匹配的,所以拿源码的同事是不同的脚本就有不同的GUID,拿DLL的同事则都是同一个GUID。导致不同部门之间没法在同一个工程上制作。

现在的做法是另外创建一个编译工程去生成各个平台对应的DLL文件,但是这样又比较繁琐。
PS:即使在已经做了模块分隔的情况下,导入DLL的时间比更新少量cs文件的时间多出很多,请问大家有没有更好的做法呢?

这个我们是看部门需求的。
1)美术部门时常需要在Unity上调试效果,我们只对该部门提供带加密好DLL的工程项目,指定目录提交对应资源,并做好工具操作的提示。
2)策划部门在Unity调效果不是硬需求(看各自公司的情况吧),可以提供可加载本地Lua代码的exe包,让业务提供配置代码,并将该部分代码对策划开放(但由于有语法学习成本,可以在svn可hook一个语法检查),或者工具打包到exe中。
临时想到这些,看看是否能帮到题主。
感谢兰叶凛香@UWA问答社区提供了回答

"导入DLL的时间比更新少量cs文件的时间多太多了,即使在已经做了模块分隔的情况下"。这个问题我估计是题主没加AssemblyInfo,导致Unity会扫描API,可以参考下:https://github.com/pangweiwei/slua/blob/master/Assets/Slua/Editor/LuaCodeGen.cs#L544。
只要大家用一个Unity版本速度会快很多。
再PS. 现在2018了为了一些代码搞这么麻烦性价比真心低。
感谢钱康来@UWA问答社区提供了回答

如果业务逻辑都在Lua,那么可以选择加密Lua的bytecode,
如果业务逻辑也是C#写的,那么可以选择不加密。
其实都到2018年年中了,代码没那么值钱了。用DLL都会加大其他部门的使用繁琐程度。
感谢史云柯@UWA问答社区提供了回答

欢迎大家转至社区进一步交流:
https://answer.uwa4d.com/question/5b4eb5f4339d267d357c6b6c


资源管理

Q4:如果多个不同的Shader引用同一份cginc文件,实际上会被编译多少次?

我理解的是,cginc 是被包含的,相当于编译器预处理复制粘贴到了Shader文件里,可以看做并不存在cginc 这个文件,所以有几个Shader文件包含了这个 cginc,就编译几次。
感谢jim@UWA问答社区提供了回答

cginc只是一些代码片段,Shader用到某个cginc的时候就会把里面对应的函数抠出来,在precompile的时候完成该项工作。所以,如果不同的Shader引用到了同一份cginc文件,其编译并不是整个cginc文件参与编译,而是Shader中用到的那一段代码进行了编译。
该回答由UWA提供

欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5b5552ff339d267d357c6bdf


动画

Q5:在一个动画事件中实例化另一个动画物体(使用Animator),发现实例化的物体并没有直接开始动画,而是显示了一下默认姿态,在下一帧之后才开始了动画。请问这个该如何处理呢?

动画事件是动画系统在进行了该帧动画计算(Animation Evaluation)之后激活,如果在动画事件中实例化动画物体,该物体的animator不会在该帧进行动画计算,而会等到下一帧时由动画系统进行动画计算。解决方案是在实例化动画物体后,调用一下 Animator.Update(0).

该回答由UWA提供,欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5b5ed8681e88b37d34e6519c

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

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