IsAlive

U3D的粒子系统脚本接口相信很多人都用过,ParticleSyetem类的一系列接口都有一个bool类型的参数——withChildren,通过这个参数可以直接将相同的判断或者操作应用到一整个通过Transform父子关系树关联起来的ParticleSystem实例集合上。然而,但凡方便的功能,里面就必然有性能陷阱……
以IsAlive这个接口为例(用来判断粒子系统是否所有粒子都已经消亡,一般用在非loop的例子发射器上),看看U3D里是如何实现这个接口的:
[csharp] view plaincopy
  1. public bool IsAlive()
  2. {
  3. bool withChildren = true;
  4. return this.IsAlive(withChildren);
  5. }
[csharp] view plaincopy
  1. public bool IsAlive(bool withChildren)
  2. {
  3. if (withChildren)
  4. {
  5. ParticleSystem[] particleSystems = ParticleSystem.GetParticleSystems(this);
  6. ParticleSystem[] array = particleSystems;
  7. for (int i = 0; i < array.Length; i++)
  8. {
  9. ParticleSystem particleSystem = array[i];
  10. if (particleSystem.Internal_IsAlive())
  11. {
  12. return true;
  13. }
  14. }
  15. return false;
  16. }
  17. return this.Internal_IsAlive();
  18. }

可以看到,如果传递的withChildren参数为true,那么函数会先尝试调用GetParticleSystems(this)来获取包括下级gameObject在内的所有能找得到的粒子系统组件,然后对这些粒子系统组件依次再调用IsAlive判断。而如果withChildren为false,就仅仅会判断自身。那么自然,开销大小与否,关键就在GetParticleSystems的实现上了。

[csharp] view plaincopy
  1. internal static ParticleSystem[] GetParticleSystems(ParticleSystem root)
  2. {
  3. if (!root)
  4. {
  5. return null;
  6. }
  7. List<ParticleSystem> list = new List<ParticleSystem>();
  8. list.Add(root);
  9. ParticleSystem.GetDirectParticleSystemChildrenRecursive(root.transform, list);
  10. return list.ToArray();
  11. }
[csharp] view plaincopy
  1. private static void GetDirectParticleSystemChildrenRecursive(Transform transform, List<ParticleSystem> particleSystems)
  2. {
  3. foreach (Transform transform2 in transform)
  4. {
  5. ParticleSystem component = transform2.gameObject.GetComponent<ParticleSystem>();
  6. if (component != null)
  7. {
  8. particleSystems.Add(component);
  9. ParticleSystem.GetDirectParticleSystemChildrenRecursive(transform2, particleSystems);
  10. }
  11. }
  12. }

U3D对获取所有下级gameObject实例上的粒子系统组件使用了递归的方式,并在递归结束后返回结果列表时做了一次列表元素复制(List.ToArray()),并且在获取粒子系统组件的时候用的是transform2.gameObject.GetComponent<ParticleSystem>(),而不是transform2.GetComponent<ParticleSystem>(),从上一篇文章里我们已经用实验证实了,前一种方式开销更大。看到这里,我们心里大概已经有谱了,那就是——效率绝对不会高到哪里去,影响性能的地方太多了……还是设计一个小实验来看看这种情况下应该用什么样的方式更好吧:

设计实验——一个两层结构,一个父gameObject挂载一个ParticleSystem组件,两个子gameObject分别挂载一个PariticleSystem组件,采用两种不同的方式对这个组合判断IsAlive各8×1024×1024次。
方案一,直接对父gameObject上的PariticleSystem调用IsAlive(true);
方案二,在循环前,先用GetComponentsInChildren将所有的PariticleSystem存入一个List,循环中对这个List做遍历,对List里每一个ParticleSystem调用IsAlive(false);
实验结果——方案一约3900ms,方案二约65ms。
结果对比很明显。其实,U3D提供的这个接口的意义在于,当不是需要进行那么频繁的调用时,可以用IsAlive(true)来省掉手动获取所有子粒子系统的过程,让代码简洁一些,虽然U3D目前对这个接口的实现有的地方还值得斟酌。ParticleSystem提供的这一族接口(IsAlive只是其中之一,此外还有Play,Pause,Stop等等),如果使用频率不是很高,比如仅仅是初始化或者销毁的时候做一次性调用,那么即便是withChildren参数是true也没有什么大不了的,还能少些很多代码,何乐而不为;但如果需要频繁调用,比如每帧都对粒子系统集合判断IsAlive,这种情况下,一定不能懒惰,该写的东西还是要写的。另外值得注意的一点,IsAlive这一族接口的无参形式,是默认withChildren为true的,使用的时候可别搞错了。
PS,留意一下GetDirectParticleSystemRecursive的实现方式,你会发现它有一个递归条件,就是节点上必须要有PariticleSystem组件,在递归过程中,一旦发现某个节点上没有ParticleSystem组件时,父子关系树上的这一枝就算遍历到头了,再往下即便是还有ParticleSystem存在也会被忽略。因此,如果你面对的ParticleSystem集合就恰好存在这样的断层,那最好还是自己勤快一点,自己动手用GetComonentsInChildren来查找所有的粒子系统组件。

转载于:https://blog.51cto.com/dingxiaowei/1366356

[Unity 3D] Unity 3D 性能优化(二)相关推荐

  1. Unity移动端游戏性能优化简谱之 常见游戏内存控制

    <Unity移动端游戏性能优化简谱>从Unity移动端游戏优化的一些基础讨论出发,例举和分析了近几年基于Unity开发的移动端游戏项目中最为常见的部分性能问题,并展示了如何使用UWA的性能 ...

  2. Unity移动端游戏性能优化简谱之 以引擎模块为划分的CPU耗时调优

    <Unity移动端游戏性能优化简谱>从Unity移动端游戏优化的一些基础讨论出发,例举和分析了近几年基于Unity开发的移动端游戏项目中最为常见的部分性能问题,并展示了如何使用UWA的性能 ...

  3. EMW 性能优化二之---并发配置

    http://www.cnblogs.com/byfhd/p/3723318.html EMW 性能优化二之---并发配置 在前一个日志中写到交货的异步更新,对于RFUI RF的前台操作会提升效率,异 ...

  4. apache php 调优_Apache的性能优化(二)

    具体模块定制: 编译和包含是两个不同的概念.编译是指这个模块被编译了,要想使用它,只用简单的修改httpd.conf加上LoadModule xxx_module libexec/mod_xxx.so ...

  5. 3D美术游戏性能优化

    以下内容转载摘编自unity中文课堂 优化 3D 美术资源时,我们将使用迭代过程指导你找出并消除性能问题.优化过程包含以下步骤: 性能分析,即使用性能分析器测试应用程序. 分析数据,查找瓶颈. 确定要 ...

  6. 【Unity】学习笔记 | 性能优化(一)—— 渲染

    Unity中,每一帧的渲染CPU和GPU都做了些什么 1. CPU检查场景中每个对象,判读他们是否应该被渲染.CPU收集即将被渲染的对象信息,并把这些信息分类为渲染指令(即draw calls) 2. ...

  7. Unity 文本颜色描边性能优化方案

    在这首先回答一个问题就是:为什么我们需要实现一个描边的方案?Unity没有吗? 答:Unity肯定有自己的代替方案,只是性能看起来并没那么优越.Unity 的方案是挂载一个 OutLine 组件. O ...

  8. android db加载后无法读取任何内容_android性能优化(二)之卡顿优化

    相对于其他类型的性能指标,卡顿是能直接让用户产生视觉反馈的现象,比如App反应滞后于用户的操作,在严重的情况下会出现ANR.关乎用户体验的大事,是很容易遭到用户吐槽的.因此,开发人员平时写代码时必须要 ...

  9. MySQL性能优化(二):优化数据库的设计

    一:数据库的设计 数据库命名:数据库名的命名一般和项目的名称保持一致,不要随意的起名字. 数据库编码: 采用utf8mb4而不使用utf8 MySQL 的"utf8"实际上不是真正 ...

  10. 性能优化二十三之Service进程防杀死

    前言 Service作为四大组件之一很多安卓开发者对他肯定是又爱又恨,爱在它可以帮助我们去处理常驻后台的任务操作,比如说推送服务,心跳传输等,恨在当Servcie遇到360.腾讯管家之类的杀毒软件,变 ...

最新文章

  1. Linux System and Performance Monitoring
  2. java buffer nio_Java NIO之Buffer(缓冲区)入门
  3. [js] 一道变态题 Number.call.call(Number, undefined, 0) 等于什么?
  4. 中国智慧VS西方智慧-看中国IT风云与IT产业怪状
  5. python爬虫爬取音乐单曲_Python爬取qq音乐的过程实例
  6. 传相互宝或于6月11日被关停 蚂蚁集团回应:假消息
  7. mysql有状态无状态_有状态和无状态的对象区别
  8. Android开发笔记(八十六)几个特殊的类
  9. 高通qusb bulk驱动_1999元!Redmi新机发布:首发高通全新SoC
  10. 微软BI SSIS 2012 辅助阅读博客
  11. DIY多快充协议太阳能充电器!----锂电池充电电路
  12. 为什么地球上只有一个硅谷?
  13. Matlab学习笔记:网格线的粗细调整
  14. 【VR】(四)VR设备盘点
  15. [DDC]Deep Domain Confusion: Maximizing for Domain Invariance
  16. 第十六届“振兴杯”计算机网络管理员赛项理论参考题库(1)单选
  17. Paper reading (二十二):Integrated omics: tools, advances and future approaches
  18. 开课通知 | 《AISHELL-3语音合成实战》课程
  19. 手机android app 无线控制led灯开关
  20. 用C语言设计一个简易的选择题答题系统

热门文章

  1. paip.gch预编译头不生效的原因以及解决:
  2. paip.android 手机输入法制造大法
  3. KKR创始人亨利·克拉维斯:像实业家那样思考和行动
  4. (转)芒格:投资成功不是频繁交易,而是好的决策和耐心
  5. 阿里巴巴的AI“发动机”
  6. 英特尔王庆连续四年担任OpenStack基金会个人独立董事
  7. 【语言去噪】基于matlab GUI IIR+FIR滤波器语音去噪【含Matlab源码 1027期】
  8. 【图像修复】基于matlab GUI空域滤波图像复原【含Matlab源码 849期】
  9. 【图像直线拟合】基于matlab最小二乘法图像直线拟合【含Matlab源码 100期】
  10. 深度学习分类pytorch_立即学习AI:02 —使用PyTorch进行分类问题简介