unity3d粒子系统怎么让传送带转起来求大神指教

&p&为了项目安全且干净其实插件用的越少越好,因为插件很多都自己封装了Dll,如果出了BUG,想解决就特别的麻烦。&/p&&p&但是自己造轮子简直太累,作为强迫症患者又见不惯自己的轮子写的难看,一不小心一天就过去了。&/p&&p&所以这里我就举3款项目里面常用的插件,好用又免费:&/p&&p&&b&1.DoTween &/b&&/p&&p&做动画非常的方便,直接链式结构写代码也非常的快。避免代码里面控制物体还需要写协程或者再Update里面循环。&/p&&div class=&highlight&&&pre&&code class=&language-text&&using System.C
using System.Collections.G
using UnityE
using DG.T
public class DotweenTest : MonoBehaviour {
public Transform targetP
// Use this for initialization
void Start () {
gameObject.transform.DOMove(targetPos.position,2).OnUpdate(()=&
//在移动中每帧执行
}).OnComplete(()=&
//移动完成后执行
gameObject.SetActive(false);
&/code&&/pre&&/div&&p&效果:&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/50/v2-9fcae42b06a_b.jpg& data-rawwidth=&623& data-rawheight=&312& class=&origin_image zh-lightbox-thumb& width=&623& data-original=&https://pic4.zhimg.com/50/v2-9fcae42b06a_r.jpg&&&/figure&&p&&br&&/p&&p&缺点是:是DLL包,想修改还得反编译。而且在Dotween回调(如OnUpdate)里面的报错是黄色警告(这个很坑,层级一个回调里面有报错结果谁都没有发现,最后游戏卡死)。&/p&&p&下载地址:&/p&&p&&u&&a href=&//link.zhihu.com/?target=http%3A//dotween.demigiant.com/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&dotween.demigiant.com/&/span&&span class=&invisible&&&/span&&/a&&/u&&/p&&p&&br&&/p&&p&&b&2.Cinemachine&/b&&/p&&p&影视镜头插件,2017的首推插件,这个做镜头非常的简单,而且效果也很棒。&/p&&p&可以很简单的创建自由视角的摄像机&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/50/v2-85ca39c5ae7bc_b.jpg& data-rawwidth=&318& data-rawheight=&184& class=&content_image& width=&318&&&/figure&&p&&br&&/p&&p&创建好的效果&/p&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/50/v2-626420dcd24cf1a5f5bd6d084cac693c_b.jpg& data-rawwidth=&710& data-rawheight=&262& class=&origin_image zh-lightbox-thumb& width=&710& data-original=&https://pic1.zhimg.com/50/v2-626420dcd24cf1a5f5bd6d084cac693c_r.jpg&&&/figure&&p&&br&&/p&&p&Cinemachine的功能很强大,之后我们会做相关文章来介绍。&/p&&p&下载地址:&/p&&p&AssetStore上免费的&/p&&p&&b&3.Litjson&/b&&/p&&p&对Json数据处理非常的简洁方便&/p&&p&比如我们要去读取一个json的数据换成游戏里面的脚本类,只用 JsonMapper.ToObject的函数就搞定了。&/p&&div class=&highlight&&&pre&&code class=&language-text&&using S
using LitJ
using System.T
using UnityE
using System.IO;
using System.Collections.G
public class configBagData
public readonly string itemN
public readonly string spriteN
public class LitJsonTest
public void Load(string rSheetName)
TextAsset textAsset = Resources.Load&TextAsset&(&assetsbundles/data/sheet/& + rSheetName);
if (textAsset == null)
Debug.LogError(rSheetName + &未找到&);
var str = textAsset.
Dictionary&string, configBagData& data = JsonMapper.ToObject&Dictionary&string, configBagData&&(str);
&/code&&/pre&&/div&&p&下载地址:&/p&&p&&u&&a href=&//link.zhihu.com/?target=http%3A//lbv.github.io/litjson/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&lbv.github.io/litjson/&/span&&span class=&invisible&&&/span&&/a&&/u&&/p&&p&&br&&/p&&p&当然还有一些美术插件,比如T4M地形插件,美术场景很多要用unity的地形功能,但是Unity的地形网格数量太多了,用T4M重新渲染可以降低网格数量。但是要注意的是美术资源用完插件后做好代码清理,不然会污染主工程代码环境。&/p&
为了项目安全且干净其实插件用的越少越好,因为插件很多都自己封装了Dll,如果出了BUG,想解决就特别的麻烦。但是自己造轮子简直太累,作为强迫症患者又见不惯自己的轮子写的难看,一不小心一天就过去了。所以这里我就举3款项目里面常用的插件,好用又免费:…
&p&&b&搬一篇自己之前写的文章
&/b&&a href=&//link.zhihu.com/?target=http%3A//www.jianshu.com/p/7f05b90f411e& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Unity 开发入门指南(学习感悟)&/a&&b&:&/b&&/p&&p&
学习 Unity 开发接近一年了,从开始对 Unity 一无所知,到现在能模仿制作出一个完整游戏,对个人成长来说,也算是一个不大不小的里程碑。这篇是对自己学习的总结与回顾,希望对 Unity 初学者有所帮助。
我的工作是做模拟集成电路设计,工作中基本不涉及编程,所以代码经验不算丰富。根据我的学习经验,总结出学习 Unity 可以分为四个阶段:&/p&&p&第一阶段: &b&跟着做&/b&。跟着 step by step 教程做,大量做。这个阶段的重点是学习 Unity 各种组件的使用(比如物理、UI等)。此时掌握编程语言最基础的东西就可以了,比如类、控制流、List、字典等。&/p&&blockquote&起步阶段的&b&难度曲线越平越好&/b&,在我对 Unity 一无所知的情况下,选择从观看 &a href=&//link.zhihu.com/?target=http%3A//www.imooc.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&慕客网&/a& 视频起步,开始给自己定的目标很简单:&b&熟悉 Unity 界面&/b&(目标就是定这么低)。 两个视频下来,差不多就熟悉 Unity 界面和一些基本操作了。
如果这个阶段你正在看三消、2048 这类靠 UI 和算法支撑的案例教程,希望你把重点放在教程中是如何使用 UI 组件上面,选择性忽略具体算法实现。不然,对于代码能力较弱的同学,分分钟被打击。&/blockquote&&p&第二阶段: &b&反推&/b&。这一阶段先看教程效果,然后反推效果的实现方式,最后研究别人是如何实现的。&/p&&blockquote&这一阶段的效果是,即可以检验你第一阶段的学习效果,又可以加深对 Unity 的理解 。&/blockquote&&p&第三阶段: &b&模仿&/b&。从模仿功能到模仿整个游戏,找你玩过的或者当下热门的游戏,模仿它。&/p&&blockquote&我模仿的 &a href=&//link.zhihu.com/?target=https%3A//github.com/wuqxuan/LifeLineUnity& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Lifeline ( 生命线 )&/a&和 &a href=&//link.zhihu.com/?target=https%3A//github.com/wuqxuan/BackToZero& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&BACK2ZERO&/a&。
这一阶段需要自己思考如何用 Unity 和代码把效果实现出来,这会倒逼你去学习 Unity 的使用,以及如何用合适的代码实现想要的效果。通过这一阶段,你对 Unity 的掌握程度和代码水平都会有很大提升(当然,语言高级特性、数据结构和算法、设计模式等这些小怪也是要刷的)。&/blockquote&&p&第四阶段: &b&Enjoy it&/b&。这一阶段你已经能从容驾驭 Unity 和代码,可以自由地把脑海中的想法实现出来,开始享受创造的快乐。我想,做技术的乐趣莫过于此。&/p&&blockquote&这一阶段应该关注 Unity 的内存优化、渲染优化、资源管理、Shader 等,如果想做出玩法和画面更好的游戏,还要学习 AI、图形学、引擎架构等相关知识。&/blockquote&&p&驾驭一项技术,无他,善用 Google,多学、多练、多想。 我在豆瓣上维护了一份书单 &a href=&//link.zhihu.com/?target=https%3A//www.douban.com/doulist//& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&游戏设计梦想家&/a&,欢迎围观。&/p&&p&欢迎试玩我的免费游戏 &a href=&//link.zhihu.com/?target=https%3A//itunes.apple.com/us/app/chao-fang-bi-ji/id%3Fl%3Dzh%26ls%3D1%26mt%3D8& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&炒房笔记 [iOS]。&/a&
搬一篇自己之前写的文章 :
学习 Unity 开发接近一年了,从开始对 Unity 一无所知,到现在能模仿制作出一个完整游戏,对个人成长来说,也算是一个不大不小的里程碑。这篇是对自己学习的总结与回顾,希望对 Unity 初学者有所…
&figure&&img src=&https://pic1.zhimg.com/v2-88db6bd5daad72e02f412_b.jpg& data-rawwidth=&800& data-rawheight=&499& class=&origin_image zh-lightbox-thumb& width=&800& data-original=&https://pic1.zhimg.com/v2-88db6bd5daad72e02f412_r.jpg&&&/figure&&p&原文链接:&a href=&https://link.zhihu.com/?target=http%3A//blog.uwa4d.com/archives/QA_ResourceManagement.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&关于Unity中的资源管理,你可能遇到这些问题 - Blog&/a&&/p&&p&在优化Unity项目时,对资源的管理可谓是个系统纷繁的大工程。鉴于Unity独特又绝(cao)妙(dan)资源打包的AssetBundle管理机制,不同资源的属性适合于不同的存储和加载方式。此外,要处理好成百上千个资源之间的相互依赖关系也非易事。谁说良好的资源管理不是个艺术呢?:)&/p&&p&——————————————————&/p&&p&&strong&关键字&/strong&&br&&/p&&p&&strong&AssetBundle&/strong&&br&&strong&资源制作 纹理\网格\材质\Shader\音频\动画&/strong&&br&&strong&Lightmap&/strong&&/p&&h2&&strong&一、AssetBundle 相关&/strong&&/h2&&p&&strong&Q1:Unity中的SerializedFile是怎么产生的?请问用Unload(false)可以清除吗?因为读取了Bundle里面的内容后已经赋值给其他物体了。而且我把图片都打成了Bundle,然后读取出来,图片的大小应该是超过了这个SerializedFile的大小的?&/strong&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-19ebf822a59694eebb0d97_b.jpg& data-rawwidth=&949& data-rawheight=&297& class=&origin_image zh-lightbox-thumb& width=&949& data-original=&https://pic1.zhimg.com/v2-19ebf822a59694eebb0d97_r.jpg&&&/figure&&br&&blockquote&&p&SerializedFile是AssetBundle加载时产生的序列化信息,一般为LoadFromCacheOrDownload、LoadFromFile和New WWW加载本地AssetBundle文件所致。如果AssetBundle中的资源已经加载,且后续没有依赖该AssetBundle的资源进行加载,那么可以通过Unload(false)将其删除。SerializedFile中记录的是AssetBundle的序列化信息,而不是其包含资源的内容,因此,其大小要小于或远小于资源的实际内存。&/p&&/blockquote&&p&&strong&Q2:我们现在采取了2种资源管理方式, 我想了解下内存占用问题。 方式A:AssetBundle加载好以后在内存中保留, 如果需要创建对象就通过Instantiate来创建。方式B:AssetBundle加载好以后立刻通过Instantiate实例化一个对象, 然后Unload(false)这个AssetBundle,如果需要,创建对象通过clone来完成。对于方式A,在Profiler中发现 WebStream中有相关AssetBundle文件存在, 我们认为这份内存是多余的, 所以就采取了方式B, 方式B又面临资源卸载不干净的情况。想确认一个问题, 如果采取方式A: 一个 xxx.assetBundle原始文件大小是 1MB, 解压到Webstream内存中是2MB, 最终实际内存占用是2MB 还是3MB 呢?&/strong&&/p&&blockquote&&p&如果采取方式A:最终实际内存占用是2MB,而不是3MB,WebStream中已经包含原始AssetBundle的数据。对于没有依赖关系的AssetBundle文件,我们推荐方式B的形式对AssetBundle进行卸载,这样可以免除不必要的内存占用,对于这种方式加载出来的资源,可以通过Resources.UnloadAsset和Resources.UnloadUnusedAssets来进行卸载,如果无法卸载,则该资源一定被缓存了,研发团队可通过检测自己的缓存池/Constainer来进行检测。同时,如果是Unity 5.3以后版本,可尝试通过Memory Profiler来进一步查看。&/p&&/blockquote&&p&&strong&Q3:打包时候AssetBundle的md5总变化(被打包的东西没变),请问能怎么解决?有说法是加上DeterministicAssetBundle就可以,但是我尝试后发现md5依然变化。&/strong&&/p&&blockquote&&p&该方法确实并不受用。对于Unity 4.x版本的AssetBundle文件,其md5值在某些情况下确实会前后不一致(哪怕是完全一样的内容进行打包)。对于该系列版本,仅能建议开发团队建立配置文件来对AssetBundle进行管理。&br&而对于Unity 5.x版本,则可以在打包时开启 AppendHashToAssetBundleName 选项,这样Unity引擎会在每个AssetBundle文件后生成一个唯一的HashID(显示地放在文件名后),开发团队可以通过该ID来判断对应的AssetBundle文件是否发生改变。&/p&&/blockquote&&p&&strong&Q4:如果采用依赖打包的话,比如NGUI,图集A作为被依赖包,界面1、2、3作为独立包,分别依赖打包。当图集A重新打包的时候,是不是界面1、2、3也都要重新打包?目前我们是界面打包时清空全部的图集信息再打包,在客户端加载后再动态赋值回来。这样可以实现单独更新图集,但是代价就是加载的性能。请问有什么更好的解决方案呢?&/strong&&/p&&blockquote&&p&“当图集A重新打包的时候,是不是界面1、2、3也都要重新打包”,这是不需要的,Unity 4.x的依赖打包的限制在于,在重新打一个包时需要将它依赖的包都重新打一次,但不需要重打依赖它的包。&/p&&/blockquote&&p&&strong&Q5:请问内置的shader怎么打包?我用到了内置材质球,不只是Shader,这时候在Profiler中看到加载的结果中会出现多份,如下图所示&/strong&&br&&figure&&img src=&https://pic4.zhimg.com/v2-d3c8bae384a4da8f26dd2f00c723b59e_b.jpg& data-rawwidth=&223& data-rawheight=&509& class=&content_image& width=&223&&&/figure&&br&&/p&&blockquote&&p&通常有两种方式对内置的Shader进行打包:&/p&&ol&&li&将其添加到Graphics Settings中的Always Included Shaders 中,此时添加后的内置Shader就不会被打入AssetBundle包中;&/li&&li&在&a href=&https://link.zhihu.com/?target=http%3A//unity3d.com/cn/get-unity/download/archive& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Unity - Get Unity - Download Archive&/a&下载内置的 Shader,将其导入项目,并替换成非内置的材质球,从而可以直接通过脚本来控制其打包的方式。&/li&&/ol&&/blockquote&&p&&strong&Q6:请问粒子特效的Shader是否不能使用依赖打包? 我们对Shader的模型和特效使用了依赖打包,运行的时候发现模型显示是正常的,但是粒子特效使用的Shader就不能正常运行,特效显示不正常。而在编辑器中,我们看到Material中的Shader是存在的。这时候如果重新手动给这个Material指定同样的Shader,这个粒子特效就能正常显示,请问这是什么原因引起的?&/strong&&/p&&blockquote&&p&部分 Shader 在打包到 Android 版本的 Assetbundle 之后,会因为平台不兼容而无法正确显示,这是因为打包后的 Shader 代码只保留了目标平台的预编译代码,不一定能够在 Editor 下运行,所以这是正常现象。 但这并不会影响依赖打包,因为在真机上并不会出现类似的问题。&/p&&/blockquote&&p&&strong&Q7:Resource的场景下有两个场景Scene1.unity和Scene2.unity。我要对这些文件进行打包,生成了&/strong&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&Scene1.assetbundle
Scene1.assetbundle.meta
Scene2.assetbundle
Scene2.assetbundle.meta
&/code&&/pre&&/div&&p&&strong&如果我有相同的资源,理论上它会在这两个包里各存一份,这样就造成了包体过大。所以有没有办法把共享资源做成依赖项单独打包,这样的话每个场景就不会过大了。Unity 5.x的BuildAssetBundles打包机制是否和Unity 4.x不一样?原来的打包机制已经被剔除了吗?&/strong&&/p&&blockquote&&p&用Unity 4.x 的 Push/Pop 是可以抽出相同的资源,并且据我们所知该方法在Unity 5.x 中也受用。根据Unity 5.x新的打包机制,只要把相同资源的 AssetBundle Name 设置好,打包时就会自动抽出来。&/p&&/blockquote&&p&&strong&Q8:现在生成AssetBundle的时候每个文件会多生成一个Manifest文件,这个文件也需要一起随着AssetBundle上传吗,在资源加载的时候具体怎么用呢?&/strong&&/p&&blockquote&&p&每个文件多生成的Manifest 文件是不需要上传的,其作用就是供开发人员查看AssetBundle 中的依赖关系等信息。&br&但除了每个文件多生成的 Manifest 以外,根目录下还会有一个与根目录同名的AssetBundle 以及 Manifest 文件,通过运行时加载这个AssetBundle,可以得到一个 AssetBundleManifest 对象,然后就可以通过这个对象得到AssetBundle直接的依赖关系。&br&更多信息可以参考&a href=&https://link.zhihu.com/?target=http%3A//docs.unity3d.com/ScriptReference/AssetBundleManifest.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&AssetBundleManifest&/a&&/p&&/blockquote&&p&&strong&Q9:如果我有一个Prefab,它的Dependencies都在Resources文件夹中,那么,当我在AssetBundle打包时,只打包这个Prefab(不指定BuildAssetBundleOptions.CompleteAssets和BuildAssetBundleOptionsCollectDependencies)的话,这个Prefab能够正确实例化吗?&/strong&&/p&&blockquote&&p&这是不能正确实例化的,因为AssetBundle中的资源和Resource文件夹下资源是不会建立依赖关系的(脚本除外,因为开启BuildAssetBundleOptionsCollectDependencies 时,脚本依然不会打包到AssetBundle中)。所以会出现Mesh、Material等的丢失。&/p&&/blockquote&&p&&strong&Q10:我们通过AssetBundle预加载Shader后,并没有卸载AssetBundle,但是发现后面加载的Object并没有引用到正确的Shader,这可能是由于什么原因呢?&/strong&&/p&&blockquote&&p&很可能是项目中AssetBundle的依赖关系打包不正确。后续加载的AssetBundle都需要与Shader的AssetBundle文件进行依赖,这样Unity引擎才会在加载后续AssetBundle时,将Shader进行关联。&br&建议开发团队通过UWA资源检测来检测下AssetBundle文件的依赖关系。主要查看两处,一个是Shader是否被冗余打包;一个是其& 他的AssetBundle是否与Shader的AB进行正确的依赖。具体检测效果如下:&br&&figure&&img src=&https://pic2.zhimg.com/v2-e1d8f8b4a63c61d59d9ddab_b.jpg& data-rawwidth=&2334& data-rawheight=&1470& class=&origin_image zh-lightbox-thumb& width=&2334& data-original=&https://pic2.zhimg.com/v2-e1d8f8b4a63c61d59d9ddab_r.jpg&&&/figure&&br&如下图红框所示,开发团队可以直接查看Shader以及其他资源在AssetBundle包中的冗余情况。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-ea7edae7cf7184_b.jpg& data-rawwidth=&2336& data-rawheight=&1514& class=&origin_image zh-lightbox-thumb& width=&2336& data-original=&https://pic3.zhimg.com/v2-ea7edae7cf7184_r.jpg&&&/figure&&/blockquote&&p&&strong&Q11:我游戏里重复的特效较多,有些只是图案相同但改变了颜色参数,如果都打成独立AssetBundle,则内存里面会有多份Texture。关于这样的打包一般有什么推荐的方法呢?&/strong&&/p&&blockquote&&p&如果是相同内容且仅是整体颜色不同的话,那么建议项目中只保留一份初始纹理资源,并通过Shader在运行时改变其整体配色,从而达到不同的效果。但如果是局部配色不同,那么可以在原始纹理的基础上加一种或几种Mask纹理,用来负责颜色的自适应调配,然后再通过Shader来达到不同的展示效果。&/p&&/blockquote&&p&&strong&Q12:请问一下,我两个预设都引用了第三个AssetBundle的贴图,如果不希望这张贴图存在两份,一定要等这两个预设都加载好了,才能卸载贴图的AssetBundle吗 ?&/strong&&/p&&blockquote&&p&是的,但并不是因为这样做会使“这张贴图存在两份”,而是因为如果先卸载贴图的AssetBundle会导致后续加载两个预设时会丢失依赖,即找不到贴图。如果脚本中会对这个情况进行检查并重新加载贴图的AssetBundle,那么此时才会造成“这张贴图存在两份”的问题。&/p&&/blockquote&&p&&strong&Q13:UGUI的图集操作中我们有这么一个问题,加载完一张图集后,使用这个方式获取其中一张图的信息:assetBundle.Load (subFile, typeof (Sprite)) as S 这样会复制出一个新贴图(图集中的子图),不知道有什么办法可以不用复制新的子图,而是直接使用图集资源 。&/strong&&br&&figure&&img src=&https://pic1.zhimg.com/v2-8a2b8bf787c94d31513bdf01d13f47ca_b.jpg& data-rawwidth=&898& data-rawheight=&586& class=&origin_image zh-lightbox-thumb& width=&898& data-original=&https://pic1.zhimg.com/v2-8a2b8bf787c94d31513bdf01d13f47ca_r.jpg&&&/figure&&br&&/p&&blockquote&&p&经过测试,这确实是 Unity 在 4.x 版本中的一个缺陷,理论上这张“新贴图(图集中的子图)”是不需要的,并不应该加载。 因此,我们建议通过以下方法来绕过该问题:&br&在 assetBundle.Load (subFile, typeof (Sprite)) as S 之后,调用&br&Texture2D t = assetBundle.Load (subFile, typeof (Texture2D)) as Texture2D;&br&Resources.UnloadAsset(t);&br&从而卸载这部分多余的内存。&/p&&/blockquote&&p&&strong&Q14:下图一是刚进游戏时获取的信息,第二张是开关几次同一个UI界面后获取,对比两图我们发现有多份重复的Texture。请问这是为什么?我们的加载方式是UI通过AssetBundle加载,加载后会释放AssetBundle,然后再次加载 UI 就会造成纹理资源的冗余。&/strong&&br&&figure&&img src=&https://pic3.zhimg.com/v2-1ec60dd47ebed7d656dabb9_b.jpg& data-rawwidth=&797& data-rawheight=&662& class=&origin_image zh-lightbox-thumb& width=&797& data-original=&https://pic3.zhimg.com/v2-1ec60dd47ebed7d656dabb9_r.jpg&&&/figure&&figure&&img src=&https://pic4.zhimg.com/v2-3f8315dee2fc528a632a39f3d030a478_b.jpg& data-rawwidth=&849& data-rawheight=&662& class=&origin_image zh-lightbox-thumb& width=&849& data-original=&https://pic4.zhimg.com/v2-3f8315dee2fc528a632a39f3d030a478_r.jpg&&&/figure&&br&&/p&&blockquote&&p&刚进游戏时获取的图中出现的“重复”资源可能并不是冗余,因为 Atlas的一个 Group 中可能包含多张一样大小的Page(即纹理),而这几个Page在内存中的名字是一样的。&br&但是,如果同一UI界面多次开启后,内存中出现了更多同样的资源,则说明UI的管理方式存在一定问题。对于频繁使用的UI,我们建议在加载之后通过缓冲池对其进行缓存,后续使用时,直接通过缓冲池获取即可。而不要每次均通过AssetBundle进行加载,这种做法既会造成更大的CPU占用,同样会很大几率造成资源的冗余。&br&同时,如果多次开启的是不同UI界面,并且造成内存中同种资源的增加,则很有可能是UI在AssetBundle打包时形成了冗余(这种情况在目前的UGUI系统中较为常见)。对此,如果开发团队使用的是UGUI,那么我们的建议如下:&/p&&ol&&li&对于使用Unity 5.x的新AssetBundle打包系统,则打包时尽可能将同种Atlas的UI界面打成一个AssetBundle文件,否则将很有可能出现资源冗余的情况;&/li&&li&对于使用Unity 4.x的老AssetBundle打包系统,则可以将一个含有Atlas的Prefab(或其他Object)先打包,其他UI元素对其进行依赖即可。&/li&&/ol&&p&此外,开发团队可以考虑用 &a href=&https://link.zhihu.com/?target=http%3A//WWW.LoadFromCacheOrDownload& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&WWW.LoadFromCacheOrDownload&/span&&span class=&invisible&&&/span&&/a& 来加载共享包,因为 new WWW 的方式会在内存中形成 WebStream 造成较多的内存开销。关于该函数的具体优劣,开发者可以参考&a href=&https://link.zhihu.com/?target=http%3A//blog.uwa4d.com/archives/ABTheory.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&你应该知道的AssetBundle管理机制&/a&。&/p&&/blockquote&&p&&strong&Q15:项目在发布时,Player Setting中勾选的这个选项(Optimize Mesh Data),对于已经打包并且放到了Streaming Assets中的AssetBundle文件有效果吗?模型资源里有个Optimize Mesh,是否能达到同样的效果?&/strong&&/p&&blockquote&&p&理论上 Optimize Mesh Data 是 Build Player 或者 Bundle 时才生效的,所以之前打好的 Bundle 就没效果了。另外,两个选项的效果是不同的,后者是调整面片排序的。&/p&&/blockquote&&h2&&strong&二、资源使用&/strong&&/h2&&h2&&strong&纹理相关&/strong&&/h2&&p&&strong&Q1:关于贴图类型设置请问有什么好的建议呢?是否所有的贴图都设置为Advanced比较好?这种情况下的贴图内存是不是比较小?&/strong&&br&&figure&&img src=&https://pic4.zhimg.com/v2-10df2672eef5fa70d2cdb9_b.jpg& data-rawwidth=&629& data-rawheight=&637& class=&origin_image zh-lightbox-thumb& width=&629& data-original=&https://pic4.zhimg.com/v2-10df2672eef5fa70d2cdb9_r.jpg&&&/figure&&/p&&blockquote&&p&Unity默认情况下会将绝大多数纹理设置为Texture模式。一般来说,Texture模式对于绝大多数纹理资源也都是合适的。上面的例子中,Advanced模式下之所以内存占用较小,是因为关闭了Mipmap选项,所以其内存下降了。其本质跟Advanced模式无关。Advanced模式较之Texture模式和其他模式,可以更大自由地对纹理资源进行控制。因此,如果你想对纹理资源进行更加自定义地设置,可以选择Advanced模式进行编辑。&/p&&/blockquote&&p&&strong&Q2:同样的包同一个图集,ETC2格式,在红米Note1上会比酷派的内存会大四倍,请问这是什么原因造成的?如果不支持OpenGL 3.0,会造成这么大的影响吗?&/strong&&/p&&blockquote&&p&ETC2 的格式理论上只在OpenGL ES 3.0 的设备上被支持,而在不被支持的设备上则会内部自动转成 RGBA32/ARGB32的格式,这对于 RGBA Compressed ETC2 8bits 的纹理就是放大了 4 倍。因此,如果希望在 OpenGL ES 2.0 的设备上对透明材质进行压缩,那么可以尝试使用分离 Alpha 通道的方式,用两个 ETC1 来进行压缩。&/p&&/blockquote&&p&&strong&Q3:我现在动态加载StreamingAssets下的贴图,代码如下&/strong&&br&&figure&&img src=&https://pic1.zhimg.com/v2-8d04f1006fcda1a8c75c38b37db97ec8_b.jpg& data-rawwidth=&581& data-rawheight=&59& class=&origin_image zh-lightbox-thumb& width=&581& data-original=&https://pic1.zhimg.com/v2-8d04f1006fcda1a8c75c38b37db97ec8_r.jpg&&&/figure&&strong&我发现这种方式内存消耗很大,一张512 x 512的贴图占用了2MB,看官方的解析是内存和显存各需一份。想了解下动态加载贴图有什么推荐的方式吗?&/strong&&/p&&blockquote&&p&一般来说,我们比较建议通过AssetBundle来动态加载资源,而非通过bytes流来进行加载。如果你的项目正在使用这种方式来加载纹理,我们建议从策略上考虑将其更改。在我们目前来看,通过bytes流来生成资源,绝大部分原因是想对其进行加密,从而让资源难于破解。但其实这种加密方式用处不大,因为据我们所知,现在有很多工具可以直接通过底层显卡层来直接查看各种纹理、Mesh资源,比如Mali Graphics Debugger、Qualcomn Profiler等。因此,如果是从加密的角度来通过bytes流生成资源,那么我们建议通过AssetBundle这种直接的方式进行加载。&/p&&/blockquote&&p&&strong&Q4:iOS平台需要对图集做RGB和Alpha通道的分离吗?我发现在同样大小的图片(正方形),RGB Compressed PVRTC 4bits和RGBA Compressed PVRTC 4bits两种格式,占用内存是一样的,如果把一张图片分成两张,那么在iOS平台是不是占用内存多一倍?有透明通道的,对于它的图集怎么处理会更好一点?&/strong&&/p&&blockquote&&p&通常iOS下是不需要做通道分离的,因为 iOS 通用的 PVRTC 格式支持 Alpha 通道。但目前也有团队反馈,在 iOS 上进行通道分离有助于减少失真,可以在一定程度上提高视觉效果,因此也可以尝试做一个对比。&br&如果发现占用内存是一样的,那么原始图片是RGB的。如果iOS上做通道分离,内存确实会增加一倍。UI的纹理在iOS下可以直接选择默认的 Compress,在打Atlas时会自动处理成 PVRTC,开发团队可以从Sprite packer窗口来看Atlas的压缩格式做个确认。&/p&&/blockquote&&p&&strong&Q5:在Unity 4.x的版本中,所有UI贴图使用ETC2格式,即使目标设备不支持该格式,也会解压成RGBA32使用。 而在目前使用的Unity 5.3.4版本中,iOS平台无法设置ETC2格式。如果压缩只能使用PVRTC格式,那么PVRTC存在显示效果比较差,并且图片必须为正方形,但如果用RGBA32格式,贴图占用的内存和存储又都过大,请问目前版本的Unity在iOS平台上应该如何设置UI贴图的压缩格式?&/strong&&/p&&blockquote&&p&我们建议可以先尝试其他的压缩格式看是否可以达到类似的效果,如ASTC格式。ASTC 在 iOS 的高端机上是被支持的,因此理论上在 Editor 下不会强制把 ASTC 转为 RGBA32,建议尝试设置为 ASTC 后打包,从 Editor.log 中或者直接从包体大小上可以看出是否确实使用了 ASTC。&/p&&p&一般来说,如果 RGBA16 的效果可以接受的话,建议使用 RGBA16,虽然打包时相对大一些,但是内存中相比 RGBA32 能够减半,但使用 ASTC 的话,虽然打包时比较小,但是在普通机型上会被处理成 RGBA32,导致过大的内存开销。&/p&&/blockquote&&p&&strong&Q6:请问Unity引擎中使用什么贴图压缩格式,可以保证在占用内存相对较小的情况下True Color效果和原图相当?同时在iOS和Android平台上图片的压缩格式分别用什么比较合适?有什么需要注意的地方吗?&/strong&&/p&&blockquote&&p&目前来讲,并不存在一个所有GPU平台都支持硬件解压的压缩格式。 ETC1 和 PVRTC 分别是Android和iOS上我们最推荐的格式。 但对于透明纹理,ETC1不支持,而 PVRTC 则可能有较大失真,因此更推荐使用 RGBA 16。&br&一般来说建议直接使用 Unity 默认的压缩格式(即选择 Compressed 即可,不需要做特殊设置),Unity 会做如下处理:&/p&&ol&&li&Android 上不带Alpha通道的图片采用 ETC1,带Alpha通道的图片采用True Color中的RGB16,TrueColor中的 RGBA16 会&比 RGBA32 更节省空间,但图像的显示质量会差一些;&/li&&li&iOS 上使用 PVRTC,但PVRTC格式要求纹理的长宽相等,且都是2的幂次(即POT,在ImportSettings中可以将NPOT的纹理自动转换成POT)。&/li&&/ol&&p&另外,针对Android 上的带Alpha通道的图片,还有一种常见的做法,即把Alpha通道独立出来作为另一张纹理,从而将 RGB 部分和 Alpha 部分分别采用 ETC1来压缩,但渲染时就需要自定义的 Shader来处理。&br&同时,我们不建议直接使用 RGBA32 格式的纹理,因为它占用了很大的内存。一般建议使用 RGBA16 和 ETC 格式的纹理来进行加载。 如果转换到 RGBA16 格式时出现了类似“色阶”的颜色问题,则建议尽可能避免大量的过渡色使用。&/p&&/blockquote&&p&&strong&Q7:请问游戏中特效使用的很多贴图, 一般有什么好的方式去管理吗 ? 不合并图集的话会有上千张小的透明贴图, 合并图集又会有占用内存过多的问题。&/strong&&/p&&blockquote&&p&可以合并成Atlas,一般将尽可能同时出现频率较高的Texture合成Atlas,这样并不会造成内存过大。在这方面也可以参考我们前不久推荐的插件&a href=&https://link.zhihu.com/?target=http%3A//blog.uwa4d.com/archives/Resource_Plugin.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Mesh Baker&/a&。&/p&&/blockquote&&p&&strong&Q8:iOS上方形POT图片有时候会失真,请问这种情况如何避免?一张NPOT的图变换成POT,是否有推荐的方法? 采用 ToLarger 的模式拉成POT是否会有损失呢?&/strong&&/p&&blockquote&&p&在其他设置一致的情况下,这两种方式无论在加载还是渲染方面其实并没有实质上的差别。在我们接触到的大多数案例中,纹理资源方面的问题除了尺寸外,纹理格式、Mipmap设置和Read&Write功能同样是需要研发团队时刻关注的。&/p&&/blockquote&&p&&strong&Q9:纹理Atlas是建议合成一张2048(尺寸)的纹理还是四张1024的纹理?&/strong&&/p&&blockquote&&p&在其他设置一致的情况下,这两种方式无论在加载还是渲染方面其实并没有实质上的差别。在我们接触到的大多数案例中,纹理资源方面的问题除了尺寸外,纹理格式、Mipmap设置和Read&Write功能同样是需要研发团队时刻关注的。&/p&&/blockquote&&p&&strong&Q10:NGUI的图集在内存里存了多份,求问怎么清理?&/strong&&br&&figure&&img src=&https://pic2.zhimg.com/v2-c13d71dfcb_b.jpg& data-rawwidth=&263& data-rawheight=&260& class=&content_image& width=&263&&&/figure&&/p&&blockquote&&p&游戏运行中,UI Mesh出现多份不同内存的情况,是正常的,因为随着UI widget使用的增加或减少,创建的UI Mesh是会随着变化的。同时,如果不同UIPanel中存在相同Atlas的Widgets,则也会出现上图中的情况。因此,建议大家遇到这种情况时,查看单帧中NGUI UI Mesh重名的是否有多份重名资源。如果存在,则说明相同Atlas中的资源被多个不同的UIPanel所使用,这种情况是需要尽可能避免的。&br&&figure&&img src=&https://pic2.zhimg.com/v2-8eb2d1139bc4eddeded1ad_b.jpg& data-rawwidth=&2842& data-rawheight=&1538& class=&origin_image zh-lightbox-thumb& width=&2842& data-original=&https://pic2.zhimg.com/v2-8eb2d1139bc4eddeded1ad_r.jpg&&&/figure&&br&&/p&&/blockquote&&p&&strong&Q11:我在UWA报告中看到大量的n/a资源,其格式的高度和宽度等信息都无法获取,并且存在大量重复,请问我该如何定位这些文件?能否优化解决呢?&/strong&&/p&&blockquote&&p&&图中n/a资源是我们在项目运行时检测到的无名称资源,一般来说,该类型资源并非Asset文件夹中的美术资源,而是项目通过脚本动态生成的资源,比如new Mesh、new Texture等操作,即会生成这种类型的无名称资源。&br&对此,我们建议研发团队详细检测逻辑代码/第三方插件中诸如New Mesh/Textue等此类操作,同时,在脚本动态生成该类资源后,为其赋上一个名字,这样即可在后续测试中看到对应名称的资源使用情况。&&/p&&/blockquote&&h2&&strong&网格相关&/strong&&/h2&&p&&strong&Q1:如果一个模型对应Skinned Mesh Renderer实例,那其所占的内存会随着角色增加而增长么 ?&/strong&&/p&&blockquote&&p&简单地从一个角色Prefab实例化(Instantiate)出多个实例时,Mesh并不会出现多份(这个行为与其他资源是一致的,包括Texture,AnimationClip,Material等等)。如果在内存中发现多份,可以考虑从项目中AssetBundle的加载方式入手,因为即使是同一个AssetBundle中的同一个角色Prefab,如果被反复进行“加载-实例化-卸载”操作,依然是会导致Mesh出现多份的(当然其他的资源也是一样)。&/p&&/blockquote&&p&&strong&Q2:我有一个特效依赖了两个FBX。我把这两个FBX的这个勾选去掉,Editor运行正常。否则就会宕机,请问这是什么原因?&/strong&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-4d683f3e50f26c192e6a524acd3534ac_b.jpg& data-rawwidth=&332& data-rawheight=&33& class=&content_image& width=&332&&&/figure&&blockquote&&p&将FBX上的Read/Write Enabled关闭后,内存中便不再保存其Mesh的副本(只存在显存中),因此其属性就不可再被访问和修改。而粒子系统通常需要动态地修改其粒子的顶点属性。因此,理论上来说,供粒子系统使用的Mesh是需要开启Read/Write Enabled的,而在Editor下Mesh和Texture都是强制开启的,所以在真机上就会出现问题。&/p&&/blockquote&&p&&strong&Q3:MeshBaker 烘焙的Mesh可以保存到Prefab中,但是不能像FBX一样,设置Model导入设置中的Generate Lightmap UVs 等信息,请问有没有大招可以处理此情况?&/strong&&/p&&blockquote&&p&首先从理论上说,一个 Mesh 只能有一个 LightmapIndex 和 LightmapOffset 属性,这就决定了 Mesh 的合并必须在 Lightmap 的烘焙之前。&br&而在做Mesh合并时,需要注意到UV2对于一个Mesh而言,其所有三角面的UV区域都必须是互不重叠的,所以不能简单直接地合并。&br&考虑到合并前每一个Mesh的UV2区域都应该是在[0,1]x[0,1]的区间中,在合并时可以给每一个UV2区域做一个缩小和平移,从而可以把每个区间在互不重叠的情况下,放到同一个[0,1]x[0,1]的区间中。&br&在UV2也正确拼合后,重新进行Lightmap的烘焙即可得到正确的效果。&/p&&/blockquote&&h2&&strong&动画片段相关&/strong&&/h2&&p&&strong&Q1:我想要在Editor下批量地对Animator Controller文件中每一个的State里的Animation Clip进行替换,但好像没有看到 Unity引擎有提供类似的API,只提供了能在Runtime时进行替换的方法,类似下图:&/strong&&br&&br&&figure&&img src=&https://pic4.zhimg.com/v2-c4fac515ea_b.jpg& data-rawwidth=&521& data-rawheight=&89& class=&origin_image zh-lightbox-thumb& width=&521& data-original=&https://pic4.zhimg.com/v2-c4fac515ea_r.jpg&&&/figure&&br&&strong&我现在想要达到的目地是在Editor下写一个批量替换Animation Clip的插件,请问下Unity引擎是否有提供这样的接口呢?&/strong&&/p&&blockquote&&p&在Unity 5.x 中已有一套完整且稳定的 API 可以访问、修改和创建 Animator 中的任何元素。其命名空间是在 UnityEditor.Animations 下,以下Blog 中有一个简单的例子是通过脚本创建一个 AnimatorController 以及其中的各种属性和参数。&a href=&https://link.zhihu.com/?target=http%3A//blogs.unity3d.com//shiny-new-animation-features-in-unity-5-0/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Shiny new animation features in Unity 5.0 – Unity Blog&/a&&br&另外,如果需要修改Animation Clip,可以直接修改一个 AnimationState 的 Motion 属性。 Animation Clip可以继承自 Motion。&/p&&/blockquote&&p&&strong&Q2:如果我的Animator是直接引用了FBX里的动画文件,而不是复制了FBX的动画文件出来再引用,那么打包的时候会把FBX都打包吗?&/strong&&/p&&blockquote&&p&这种情况下并不会把 FBX 打入 AssetBundle 中。将动画文件Copy出来通常是为了直接对动画文件打包,作为依赖包。&/p&&/blockquote&&p&&strong&Q3:我们的动画是放在FBX文件里的&/strong&&/p&&p&&figure&&img src=&https://pic1.zhimg.com/v2-65d3c4b9c29e46714d22c_b.jpg& data-rawwidth=&425& data-rawheight=&426& class=&origin_image zh-lightbox-thumb& width=&425& data-original=&https://pic1.zhimg.com/v2-65d3c4b9c29e46714d22c_r.jpg&&&/figure&&strong&这样做导致打包的时候把一些无用的文件也打进AssetBundle包里了,实际上我们只想使用最后这个动画文件。但在编辑器里选中FBX文件里的动画文件时却没有AssetLabels这个窗口,设置不了AssetBundle Name。&/strong&&br&&br&&figure&&img src=&https://pic4.zhimg.com/v2-366c88ec8cffce8b8e5924e_b.jpg& data-rawwidth=&328& data-rawheight=&80& class=&content_image& width=&328&&&/figure&&br&&strong&是不是只能用代码设置?还是意味着不能设置AssetBundle Name,只能把动画文件提取出来,类似下图这样单独的一个文件?&/strong&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-43d7f4ad4bf60a05adf7_b.jpg& data-rawwidth=&337& data-rawheight=&41& class=&content_image& width=&337&&&/figure&&blockquote&&p&在Unity 5.x 的打包机制下确实无法手动为 FBX 下的 Mesh 或 AnimationClip 单独资源设置 AssetBundle Name。因此,如果需要将这部分资源抽出来作为依赖包,目前确实就需要先通过脚本将这部分资源提取出来了。&/p&&/blockquote&&h2&&strong&音频相关&/strong&&/h2&&p&&strong&Q1:请问音频中的 Quality 什么意思?一般设置为多少合适?我拖进去一首歌曲,试了一下 在0 和 100 的情况下区别不大,但是生成的音频文件大小差别很大。&/strong&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-2c08dfddbd3ce_b.jpg& data-rawwidth=&572& data-rawheight=&150& class=&origin_image zh-lightbox-thumb& width=&572& data-original=&https://pic4.zhimg.com/v2-2c08dfddbd3ce_r.jpg&&&/figure&&blockquote&&p&Quality 表示在压缩音频时的失真程度(实际上可以认为是压缩算法的一个参数),该值越大,压缩后的文件越大,但音质保留的越好。而对于其失真的程度是视音频数据以及内部的压缩算法而定的,确实会有区别不大的情况。该值的设置原则就是,在音质失真可接受的情况下,越小越好。&/p&&/blockquote&&h2&&strong&材质相关&/strong&&/h2&&p&&strong&Q1:我们发现材质实例数量特别多,想问下这个对性能的影响如何,有没有什么建议?&/strong&&/p&&blockquote&&p&Material的内存占用一般很小,所以大量的Material资源对于内存的压力其实很小的。但是,它本身对于场景的切换时间是有影响的,即资源冗余得越多,切换场景时,UnloadUnusedAssets的开销越大,进而增加了场景的切换时间,同时也会影响DrawCall的拼合。所以,建议研发团队尽可能定位资源冗余的原因,并对其进行修复和完善。这一点,我们在UWA性能测评报告中的“分析和建议”中都有详细说明。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-9e219de77ad55327dcd8_b.jpg& data-rawwidth=&2162& data-rawheight=&839& class=&origin_image zh-lightbox-thumb& width=&2162& data-original=&https://pic3.zhimg.com/v2-9e219de77ad55327dcd8_r.jpg&&&/figure&&/blockquote&&p&&strong&Q2:我在UWA上进行了性能检测,在资源内存这里看到详情如下。请问这个数量峰值大于1是不是就是有问题的?但一个Material是很可能被实例化多份的。实例化后对象释放掉,然后清理掉原始的Material,按道理就不算冗余吧?毕竟大部分都是材质在操作,对贴图资源应该没有影响。而且,如果确实有那么多角色同屏怎么办呢?&/strong&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-a604d3e1d4e23f23f21347_b.jpg& data-rawwidth=&590& data-rawheight=&370& class=&origin_image zh-lightbox-thumb& width=&590& data-original=&https://pic1.zhimg.com/v2-a604d3e1d4e23f23f21347_r.jpg&&&/figure&&blockquote&&p&是的,如果数量峰值&1,则说明存在资源冗余的风险。如果是Material实例化,那么后者是有个(instance)后缀的,比较好识别。如果是new Material(Shader)出来的,那么是没有instance后缀的。但无论是哪种方式,如果数量峰值较大,都应引起大家注意。一般都是可以通过其他方法来尽可能避免冗余的。&/p&&p&如果变化不是随机的,且Material参数变化情况比较少,那么可以根据参数的变化情况只做几种Material,然后通过脚本动态赋值。如果是随机或者动画,那就没什么办法了,要么改需求,要么就接受这么多。&/p&&/blockquote&&h2&&strong&Shader相关&/strong&&/h2&&p&&strong&Q1:我用内建的Shader渲染场景,深度图里有内容。而用自己的Shader,取到的深度图什么都没有,都是1,什么原因导致的呢?我已经打开ZWrite了。&/strong&&/p&&blockquote&&p&Unity的_CameraDepthTexture 的生成,会根据Rendering Path的选择和设备的不同使用不同的方法实现,一种是直接从depth buffer获取,另一种是添加额外的Pass来渲染到纹理。目前在移动设备上主要是通过后者实现,而后者的实现借助了Shader Replacement的机制(批量替换为简单的Shader,并将深度渲染到纹理中)。&br&因此,在使用自定义的Shader时,就需要正确地设置RenderType的Tag(所有内置Shader都是设置好的),从而使得Shader Replacement正确地执行。具体可见文档:&a href=&https://link.zhihu.com/?target=http%3A//docs.unity3d.com/Manual/SL-ShaderReplacement.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Rendering with Replaced Shaders&/a&&/p&&/blockquote&&p&&strong&Q2:我们的游戏使用 Spine 插件,因为要用到裁切动画,所以修改了Shader,但在使用的时候出现异常: Shader wants normals, but the mesh Skeleton Mesh doesn't have them,可能是什么原因?&/strong&&/p&&blockquote&&p&开发团队需要注意:Surface Shader在生成代码中默认会处理normal(即 Spine/Skeleton 实际上是需要 normal 的),而对应的Mesh并没有包含normal,所以在预览窗口里渲染的时候会检查 Mesh 是否包含 normal 信息,没有的话会报这个错误。&br&开发团队可以尝试编写一个Vertex & Fragment Shader 从而避免处理normal,也可以尝试创建带normal的Mesh,来避免该问题。&/p&&/blockquote&&p&&strong&Q3:以前端游时代,材质根据Pass不同、光照环境不同可以离线预编译成ShaderCache,运行时并不需要拼材质再实时编译,只要加载二进制代码就好了。那Unity有没有做这件事呢?我们是根据平台和环境预编译的Shader。&/strong&&/p&&blockquote&&p&对于支持 Binary Shader 加载的设备,在首次编译某个 Shader 的时候是会生成其对应的 Binary Shader Cache ,生成的 Binary 文件位于和 Application.persistantPath 并列的Cache 目录下。&/p&&/blockquote&&p&&strong&Q4:相同效果前提下,就性能而言,Shader 是用 V&F 还是Surface好?&/strong&&/p&&blockquote&&p&Surface生成的V&F比较庞杂,分支较多,如果不注意 #pragma surface 参数的选择,容易出现不必要的开销。举例来说,如果直接用 Unity 5.x 中默认创建的 Surface Shader (默认参数为 #pragma surface surf Standard fullforwardshadows),那么 Shader 是会做 Physically based Standard Lighting 的,而这在移动端开销非常大,且并非必要。&/p&&/blockquote&&p&&strong&Q5:某个Shader里设置了Culling Off,会影响到后面所有Shader的渲染状态么(假设后面不再设置Culling)?&/strong&&br&&figure&&img src=&https://pic4.zhimg.com/v2-ec479d067d992b5ea867f1_b.jpg& data-rawwidth=&583& data-rawheight=&23& class=&origin_image zh-lightbox-thumb& width=&583& data-original=&https://pic4.zhimg.com/v2-ec479d067d992b5ea867f1_r.jpg&&&/figure&&/p&&blockquote&&p&一次 Draw Call 提交所相关的 Render State 是不会影响到下一次的渲染状态的。如果不在 Shader 中显示指定 Cull 模式,则会使用默认的 Cull Back。&/p&&/blockquote&&p&&strong&Q6:我们将Shader放到了Resource的目录下,也已加到Editor的GraphicSetting里,也试过在加载一个空的Prefab时绑定对应的Shader。 但该Shader在Editor里无法正常显示,看运行时指向是有的,重新指一下就能显示了, 然而打包以后在手机上显示正常。&/strong&&/p&&blockquote&&p&这确实是Unity已知的一个问题,Android 和 iOS 的部分Shader在打包后,在Editor 下无法正常显示。 主要原因是在打包时,只会把对应平台的Shader预编译代码(如 gles )打入包中,因此在 Editor 下会执行失败(通常 Editor 是 d3d 驱动)。 因此,目前只能尝试在Editor下重新指定Shader来绕过这个问题。&/p&&/blockquote&&p&&strong&Q7:我在shader里这么写的代码&/strong&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&o.texcoord1 = vec2(mod(v.texcoord.x,1.0),mod(v.texcoord.y,1.0));
&/code&&/pre&&/div&&p&&strong&但是报错 undeclared identifier 'mod' at line 106 (on d3d11),请问是什么原因导致的呢?&/strong&&/p&&blockquote&&p&报错表明mod在d3d11的Shader中是未定义的,如果开发团队无需在d3d11的平台上使用该 Shader,则可以添加以下预编译指令:&br&#pragma exclude_renderers d3d11&br&如果Shader依旧无法正常显示,那可能是因为在Editor中使用的是 DX11(可以从标题栏中看出)。 可以尝试修改DX9的参数 :Build Settings -& 点击 PC, Mac ... -& Player Settings(不需要点击 Switch Platform) -& 去掉 Auto Graphics API for Windows 的勾选,只保留 Direct3D9。同时,开发团队也可以直接使用 fmod 替换 mod,理论上 fmod 在各个平台都是支持的。&/p&&/blockquote&&h2&&strong&字体相关&/strong&&/h2&&p&&strong&Q1:我们现在为了美观,需要同时使用2套字体。但是每增加一套字体,就会内存增加50MB左右。请问你们在优化其他Unity游戏时,怎么处理类似情况的?&/strong&&/p&&blockquote&&p&如果美术字不多的话,建议使用单独的字体贴图来进行实现,从而来达到特定美术字显示的效果;如果美术字较多的话,那么仅能建议使用另外一个套字体来进行实现。一般来说,字体的内存量应该也是完全可以控制在10MB以下的。&br&开发者可以直接在Unity Profiler中查看字体的内存占用,也可以通过&a href=&https://link.zhihu.com/?target=http%3A//www.uwa4d.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&UWA网站&/a&上测评报告中的具体资源信息页面查看对应的字体资源使用情况。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-3c726a59e8e2ed1af596d441a85dc3c7_b.jpg& data-rawwidth=&2184& data-rawheight=&538& class=&origin_image zh-lightbox-thumb& width=&2184& data-original=&https://pic4.zhimg.com/v2-3c726a59e8e2ed1af596d441a85dc3c7_r.jpg&&&/figure&&/blockquote&&p&&strong&Q2:我做的预设用到了这个字体&/strong&&br&&figure&&img src=&https://pic4.zhimg.com/v2-6fbad79e32cef05b4720207faeff4ead_b.jpg& data-rawwidth=&939& data-rawheight=&446& class=&origin_image zh-lightbox-thumb& width=&939& data-original=&https://pic4.zhimg.com/v2-6fbad79e32cef05b4720207faeff4ead_r.jpg&&&/figure&&strong&我将这个预设打成AssetBundle包,通过Profiler分析时发现占了两份内存。&/strong&&/p&&p&&figure&&img src=&https://pic3.zhimg.com/v2-c4d8fbd8aad_b.jpg& data-rawwidth=&966& data-rawheight=&182& class=&origin_image zh-lightbox-thumb& width=&966& data-original=&https://pic3.zhimg.com/v2-c4d8fbd8aad_r.jpg&&&/figure&&strong&下面这个SIMHEI应该是那个TTF的,为什么会占两份内存呢?&/strong&&/p&&blockquote&&p&通常TTF文件会包含一个字体的多个字型,如可能包含正常字型、加粗字型、斜体字型等。而在Unity中会将其分为不同的Font资源,且他们之间会相互依赖。所以,如果项目中确实需要加粗字型的话,内存里出现两个Font是正常的,但如果实际上不需要加粗,那么可以尝试寻找一个不包含加粗字型的字体文件来替换该TTF文件。&/p&&/blockquote&&h2&&strong&粒子系统&/strong&&/h2&&p&Q1:我在UWA上提交了资源检测,资源打的是依赖包,报告显示Default—Particle这个资源存在大量冗余,这个是正常的吗?&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-b280fa51b5e85ca15fec3b3f11204d79_b.jpg& data-rawwidth=&741& data-rawheight=&409& class=&origin_image zh-lightbox-thumb& width=&741& data-original=&https://pic3.zhimg.com/v2-b280fa51b5e85ca15fec3b3f11204d79_r.jpg&&&/figure&&blockquote&&p&Default—Particle 这个是粒子系统的默认资源。如果使用的是默认的粒子系统,没有对Material进行修改,且每个粒子系统都是打一个AssetBundle文件的话,那么该冗余问题是正常的。对此,我们建议开发团队把下图中默认的Material换成自己的资源,不使用Built-in资源,这样通过依赖关系打包,就不会出现该资源冗余的问题了。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-4e9d0b14ac4b4a614122_b.jpg& data-rawwidth=&606& data-rawheight=&358& class=&origin_image zh-lightbox-thumb& width=&606& data-original=&https://pic4.zhimg.com/v2-4e9d0b14ac4b4a614122_r.jpg&&&/figure&&/blockquote&&h2&&strong&Lightmap&/strong&&/h2&&p&&strong&Q1:Unity 5.x 能把指定集合的Mesh烘焙到一张Lightmap里吗?&/strong&&/p&&blockquote&&p&Unity 5.x 是没有这样的功能项的。据我们的判断,这样的需求通常是为了动态加载,因此可以尝试将Mesh分组到不同的场景分别烘焙。而在加载时可通过脚本动态地合并Lightmap,同时将物件的Lightmap Index进行正确的偏移即可。&/p&&/blockquote&&p&&strong&Q2:Lightmap在Baked GI的等待时间比较长(Realtime GI已关闭),想请教有没有什么建议的参数或是方式,可以缩短等待的时间?&/strong&&/p&&blockquote&&p&目前就我们的了解,在Unity 5.x比较影响烘焙时间的主要是大面积的面片导致Light Transport 过程过久(Enlighten 的机制所限)。可以尝试拆分面积较大的面片,来提高烘焙的速度(通常,拆分大面积的面片对渲染性能也会有所提升)。&br&主要原因可参考如下的帖子: &a href=&https://link.zhihu.com/?target=http%3A//forum.unity3d.com/threads/light-transport-problem-with-large-objects.310405& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Light transport problem with large objects&/a&&/p&&/blockquote&&p&&strong&Q3:如下图所示,第一张显示的是没有烘培Lightmap的场景效果,里面有一盏点光源;第二张显示的是烘培Lightmap后的场景效果。请问为什么同一盏点光源照亮的效果差别那么大?&/strong&&br&&figure&&img src=&https://pic4.zhimg.com/v2-2e4b8baa4ac6e0ebd9fa_b.jpg& data-rawwidth=&964& data-rawheight=&546& class=&origin_image zh-lightbox-thumb& width=&964& data-original=&https://pic4.zhimg.com/v2-2e4b8baa4ac6e0ebd9fa_r.jpg&&&/figure&&figure&&img src=&https://pic3.zhimg.com/v2-c6a75cc50eb771f22a3b4_b.jpg& data-rawwidth=&968& data-rawheight=&545& class=&origin_image zh-lightbox-thumb& width=&968& data-original=&https://pic3.zhimg.com/v2-c6a75cc50eb771f22a3b4_r.jpg&&&/figure&&/p&&blockquote&&p&简单来说,这就是实时的直接光照和全局光照的差别。&br&在渲染时前者只能处理光源和单个物件之间的直接光照,而后者在烘焙时是通过光线跟踪或者辐射度等复杂算法,计算出所有物体各个表面之间相互反射的光照信息,这也是烘焙Lightmap需要较久的时间的原因 。可以发现在全局光照下,即使是物体的背面也会因为其它表面的反射而被照亮,这在直接光线下就无法实现这样的效果。&/p&&/blockquote&&p&&strong&Q4:当关闭预渲染GI时会出现IndirectResolution,这个参数有什么用,为什么调大了以后会大大增加渲染时间,但是烘培出来没有啥效果。&/strong&&/p&&blockquote&&p&简单来说,该值主要控制的是GI的烘焙密度,数值越大,表示每个单位距离内的texel越多,即烘焙得越精致,自然烘焙的时间也越长。该值并不需要越大越好,场景越小,建议该值越低。该值为1时,对于多数场景,其烘焙效果已经足够了,升高该值,其效果也不会有明显提升。&br&开发者也可以参考Unity官方的说明文档:&br&&a href=&https://link.zhihu.com/?target=http%3A//docs.unity3d.com/Manual/GlobalIllumination.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Unity - Manual: Lighting Window&/a&&/p&&/blockquote&&p&&strong&Q5:Lightmap丢失。用Unity5.1.2的AssetBundle做热更新,资源导出的时候分析了所有的依赖项单文件导出。比如在导出场景的时候场景的烘焙出来的LightmapSnapshot.asset文件导出不了,导致运行的时候场景的Lightmap丢失了。&/strong&&/p&&blockquote&&p&LightmapSnapshot.asset 本身是Editor下使用的,并不能单独被打包进AssetBundle。 运行时加载Lightmap,一种方法是把场景(.unity 文件)打成AssetBundle加载,Lightmap 信息会打入场景AssetBundle(因为Lightmap信息和场景绑定)。另一种是通过Lightmapsettings.Lightmaps方法来运行时设置。需要注意的是,同时还需要重设Prefab的Lightmap信息(Lightmapindex和Lightmapscaleoffset),因为Lightmap信息在Unity 5.x下不会保存在Prefab 上。&br&另外存在一种可能,Unity 5.x中加入了Shader Stripping功能,在打包时,默认情况下会根据当前场景的Lightmap及Fog设置对资源中的Shader进行代码剥离。这意味着,如果在一个空场景下进行打包,则Bundle中的Shader会失去对Lightmap和Fog的支持,从而出现运行时Lightmap和Fog丢失的情况。 而通过将Edit-&Project Settings-&Gaphics下Shader Stripping中的modes改为Manual,并勾选相应的Mode即可避免这一问题。&/p&&/blockquote&&p&&strong&Q6:Lightmap在PC上显示正常,但是转到Android平台上存在色差,颜色普遍偏暗。&/strong&&/p&&blockquote&&p&一般来讲,有两种情况可能会导致色偏和亮度差异。&/p&&ol&&li&&p&Unity烘焙的Lightmap是32bit的HDR图,而移动设备通常不支持HDR图(32bit per channel),会按照LDR图(8bit per channel)的形式进行处理,因此会出现色偏问题。因此我们建议:&br&1)在移动平台下使用Mobile/Diffuse材质,可载入Standard Assets(Mobile) package获得。如果要获得更合适的效果,需要自行修改Lightmap的DecodeLightmap函数,该函数可在Unity\Editor\Data\CGIncludes\UnityCG.cginc文件中找到。需要说明的是,这种方法也不能达到与PC端完全一致的效果。&br&2)如果需要PC和移动平台的显示效果一致,可以用图像编辑软体修改Lightmap為LDR格式,例如PNG(8bit per channel)。&br&3)为了避免类似问题,请不要使用过于强烈的Light进行烘焙,因為Light的强度(Intensity)越高,色偏问题会越严重。若有阴影丢失时,可以尝试检查一下模型的Lightmapindex、Lightmapscaleoffset、UV2等影响Lightmap采样的一些参数。&/p&&/li&&li&&p&另一种可能是存在过曝现象,可以尝试将playersettings -& use direct3d 11关闭,看问题是否解决。&/p&&/li&&/ol&&/blockquote&&p&&strong&Q7:在同一场景里烘培的Lightmap,我用了2张的光照图,大小是5.3MB;别人用了3张的图,大小是4.3MB。请问是什么影响这个光照图的大小,在哪里调?&/strong&&/p&&blockquote&&p&首先,请确认下Lightmap的类型,Single类型只生成一张,而Dual和Directional会生成两张。 其次,请确认下当前的发布平台,Android下的Lightmap会比Standalone更小。因为不同平台采用的压缩格式不同。此外,Lightmapping中的Lock Atlas,Resolution,Padding等选项也会影响最后烘焙光照图的大小。&/p&&/blockquote&&p&&strong&Q8:在游戏中,有些Mesh在编辑时候是接收Lightmap的,出于某些原因我们合并了相同的Mesh(材质也相同)。但是发现原先的Lightmap不再影响合并后的Mesh,请问怎么才能实现让合并后的Mesh也接收原先的Lightmap?&/strong&&/p&&blockquote&&p&如果Lightmap不止一个的话,手动合并Mesh是会出现问题的,因为合并的Mesh烘焙信息很可能出现在不同的Lightmap中,但合并之后的Mesh在渲染时只能使用一个Lightmap,这样uv2读取到Lightmap信息就会出现问题,进而出现这种现象。其实,对于材质相同的Static物体并不需要手动对其Mesh进行combine,因为Unity的Static Batching会自行完成。而如果由于某种特定需求一定要将Mesh进行合并的话,那么也要将其所需要的Lightmap也一并合并,同时改变相应的uv2。不仅如此,Shader中Lightmap也需要进行相应修改,这是比较复杂的,所以我们并不建议这样的做法,因为可能会花掉开发团队大量的开发时间。&/p&&/blockquote&&p&&strong&Q9:当关闭预渲染GI时会出现IndirectResolution,这个参数有什么用,为什么调大了以后会大大增加渲染时间,但是烘培出来却没有什么效果。&/strong&&/p&&blockquote&&p&该值主要控制的是GI的烘焙密度,数值越大,表示每个单位距离内的Texel越多,即烘焙得越精致,自然烘焙的时间也越长。&br&该值并非越大越好,场景越小建议该值越低。该值为1时,对于多数场景,其烘焙效果已经足够了,升高该值,其效果也不会有明显提升。&/p&&/blockquote&
原文链接:在优化Unity项目时,对资源的管理可谓是个系统纷繁的大工程。鉴于Unity独特又绝(cao)妙(dan)资源打包的AssetBundle管理机制,不同资源的属性适合于不同的存储和加载方式。此外,要处理好成…
&figure&&img src=&https://pic3.zhimg.com/v2-ff389bc9cc6f9ee306b9_b.jpg& data-rawwidth=&1619& data-rawheight=&1080& class=&origin_image zh-lightbox-thumb& width=&1619& data-original=&https://pic3.zhimg.com/v2-ff389bc9cc6f9ee306b9_r.jpg&&&/figure&&h2&&b&前言&/b&&/h2&&p&前几天做导出安装包插件时,遇到了个问题,我需要获取地址,可是每次都要手动填入(复制粘贴)地址是个很费时不讨好的事,所以我就写了一个获取地址的小组件。 样子就是这样的:&/p&&figure&&img src=&https://pic4.zhimg.com/v2-bd9264dcfbee4b_b.png& data-rawwidth=&471& data-rawheight=&278& class=&origin_image zh-lightbox-thumb& width=&471& data-original=&https://pic4.zhimg.com/v2-bd9264dcfbee4b_r.jpg&&&/figure&&figure&&img src=&https://pic3.zhimg.com/v2-b583db92d4b91ad705b7a_b.png& data-rawwidth=&471& data-rawheight=&278& class=&origin_image zh-lightbox-thumb& width=&471& data-original=&https://pic3.zhimg.com/v2-b583db92d4b91ad705b7a_r.jpg&&&/figure&&p&一个文本和一个按钮,文本显示选择的路径(路径为空时显示提示语,并且无法选择),点击按钮打开面板选择文件夹。&/p&&p&&br&&/p&&h2&&b&声明&/b&&/h2&&ul&&li&&b&欢迎分享本文&/b&&/li&&li&&b&本文未经允许不能以任何形式转载。&/b&&/li&&/ul&&p&&br&&/p&&p&&br&&/p&&h2&&b&知识要点&/b&&/h2&&ul&&li&&b&组合GUI组件&/b&&/li&&li&&b&EditorGUI.BeginDisabledGroup()/EndDisabledGroup()&/b&&/li&&li&&b&EditorUtility.OpenFolderPanel()&/b&&/li&&/ul&&p&&br&&/p&&h2&&b&使用版本&/b&&/h2&&ul&&li&&b&Unity3D 5.3.3&/b&&/li&&/ul&&p&&br&&/p&&h2&&b&目标&/b&&/h2&&ul&&li&&b&如何把多个组件封装在一起,组合成自己需要用的组件,然后一句代码就可以调用&/b&&/li&&/ul&&h2&&b&准备&/b&&/h2&&p&&b&整个插件的结构:&/b&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-ff195eefd825e_b.png& data-rawwidth=&251& data-rawheight=&67& class=&content_image& width=&251&&&/figure&&p&在开始写主要逻辑之前,我们先要做准备工作,那就是,怎么打开下图这个窗口(系统选择文件夹的窗口)。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-a48ceadc2a040f9011b56_b.png& data-rawwidth=&960& data-rawheight=&540& class=&origin_image zh-lightbox-thumb& width=&960& data-original=&https://pic3.zhimg.com/v2-a48ceadc2a040f9011b56_r.jpg&&&/figure&&p&我在网上搜了一下“Unity3d 如何选择文件夹”的资料,发觉都是要导入一个&i&System.Windows.Forms.dll&/i&,然后调用&i&OpenFileDialog&/i&。 可是这种方式很不优雅,所以我就去找api,发现了原来&b&EditorUtility&/b&是有操作外部文件的方法(项目内部使用&b&AssetDatabase&/b&)。&b&EditorUtility&/b&里面的&b&OpenFilePanel()&/b&、&b&OpenFolderPanel()&/b&方法就是今天我们要用到的,选择文件和选择文件夹。&/p&&p&代码:&/p&&p&准备工作好了,那么接下来就是正式的代码逻辑了,我们先创建一个&b&GUIExtendWindow&/b&的窗口类,之前的教程已经教了很多次了,这里就不再叙述了。&/p&&p&然后申明一个字段“_folderPath”用于后面保存路径。&/p&&div class=&highlight&&&pre&&code class=&language-csharp&&&span&&/span&&span class=&k&&public&/span& &span class=&k&&class&/span& &span class=&nc&&GUIExtendWindow&/span& &span class=&p&&:&/span& &span class=&n&&EditorWindow&/span&
&span class=&p&&{&/span&
&span class=&na&&
[MenuItem(&Tools/GUIExtend&)]&/span&
&span class=&k&&public&/span& &span class=&k&&static&/span& &span class=&k&&void&/span& &span class=&nf&&ShowWindow&/span&&span class=&p&&()&/span&
&span class=&p&&{&/span&
&span class=&n&&EditorWindow&/span&&span class=&p&&.&/span&&span class=&n&&GetWindow&/span&&span class=&p&&&&/span&&span class=&n&&GUIExtendWindow&/span&&span class=&p&&&(&/span&&span class=&s&&&GUIExtend&&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&k&&private&/span& &span class=&kt&&string&/span& &span class=&n&&_folderPath&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&接下来就是今天的主角————&b&OpenFolderPanelField()&/b&方法。我们要把按钮和文本的逻辑都封装在这个方法里面。首先先看看整个方法的代码。&/p&&div class=&highlight&&&pre&&code class=&language-csharp&&&span&&/span&&span class=&c1&&/// &summary&&/span&
&span class=&c1&&/// &/span&
&span class=&c1&&/// &/summary&&/span&
&span class=&c1&&/// &param name=&path&&选择的路径&/param&&/span&
&span class=&c1&&/// &param name=&buttonLabel&&按钮上的文字&/param&&/span&
&span class=&c1&&/// &param name=&tips&&提示&/param&&/span&
&span class=&c1&&/// &returns&&/returns&&/span&
&span class=&k&&private&/span& &span class=&kt&&string&/span& &span class=&nf&&OpenFolderPanelField&/span&&span class=&p&&(&/span&&span class=&kt&&string&/span& &span class=&n&&path&/span&&span class=&p&&,&/span& &span class=&kt&&string&/span& &span class=&n&&buttonLabel&/span&&span class=&p&&,&/span& &span class=&kt&&string&/span& &span class=&n&&tips&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&kt&&bool&/span& &span class=&n&&disabled&/span&&span class=&p&&;&/span&
&span class=&kt&&string&/span& &span class=&n&&content&/span&&span class=&p&&;&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&kt&&string&/span&&span class=&p&&.&/span&&span class=&n&&IsNullOrEmpty&/span&&span class=&p&&(&/span&&span class=&n&&path&/span&&span class=&p&&))&/span&
&span class=&p&&{&/span&
&span class=&n&&disabled&/span& &span class=&p&&=&/span& &span class=&k&&true&/span&&span class=&p&&;&/span&
&span class=&n&&content&/span& &span class=&p&&=&/span& &span class=&n&&tips&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&k&&else&/span&
&span class=&p&&{&/span&
&span class=&n&&disabled&/span& &span class=&p&&=&/span& &span class=&k&&false&/span&&span class=&p&&;&/span&
&span class=&n&&content&/span& &span class=&p&&=&/span& &span class=&n&&path&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&n&&EditorGUILayout&/span&&span class=&p&&.&/span&&span class=&n&&BeginHorizontal&/span&&span class=&p&&();&/span&
&span class=&n&&EditorGUI&/span&&span class=&p&&.&/span&&span class=&n&&BeginDisabledGroup&/span&&span class=&p&&(&/span&&span class=&n&&disabled&/span&&span class=&p&&);&/span&
&span class=&n&&EditorGUILayout&/span&&span class=&p&&.&/span&&span class=&n&&TextArea&/span&&span class=&p&&(&/span&&span class=&n&&content&/span&&span class=&p&&,&/span& &span class=&n&&EditorStyles&/span&&span class=&p&&.&/span&&span class=&n&&label&/span&&span class=&p&&);&/span&
&span class=&n&&EditorGUI&/span&&span class=&p&&.&/span&&span class=&n&&EndDisabledGroup&/span&&span class=&p&&();&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&n&&GUILayout&/span&&span class=&p&&.&/span&&span class=&n&&Button&/span&&span class=&p&&(&/span&&span class=&n&&buttonLabel&/span&&span class=&p&&,&/span& &span class=&n&&GUILayout&/span&&span class=&p&&.&/span&&span class=&n&&Width&/span&&span class=&p&&(&/span&&span class=&m&&100&/span&&span class=&p&&)))&/span&
&span class=&p&&{&/span&
&span class=&kt&&string&/span& &span class=&n&&currentDirectory&/span&&span class=&p&&;&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&kt&&string&/span&&span class=&p&&.&/span&&span class=&n&&IsNullOrEmpty&/span&&span class=&p&&(&/span&&span class=&n&&path&/span&&span class=&p&&))&/span&
&span class=&p&&{&/span&
&span class=&n&&currentDirectory&/span& &span class=&p&&=&/span& &span class=&n&&Directory&/span&&span class=&p&&.&/span&&span class=&n&&GetCurrentDirectory&/span&&span class=&p&&();&/span&
&span class=&p&&}&/span&
&span class=&k&&else&/span&
&span class=&p&&{&/span&
&span class=&n&&currentDirectory&/span& &span class=&p&&=&/span& &span class=&n&&path&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&n&&path&/span& &span class=&p&&=&/span& &span class=&n&&EditorUtility&/span&&span class=&p&&.&/span&&span class=&n&&OpenFolderPanel&/span&&span class=&p&&(&/span&&span class=&n&&tips&/span&&span class=&p&&,&/span& &span class=&n&&currentDirectory&/span&&span class=&p&&,&/span& &span class=&s&&&&&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&n&&EditorGUILayout&/span&&span class=&p&&.&/span&&span class=&n&&EndHorizontal&/span&&span class=&p&&();&/span&
&span class=&k&&return&/span& &span class=&n&&path&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&三个参数的作用注释已经说明了,而参数部分是可以根据你功能自定义的,你可以替换成&b&GUIContent&/b&类型,也可以删除或增加,这就看具体要做到什么的效果了。&/p&&p&接着是判断路径参数是否为空。空的话,文本内容显示为tips,无法选择。不为空,文本内容显示路径,可以选择。&/p&&p&&b&EditorGUILayout.BeginHorizontal()&/b&方法之前的文章提到过,是水平布局的一个组件。 这些组件都是一对对的,有Begin就有End。例如&b&BeginDisabledGroup()&/b&/&b&EndDisabledGroup()&/b&,这是个禁用组件,如果参数为true,包含着的组件都会变成禁用状态。&/p&&p&在禁用组件中间我们绘制一个&b&TextArea&/b&组件,样式是&b&EditorStyles.label&/b&,这样,原本是文本就不会显示文本框,而又可以选择文本。&/p&&p&接着是点击按钮的逻辑,首先是准备一个默认目录待会打开,默认打开&b&path&/b&,如果&b&path&/b&为空,则获取项目的目录。&/p&&p&然后我们就可以是使用&b&OpenFolderPanel&/b&打开面板了,第一个参数为窗口的标题,第二个参数为默认打开的文件夹目录,第三个参数选择的文件夹的默认名字。使用很简单,用一下就可以了。然后这个方法会回调一个你选择的文件夹的绝对地址。然后我们赋值到参数path里,最后返回。&/p&&p&组件封装完毕了,接下来就是使用了,使用也很简单,跟&b&EditorGUILayout&/b&的方法一样使用就行了。&/p&&div class=&highlight&&&pre&&code class=&language-csharp&&&span&&/span&&span class=&k&&void&/span& &span class=&nf&&OnGUI&/span&&span class=&p&&()&/span&
&span class=&p&&{&/span&
&span class=&n&&_folderPath&/span& &span class=&p&&=&/span& &span class=&n&&OpenFolderPanelField&/span&&span class=&p&&(&/span&&span class=&n&&_folderPath&/span&&span class=&p&&,&/span& &span class=&s&&&Select Folder&&/span&&span class=&p&&,&/span& &span class=&s&&&please select Folder&&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&h2&&b&最后&/b&&/h2&&p&其实,Unity3D的&b&GUILayout&/b&、&b&EditorGUILayout&/b&等类都是采用上述的方法将多个组件(内容)封装在一起。 所以这种封装的方法我建议是写在一个类里面,然后变成静态函数,这样就可以任何地方都能使用。例如笔者就用了一个&b&EditorGUILayoutExtend&/b&作为封装组件的类。&/p&&p&有人问到,如果我不是选择文件夹,而是选择文件怎么办,其实做法也是一样的,当然,我也会在源代码里面把选择文件的逻辑加上。&/p&&blockquote&&a href=&http://link.zhihu.com/?target=https%3A//github.com/L-Lawliet/UnityEditorTutorial/blob/master/GUIExtend/Editor/GUIExtendWindow.cs& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&源代码&/a&&/blockquote&&p&==========================分割线==========================&/p&&p&如果大家有什么意见和建议,或者是有什么疑问,或者是有想看的知识点内容,都欢迎到评论区发上你们的评论。&br&&/p&&p&最后我希望有更多人参与到插件开发的队伍里。也欢迎大家投稿。&/p&&p&&br&&/p&&p&QQ群:&b&&/b&&/p&&p&&b&=========================最后的最后=======================&/b&&/p&&p&&b&你们觉得好记得赞啊,觉得不好可以评论啊,不然我不知道到底有没有人在看啊/(ㄒoㄒ)/~~&/b&&/p&
前言前几天做导出安装包插件时,遇到了个问题,我需要获取地址,可是每次都要手动填入(复制粘贴)地址是个很费时不讨好的事,所以我就写了一个获取地址的小组件。 样子就是这样的:一个文本和一个按钮,文本显示选择的路径(路径为空时显示提示语,并且无…
&p&做游戏技术主要讲究的是套路,以及对套路的掌握程度。比如说你要搞个体积光,那么从用mesh+uv动画,到volumetric scattering你都得知道,而且要知道这些方案的优缺点,以及具体的实现细节,比如camera会不会到体积光里边之类的,这种细节的了解会让你更加有信心做出各种技术决策。&/p&&p&所以3a级游戏的大神技术也是对各种领域的套路玩得比较溜,这里我也分享一些做游戏20来年自己领悟出的一些套路吧。&/p&&p&美术用工具输出的3d模型,材质一定要做一个导出插件,否则做出来和进引擎效果不一样,就只能做做手游这种无光照的手绘贴图质量的产品了。&/p&&p&动画要想不滑步,就只能用animation driven的方法,这个需要跟策划做好深度的沟通,得让策划知道移动不是说配置一个速度就可以了,得去找动画师一起调整移动的动画。&/p&&p&动态天气的困难不是制作上的困难,是可以用lightmap的物件会少很多,性能不一定扛得住,这个要在项目初期一定得和制作团队沟通清楚。&/p&&p&球类游戏要达到非常自然的动画,一方面动画肯定是要动捕的,另一方面更重要的是搭建一套动画选择机制,然后根据运动中的球类位置来选择最合适的动画来匹配,再加上小部分的ik。&/p&&p&头上冒字和冒血这种hud就应该用hud的标准方法来制作,切记不能涂省事用ui的方法,对性能效率会有非常大的影响。&/p&&p&音频对最终品质影响很大,一般遵循46原则,即图像资源在最终包中占6成,音频资源占4成。给音频设计师配置一个独立的程序来达成音频的设计需求。&/p&&p&状态机最好是用可视化的方法来实现,游戏中80%的bug都是和状态没切对有关,有个可视化的状态机对于找bug非常方便。&/p&&p&control是最需要状态机化设计的(不同的情况下按同样的按键达成不同的逻辑)&/p&&p&做面部表情,如果不是捕捉就用骨骼简单搭搭就好,如果是捕捉,制作成本会变得非常的高(制作各种morphing target)&/p&&p&对最终画面影响最大的是镜头效果,所以尽量节省渲染时间留给镜头特效。一般影响最大的是校色,如果硬件平台允许尽量给美术提供带深度校色的工具。&/p&&p&有比较宽广视野的游戏,室外可以用一些很取巧的方法来模拟mie scattering和rayleigh scattering,加上哪怕是假的对画面的提升也是巨大的。&/p&&p&对于不同的数据采用不同的配置方法,不要什么数据都用excel,对于有可视化需求的配置,比如ui或者角色身上需要装配一些武器的,提供可视化的工具。对于需要描述父子关系的例如技能树解锁之类的用json或者xml来描述,对于纯数字逻辑的就用csv就好了。&/p&&p&场景的材质如果制作normal map对于你们团队比较复杂,多加一层detail map也能对效果获得较大的提升。&/p&&p&角色的材质,如果性能有限或者说制作成本无法承受的话specular map比normal map的效果要好。&/p&&p&如果角色会近距离看脸,脸部的眼睛一定要单独拿出来处理,脸可以糊,眼睛一定不能糊。&/p&&p&脚步声的标准做法是在地面上放一层低模做和脚的碰撞检测(脚步声如果追求真实,最少得有3个以上的样本随机)&/p&&p&如果要提升动画效果,考虑主角的前臂加上twist骨骼,左肩和右肩不要从脖子上搭建骨骼,要从胸口开始(做head lookat的时候效果会更好)&/p&&p&衣服的标准做法是通过贴图来控制哪些顶点受skin和物理影响的权重比,那张贴图还可以用一个通道来控制流汗的时候哪些地方的smothness要提高。&/p&&p&搭建一个运行时数据库,并且游戏中经常需要访问的数据都放入数据库,可以类似redis那样非常简单的提供一个set和get就行了,运行时数据库可以帮助你找到绝大多数bug。&/p&&p&制作ai尽量使用行为树,并且花时间一定要让策划具备编辑和调式行为树的能力。&/p&&p&顶点色可以各种花式使用,无论是用来bake ao还是决定detail map的权重,都可以用很低廉的代价来获得非常棒的效果。&/p&&p&动画不是在任何时候都可以blend的,要想效果好,牢记:左脚落地的时候只能blend到左脚落地开始的动画,右脚同上。&/p&&p&做上下楼梯的locomotion的时候,用椭球碰撞体会非常简单的获得还不错的效果。&/p&&p&如果画面会经常快速的运动,可以加入一个vector based motionblur,效果会出奇的好。&/p&&p&要想场景生动,一定要使用decal,一个方便美术的decal工具可以让美术一天之内让整个场景提升几个档次。&/p&&p&暂时想到这些,不说了,休息好了继续干活。&/p&&p&~~~~~继续更新一波套路&/p&&p&解决alpha透贴排序的标准方法是两次绘制,第一次在不透明队列里渲染一次alpha test(cutout),打开zwrite,第二次在transparent队列里开alpha blend不开zwrite,ztest lessequal渲染就能还原美术在maya里看到的效果。&/p&&p&弹簧是个非常好用的物理组件,其虎克系数可以有效的模拟力的衰减来做出很多感人的效果,从乳摇,臀摇,尾巴,头发马尾,布料,脸上被重拳击中的肌肉变化都可以看到弹簧的身影。&/p&&p&adobe fuse cc + mixamo可以非常快速的搭建模型和动画来帮助策划找到剧情的场景的感觉。&/p&&p&脚下ik从程序来讲是很方便实现的,大多数引擎都有ik功能,但是工作流程我发现很多公司都没有正确使用。正确的流程是对输出的动画有一个左右脚高低的分析工具,逐动画生成每个脚步离水平面的高度曲线,然后运行时根据脚步的高低来决定ik和skin的权重。&/p&&p&镜头的设置很重要,最好给美术一个和相机镜头类似的算法来反过来计算fovx和fovy,我看到很多产品的fov都是一水的60之类的。&/p&&p&对于类似铁丝网或者其他半透物体的mipmap的标准做法是先自动生成mipmap,然后要美术手动的来降低不同lod贴图的alpha,换句话说近处看有铁丝网,远看就只有框中间近乎全透了来降低锯齿感。&/p&&p&dx10以上的平台上特效的shader加一句根据当前depth和已经绘制的depth的差来控制alpha可以实现简单且效果不错的软粒子效果。&/p&&p&头发的物理效果可以参考衣服的做法,发根受skin影响多,发梢受物理多一些即可。(额前刘海受物理要关掉重力)&/p&&p&如果实时sss负担太重,可以简单的把模型厚度信息烘培在顶点色的某个通道上,然后只需三两行代码就可以让皮肤有sss效果。&/p&&p&看到好多项目用双面材质只是在shader中简单加一句cull none,这个是完全错误的实现。正确的做法是需要把三角形索引信息走vs传递进来,然后判断是否顺逆时针,对于反面需要把法线反转才能获得正确的渲染结果。&/p&&p&先更新到这。&/p&&p&完了,感觉思绪开始打开了,又更新一些,怕一会会忘。&/p&&p&动画驱动的模式下,转向最少需要8个动画,原地左转90,右转90,左转180,右转180,移动同样四个,然后根据控制器的输入来决定混合的权重,一般神海这种级别的产品光locomotion牵扯到的动画会在40-50个这种量级。&/p&&p&对于衣物和皮肤,detail normal十分重要,可以瞬间让你的衣服能看出针织的材质。&/p&&p&处}

我要回帖

更多关于 unity3d粒子系统 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信