1)URP关于多个摄相机的性能优化
2)Unity Addressables打包的时候如何设置BuildAssetBundleOptions.DisableWriteTypeTree
3)Unreal能够用于商业化游戏的热更新方案
4)UGUI SpriteAtlas在使用中回调实例化,AtlasRequested和Start的顺序颠倒
5)从AssetBundle中动态加载渲染管线,后期渲染异常问题git
UWA 问答社区:answer.uwa4d.com
UWA QQ群2:793972859(原群已满员)github
Rendering
Q1:URP7.4.3,除开主相机外,还有一个子相机,用于将照到的模型渲到游戏主界面UI上。在Profiler中看到如下状况:性能优化
能够看到,在子相机中也进行了包括对LOD的计算,但子相机的CullingMask只开了一个名为RTModel的Layer,在这一层里只有一个3D对象。按说子相机CullScriptable这块开销不该该有才对。网络
目前怀疑可能的缘由是URP会对每一个Base Camera都进行这部分的计算,但若是用Overlay相机,又没法用原来的方式将相机的targetTexture渲到一张RawImage上了。框架
有人遇到过么?编辑器
A:题主的疑惑是:子相机的CullScriptable这块的开销不该该有那么大对吧(毕竟我只有一个物件)?函数
这里有两个问题:
1.Culling到底作了啥,只有一个物件为啥要Culling那么久(难道只有一个物件也要作不少的准备工做)?
2.你在Profiler里面看到的数据真的是真实数据吗?也就是说,子相机的Culling真的作了1.68ms吗?工具抛开这两个问题,也能够有更好的作法:oop
咱们一共两个相机,主相机和UI相机,那么UI上显示的3D物件怎么办呢?
咱们有个虚拟相机,所谓相机,其实就是作一个VP矩阵,作一个RT,绘制可见的物件就能够了。那么使用Unity的SRP,随便在什么地方,设置一下VP矩阵,设置RT,接着绘制指定的物件(UI中全部的3D物件都会挂在这个物件下面),而后这个RT就能够随意使用了。性能假如一个UI上有两个3D物件,尽可能都放在一个RT上,若是不行,就放在两个或更多的RT上。只是会多几个绘制命令,几个RT(还不须要是全屏的),并且会多几个Swap RT的操做。因为咱们项目没需求须要若干RT,因此假设一下,在这种须要若干RT的状况下,也能够用一个RT加多个Viewport来解决的。这个代码都是现成的,参考一下Cascade Shadow Map的作法,这样Swap RT也就省了。
综上所述,既然你都知道本身要绘制什么,就不要给Unity Culling的机会了。
感谢王烁@UWA问答社区提供了回答
Q2:数据是在Development Build中连真机看到的性能数据, 目前在使用相似于HLOD的方式来减小掉这个LOD的巨大开销。楼上说的“设置一下VP矩阵,设置RT”,请问这个VP矩阵的操做具体是什么?能否详解下或者有相关资料吗?
A:一切皆有可能!但不过这个不重要。而后你提的HLOD和LOD和上面的Culling不要紧。VP矩阵就是view矩阵和projection矩阵。相机的做用就是提供这俩矩阵的。
若是你在管线里面设置了相应的矩阵,而后绘制指定的物件,就能够彻底不用多一个相机,毕竟多一个相机就多一个Culling。
若是你对VP矩阵不熟悉,不清楚怎么实现,也简单。依然用一个额外相机,关上这个相机的Culling,而后在渲染pass中,不要绘制cullingresult.visibleobject,而直接用Graphics.DrawMesh或者CommandBuffer.DrawMesh绘制你要显示的那个3D Object的物件就行了。
感谢王烁@UWA问答社区提供了回答
Addressable
Q:原来的AssetBunlde打包的时候能够设置BuildAssetBundleOptions.DisableWriteTypeTree,使得包体小好多。今天项目尝试升级使用Addressables,请问该如何设置BuildAssetBundleOptions.DisableWriteTypeTree?
A1:首先Addressable打Bundle包主要的脚本是BuildScriptPackedMode,在DoBuild函数内能够看到用了AddressableAssetsBundleBuildParameters这个类,这个类继承于BuildParameters,而BuildParameters有一个成员变量是public ContentBuildFlags ContentBuildFlags { get; set; },这个ContentBuildFlags就是用于设置DisableWriteTypeTree的,BuildParameters是属于ScriptableBuildPipline的。
参考SBP的CompatibilityBuildPipline有如下操做:
if ((options & BuildAssetBundleOptions.DisableWriteTypeTree) != 0) parameters.ContentBuildFlags |= ContentBuildFlags.DisableWriteTypeTree; IBundleBuildResults results; ReturnCode exitCode = ContentPipeline.BuildAssetBundles(parameters, content, out results);
咱们在BuildScriptPackedMode.cs里也能够加上:
var buildParams = new AddressableAssetsBundleBuildParameters( aaContext.Settings, aaContext.bundleToAssetGroup, buildTarget, buildTargetGroup, aaContext.Settings.buildSettings.bundleBuildPath); buildParams.ContentBuildFlags = UnityEditor.Build.Content.ContentBuildFlags.DisableWriteTypeTree;
可是我在这儿测试了一下,并无什么用,不知道是最底层没有支持仍是个人测试用例有问题。建议用一样的方法,测试一下。
另外说一下,我看了一圈代码,在打包和压缩部分SBP并无用到这个参数。而在处理场景依赖的地方,这个参数会被合到BuildSettings结构体提供给C++部分调用。因此这个参数应该最终传到C++层起做用。
感谢黄程@UWA问答社区提供了回答
A2:Addressable彷佛没有给外部的接口直接来修改这个设置项,应该是须要本身写代码来修改打包方式了。须要本身写一个BuildMode,能够参考如下这个帖子中第五个问题的回答:https://answer.uwa4d.com/question/5e649911438f7d0db495c724#5e64a4e8438f7d0db495c725
核心的代码是要DoBuild中修改buildParams的设置项,buildParams.ContentBuildFlags |= UnityEditor.Build.Content.ContentBuildFlags.DisableWriteTypeTree;以下图:
作了一下测试,发现是有效果的:
上面是默认的打包,修改后从新打包,变成下面的结果:
总体都变小了一点点,并且使用解开AssetBundle后,能够看到里面的内容变得很简洁。
感谢Xuan@UWA问答社区提供了回答
Unreal
Q:Unreal方面,目前有什么能够用于商业化游戏的热更方案吗?
A1:由于咱们公司是本身研发的一套框架,因此我也没有太在乎是否有开源的Unreal热更新方案,印象中好像是没有的。
但基于Unity引擎的开源方案却是蛮多,大家能够按照Unity的开源方案的思路实现一套,基本思路就是使用反射预先生成引擎的导出Lua接口。
如何利用反射呢?简单来讲就是根据反射获得引擎接口的函数名,返回值类型、参数名和参数类型,由工具生成解析参数类型以及它的个数和顺序,返回正确结果的Lua导出函数int xxx(lua_State *L) 函数。对于类成员函数须要导出到Table里,根据C++类层级关系利用Metatable能够找到父类的Lua导出成员函数。
Unity开源方案如此,Unreal也能够如此,区别只是Unreal使用UClass UProperty这套,而Unity使用C#而已。大家能够尝试着实现一下。
感谢王远明@UWA问答社区提供了回答
A2:能够参考如下这个连接:
https://github.com/Tencent/puerts
感谢lanyt@UWA问答社区提供了回答
A3:腾讯有两款Lua热更新的框架可供使用:
sLuaUnreal
听说是《和平精英》手游采用的框架;UnLua
较sLua后推出的一个框架。
感谢Vest@UWA问答社区提供了回答
Script
Q:请问UGUI SpriteAtlas使用中,AtlasRequested和Start的顺序颠倒,以下图:
测试工程可戳原问答获取,测试环境Unity 2019.4。
A:可使用Timeline看到具体的执行时机,在Main.Update里面进行实例化的时候(我测试的时候把Main.Update里面的interval去掉了),Atlas的回调跑到第二帧了,而TestAtlasSprite的Awake、OnEnable和Start都在第一帧。在Main.Start里面实例化的时候,这些打印都在第一帧,由于Atlas的回调是在EarlyUpdate.SpriteAtlasManagerUpdate里面,而实例化出来的TestSpriteAtlas.Start是在FixedUpdate.ScriptRunDelayedFixedFrameRate下面的,因此就跑到了Atlas回调的后面。
这个图是在Update里面执行的状况。
这个是在Start里面执行的状况,能够看到都是在第一帧打印的。
这是在Main.Start里面执行实例化的Timeline的图,能够看到TestSpriteAtlas.Start是在Atlas的回调后面执行的。
这是在Main.Update里面执行实例化的Timeline。
EarlyUpdate,FixedUpdate这些回调的执行顺序能够参考:
https://medium.com/@thebeardphantom/unity-2018-and-playerloop-5c46a12a677
感谢Xuan@UWA问答社区提供了回答
Rendering
Q:有人遇到动态切换管线,显示错误的问题吗?
现有UBP项目需求在进入新的场景以后,切换到指定的渲染管线。在打包场景的时候将渲染管线一并打包到场景中,并经过如下代码来切换渲染管线。
GraphicsSettings.renderPipelineAsset = targetAsset; QualitySettings.renderPipeline = targetAsset;
可是经过AssetBundle加载出来的渲染流程:在后处理中,UberPost 缺乏两个Keyword。
形成以下的图像。
在Project Setting -》 Quality里面手动设置成项目的hero_show管线则正常显示。
经过断点调试发现:在Render过程当中,Keywords其实都是有赋值的。两者的流程均一致。
在PostProcessPass.cs文件中:
void Render(CommandBuffer cmd, ref RenderingData renderingData)
但就是在Frame Profiler中抓帧显示没有Keywords。附上简单的项目测试:
默认是Windows平台。直接运行defaultScene便可。
如不是,按下面流程处理:
1. AssetBundle->build
2. 运行defaultScene.
连接:https://pan.baidu.com/s/1q3s6mAUwE723wTJ3VmS81g
提取码:8kwn
A1:虽然没遇到过,可是能猜到缘由。
先总结一下楼主的问题:
Project Setting -》 Quality里面手动设置渲染管线,显示正常;
以AssetBundle的形式加载渲染管线,显示不正常,缘由是Keyword丢失。那么答案就很简单了。
由于这两种模式Unity对渲染管线这个资源的处理方式是不一样的:
以第一种方式,Unity会认为渲染管线是个默认资源,将其所有打包进包体,并进行使用。
以第二种方式,Unity会将渲染管线,特别是渲染管线关联的Shader,判断其Keyword是否被使用,若是没使用,就优化掉了。项目尚未看,我猜想楼主是在代码中开启的这两个Keyword,这种代码开启Keyword的方式,Unity检测不到,因此就丢掉了。
解决方法也简单,对付Keyword经常使用的方案,建立一个没用的材质球,使用相应的Shader,在材质球中开启对这些Keyword的使用打进AssetBundle,这样Unity就知道,这个Shader的这些Keyword是有用的,就不会Skip掉了(其实这个方法常被用于以防instance_on这个Keyword丢失)。
感谢王烁@UWA问答社区提供了回答
A2:想尝试楼上的方法,发现材质球并不能直接引用到UberPost这个Shader,由于这个Shader是放在Package目录下,因而参考了Packages目录下Shader打包这个帖子中的方法进行打包。使用编辑器的SVC采集方法采集了一下SVC,SVC里面的UberPost是有那两个Keyword的。将UberPost和这个SVC一块儿打包,拆包后能够看到ubqScene场景是引用了刚刚这个SVC中的Shader的,切场景后在Awake里面加载SVC并Warmup,然而也仍是没有解决问题。最后我把题主的原始工程打了一个exe,运行发现并无Keyword丢失的问题,渲染一切正常。另外打包成APK测试,在小米9上测试也是正常渲染的。
可能仍是Unity编辑器的问题吧,相似于这个帖子:
UnityEditor下加载AssetBundle,材质球Keywords正常,可是某些属性不存在)。
感谢Xuan@UWA问答社区提供了回答
封面图来源于网络
今天的分享就到这里。固然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,咱们早已在UWA问答网站上准备了更多的技术话题等你一块儿来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。
官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
UWA学堂:edu.uwa4d.com 官方技术QQ群:793972859(原群已满员)