有时候会发现 Unity UI 非常耗时,在 Profiler 中可以轻易的看到 UI 中 的 GraphicRaycaster.Raycast 单帧调用可以成百上千,甚至好几千,帧速率前不忍赌,一关掉 UI 立马满血复活。
     这种情况大多出现在一是 Canvas 比较多而且子节点添加 GraphicRaycaster  组件也比较多的情况;二是每个 Canvas 下面有很多个 UI 面板,而每次其实显示的只有那么几个,不用的隐藏 SetActive(false),使用的激活显示 SetActive(true)。
     第一种情况就只能自己根据需求进行简化,不要滥用了 Canvas,优化和精简自己的设计;第二种情况看起来貌似没什么问题,实际上正是帧速率大大下降的元凶。
     说第二种没问题主要是符合 Unity 的使用基本原则,而且大家容易想到的使用方式,那为什么有问题,那要先看看一点相关 UI 的工作模式。每个 Graphic 组件(包括所有继承自 Graphic 的组件)都必须要通过 GraphicRegistry.RegisterGraphicForCanvas 注册到 GraphicRegistry 中,Graphic 中能够引起注册的事件有:OnTransformParentChanged(),OnEnable(),OnCanvasHierarchyChanged();OnEnable() 这个不必说就是组件激活时的回调,其它两个 OnTransformParentChanged(), OnCanvasHierarchyChanged() 理论上应该只在控件可用 Enable 和 Active 的时候才会被调用,或者说才应该产生 GraphicRegistry.RegisterGraphicForCanvas 的注册过程,而现在的代码是只有 OnTransformParentChanged() 在 GraphicRegistry.RegisterGraphicForCanvas 之前检测了 IsActive(),而 OnCanvasHierarchyChanged() 却未做任何检测,即使挂接了 Graphic 的对象在 Unity 的 Inspector 中处于非激活状态,启动游戏后 OnCanvasHierarchyChanged() 依然会被调用,导致该 Graphic 被注册进 GraphicRegistry,并且最终参与了 GraphicRaycaster.Raycast,造成了 CPU 周期的浪费。
     总而言之,这应该是 Unity UI 系统的一个 bug,本来从 BitBucket 上 Fork 了想修改下提交,但是发现无法 clone,很是奇怪,暂时搁置了,既然暂时无法修改源码,官方也没有修改,那么暂时的解决方案就是在启动后,手动清理每个 Canvas 下在 GraphicRegistry 中注册的 Graphic,将所有 IsActive() 为 false 的组件通过 GraphicRegistry.UnregisterGraphicForCanvas 从 GraphicRegistry 中移除即可,达到曲线救国的目的。
 

关于 Unity UI 中 GraphicRaycaster.Raycast 数量巨大的问题的更多相关文章

  1. unity ui中使用onmouseover

    unity ui中鼠标移进或者移出的触发方式与2d.3d的不同,2d.3d物体使用的是onmouseover,ui使用的是OnPointerEnter.需要实现以下两个接口. public class ...

  2. Unity UI性能优化技巧

    本文将介绍一些提升Unity UI性能的技巧.更多优化技巧,可以观看Unity工程师Ian Dundore在Unite Europe 2017的演讲<使用Unity性能提升技巧>. 1.划 ...

  3. Unity优化方向——优化Unity游戏中的图形渲染(译)

    CPU bound:CPU性能边界,是指CPU计算时一直处于占用率很高的情况. GPU bound:GPU性能边界,同样的是指GPU计算时一直处于占用率很高的情况. 原文:https://unity3 ...

  4. i3D的一篇Unity教程中的笔记

    原地址:http://blog.sina.com.cn/s/blog_72b936d80100wwej.html 以下是i3D的一篇Unity教程中的笔记. i3D的这篇教程是[i3D.Next-Ge ...

  5. [译]如何在Unity编辑器中添加你自己的工具

    在这篇教程中你会学习如何扩展你的Unity3D编辑器,以便在你的项目中更好的使用它.你将会学习如何绘制你自己的gizmo,用代码来实现创建和删除物体,创建编辑器窗口,使用组件,并且允许用户撤销他们所作 ...

  6. 关于Unity项目中创建项目遇到的一些问题

    1.Unity调用Android的方法默认不是在UI线程执行,所以在Android上写一些页面的重绘的方法,让Unity去调用时,注意要在Android中添加对应的runOnUiThread才可以: ...

  7. Unity UI 基础【译】

    https://unity3d.com/cn/learn/tutorials/topics/best-practices/fundamentals-unity-ui?playlist=30089 理解 ...

  8. Unity 3D中不得不说的yield协程与消息传递

    1. 协程 在Unity 3D中,我们刚开始写脚本的时候肯定会遇到类似下面这样的需求:每隔3秒发射一个烟花.怪物死亡后20秒再复活之类的.刚开始的时候喜欢把这些东西都塞到Update里面去,就像下面这 ...

  9. Unity UI相关总结

    UIGrid 加载面板时,如果面板中含有大容量的 UIGrid,可能会很卡.我们可以只加载 UIGrid 的前 n 个单元格对象,在显示面板之后,利用协程加载剩余的所有单元格,每帧加载 m 个. 同样 ...

随机推荐

  1. javascript操作html元素CSS属性

    下面先记录一下JS控制CSS所使用的方法. 1.使用javascript更改某个css class的属性... <style type="text/css"> .ori ...

  2. RSA使用 常识

    1公钥加密,私钥解密  OK反过来, 私钥加密,公钥解密 也OK 2 使用RSA加密 对称算法的key ,用对称算法加密 消息.伙伴收到消息后,RSA解密出 对称算法的key,再用这个key去解密消息 ...

  3. 一次Oracle数据迁移

    目标数据库:Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 源数据库  : Oracle Database 11g Enterpri ...

  4. Boost format

    浅尝boost之format 概述      std::string是个很不错的东东,但实际使用时基本在每个程序里都会遇到不愉快的事情:格式化字符串.我甚至由于这个原因在代码里引入平台有关的MFC,A ...

  5. 今年的IT大趋势是虚拟现实

    从今年下半年开始,陆陆续续出现了一些基于虚拟现实技术的创业公司,先是从IT新闻中的一篇创业故事中了解到这个方向,后来再是身边一个以前的朋友也发布了类似的产品. 从他们的产品来看,基本都是围绕教育行业开 ...

  6. JLink软件升级到4.92之后,Jlink不能用了

    JLink软件升级到4.92之后,Jlink不能用了                                                       情景描述: Jlink软件升级到4.9 ...

  7. SDC(1)–Hold Time

    从以下两个论点触发可能会使Hold Time的计算理解起来更加容易: (1) H = SU – 1 ; (2) Hold Check的目的是确保Source Clock在某个边沿打出数据时,该数据不会 ...

  8. Swagger+AutoRest

    Swagger+AutoRest 生成web api客户端(.Net)   简介 对于.net来说,用web api来构建服务是一个不错的选择,都是http请求,调用简单,但是如果真的要在程序中调用, ...

  9. SendKeys总结

    1.SendKeys中特殊字符的键代码BACKSPACE {BACKSPACE}.{BS} 或 {BKSP} BREAK {BREAK} CAPS LOCK {CAPSLOCK} DEL 或 DELE ...

  10. SQL 返回数量一定的行

    1. 限制返回的行 select top 10 * from tablename 2. 返回随机n行 select top n * from tablename order by newid()