有时候会发现 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. 利用Keepalived+mysql构建高可用MySQL双主自动切转

    转载:http://www.it300.com/index.php/article-15266.html 关于MySQL-HA,目前有多种解决方案,比如heartbeat.drbd.mmm.共享存储, ...

  2. Oracle OEM重建

    参考博客:http://blog.csdn.net/tianlesoftware/article/details/4702978 测试环境: C:\Users\Administrator>sql ...

  3. php的post和get方法

    <?php function post($url,$fields) { $fields_string = ''; foreach($fields as $key=>$value) { $f ...

  4. 学无止境,学习AJAX(一)

    什么是AJAX?异步JavaScript和XML. AJAX是一种用于创建快速动态网页的技术. 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个网页的 ...

  5. ISNULL

    ISNULL 使用指定的替换值替换 NULL. 语法ISNULL ( check_expression , replacement_value ) 参数check_expression 将被检查是否为 ...

  6. 《JavaScript启示录》摘抄

    1.JavaScript预包装的9个原生的对象构造函数: Number(),String(),Boolean(),Object(),Array(),Function(),Data(),RegExp() ...

  7. JSON漫谈

    JSON: JavaScript Object Notation(JavaScript 对象表示法),JSON 是存储和交换文本信息的语法.类似 XML.JSON 比 XML 更小.更快,更易解析. ...

  8. 最近在折腾VPS(持续完善)

    买的某国内vps. 本机环境 Win7-x64 使用官方英文版的putty,用于远程登录linux主机.WinSCP图形界面管理文件. VPS CentOS 6.2 安装 安全狗(safedog.cn ...

  9. ZOJ 3705 Applications

    点我看题目 题意 : 真是一道又臭又长的模拟题啊,不过比赛的时候没看,赛完了补的. 给你N个候选人,让你从中选M个候选人,根据四个大规则来确定每个人的分数,然后选分数前M个人的输出. 1.在MOJ上做 ...

  10. easyui源码翻译1.32--Pagination(分页)

    前言 使用$.fn.pagination.defaults重写默认值对象下载该插件翻译源码 该分页控件允许用户导航页面的数据.它支持页面导航和页面长度选择的选项设置.用户可以在分页控件上添加自定义按钮 ...