Unity 自定义"=="操作符 [翻译来源blogs.unity3d,2014/05]
主要内容来源
https://blogs.unity3d.com/cn/2014/05/16/custom-operator-should-we-keep-it/
在我们代码里,如果有这样的代码:
if (myGameObject == null)
那Unity底层做了什么? (事实上,除了GameObject,继承自UnityEngine.Object的类都是这样的)
在Unity的Editor运行时,特殊实现了这一类继承自UnityEngine.Object的 "==" 操作符
主要有两个原因:
1. 在Editor下,如果对一个Monobehaviour的字段赋值为null, Unity并不会真的把这个字段置为null,而是用一个 "fake null" 对象代替,并且在这个特殊对象里记录了一些信息 [备注1]
这样的好处是,当你尝试去访问这个字段时,并不是得到一个缺乏具体指示的NullReferenceException报错,而是一个具有提醒信息的空抛错: 例如: MissingReferenceException: The object of type 'XXX' has been destroyed but you are still trying to access it"
并且Unity会在Inspector界面上高亮发生这个错误的GameObject. 这样是为了让开发者的开发查错更加容易
2. 由于Unity是C/C++引擎,在我们用C#开发,去访问一个GameObject时[备注2],实际得到的是一个C#对象(wrapper object),而这个物体的实际信息,包括name, HideFlags, Components都是在C++ 的本地对象(native object)里.C# wrapper object存储了指向native object的指针.
这些native object(包括GameObject本身及其components)的生命周期都是托管(explicitly managed)的,在切场景或者调用Object.Destroy(myObject)时被销毁,而C# wrapper object是通过C# gc管理的
这就可能会出现.一个C# wrapper object仍然存在但是其对应的C++ object已经被销毁的情况. 当你去拿C# wrapper object判空时, 内部实现的"=="运算符会返回true,尽管在实际上C#对象是仍然存在的.
虽然基于上面两个原因,Unity引擎自定义了"=="运算符有其合理之处.但是这也导致了以下几个负面影响:
1. 这是有悖常理的(C# wrapper object仍然存在,拿其判空却为true)
2.拿两个UnityEngine.Objects对比或者和null对比的效率要低于我们的期待
3."=="运算符是不线程安全的,所以你不能在非主线程对比objects. (这一点Unity会去修复)
4.会导致??操作符表现不一致(It behaves inconsistently with the ?? operator,). 因为??操作符内部会做真正的C#对象的空检查,不会调用到Unity自定义的空检查函数
所以会导致 ?? 操作符和 == 操作符的结果矛盾
很多用户可能会没有意识到这个"=="的副作用.[备注3]
综合上面的积极和消极影响,考虑到已有项目的兼容和升级成本,Unity也在纠结是否拿掉这个自定义的"==".
备注
[1] 这种fake null 对象只会在Editor下使用,所以在你使用GetComponent查询一个不存在的Component时会看到一个C#内存分配,这是因为我们在内部创建Fake null Object时生成了一个自定义的警告String文本.这个内存分配不会出现在构建后的游戏中
这也是一个很好的例子证明: 你应该始终在实际运行的独立运行环境(standalone player)或者手机运行环境(mobile player)上要做性能分析,而不要在Editor下做Profile, 这是因为我们在Editor环境下做了大量的额外安全性检查,容错检查,资源使用检查等,牺牲了一些性能,这也是为了让你的开发变的轻松, 所以如果要分析内存分配的性能问题,永远不要在Editor下做Profiler,要始终在构建的游戏中进行Profiler
[2]这个规则不仅仅适用于GameObject,而且还适用于所有继承自UnityEngine.Object的类
[3]自己作为Unity的官方技术人员在做性能优化时都出现过忽视该空检查的副作用的情况
以至于目前为止,Unity还是没有去掉该自定义"=="
Unity 自定义"=="操作符 [翻译来源blogs.unity3d,2014/05]的更多相关文章
- (Unity)Unity自定义Debug日志文件,利用VS生成Dll文件并使用Dotfuscated进展混淆,避免被反编译
Unity自定义Debug日志文件,利用VS生成Dll文件并使用Dotfuscated进行混淆,避免被反编译. 1.打开VS,博主所用版本是Visual Studio 2013. 2.新建一个VC项目 ...
- RxJava(10-操作符原理&自定义操作符)
转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51791120 本文出自:[openXu的博客] 目录: 自定义创建操作符 数据序列操作符li ...
- Swift 4.0 高级-自定义操作符
在Swift语言中,常见的操作符有+.-.*./.>.<.==.&&.||等等,如果不喜欢,你也可以定义自己喜欢的操作符. 操作符类型 中置运算符(infix operat ...
- https://blog.newrelic.com/2014/05/02/25-php-developers-follow-online/
w https://blog.newrelic.com/2014/05/02/25-php-developers-follow-online/ 1. Rob Allen. Zend Framework ...
- new操作符(翻译自mozilla.org)
翻译自:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new new操作符可以实例化一个用户自 ...
- 【Unity Shaders】Reflecting Your World —— Unity3D中简单的Cubemap反射
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- Unity 自定义编辑窗体之ScriptableWizard
当我们在编辑界面要批量设置游戏资源的时候,就需要从UnityEditor里面继承,实现自己的窗口类. 所幸UNITY提供了最简单的一个自定义窗体类,我们直接往上扔public类型的属性就好,提供了确认 ...
- unity, 自定义类中使用print
在unity脚本中自定义c#类,而且不继承MonoBehaviour的话,若还想在其中使用print函数,可以用MonoBehaviour.print(...).
- Unity 自定义Inspector面板时的数据持久化问题
自定义Inspector面板的步骤: Unity内创建自定义的Inspector需要在Asset的任意文件夹下创建一个名字是Editor的文件夹,随后这个文件夹内的cs文件就会被放在vstu生成的Ed ...
随机推荐
- angular 中数据循环 *ngFor
<!--The content below is only a placeholder and can be replaced.--> <div style="text-a ...
- 重置密码解决MySQL for Linux
重置密码解决MySQL for Linux错误 ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using passwor ...
- 清空表且id为0
sql命令: 用于清空某表的数据 且让自增的id重新从0开始 truncate table
- Mac 高效 软件
彻底卸载软件: cleanmymac 软件转移: AppDelete,选择一个软件归档,换台电脑从归档安装 finder类chrme标签页: XtraFinder
- 【Leetcode_easy】606. Construct String from Binary Tree
problem 606. Construct String from Binary Tree 参考 1. Leetcode_easy_606. Construct String from Binary ...
- react 问题记录三
7.三元表达式 是否显示提交按钮(值运算用一对大括号包起来): {this.state.isTrue ? <FormItem style={{textAlign: 'right',marginT ...
- [CareerCup] Guards in a museum 博物馆的警卫
A museum was represented by a square matrix that was filled with O, G, and W where O represented ope ...
- 利用pandas读取Excel表格,用matplotlib.pyplot绘制直方图、折线图、饼图
利用pandas读取Excel表格,用matplotlib.pyplot绘制直方图.折线图.饼图 数据: 折线图代码: import pandas as pdimport matplotlib. ...
- python介绍,计算机组成。内存分布,进制,操作系统介绍
学习小方法 三个W一个Hwwwh:what(是什么) why(为什么) where(怎么用) how(如何用) 来思考知识点多练,多写,多敲代码增加熟练度与代码量 Python 是一门面向后台的编 ...
- CentOS系统下Tomcat的优化
一.JVM内存优化(线程优化) vim ./bin/catalina.sh 在catalina.sh文件中添加以下配置: JAVA_OPTS="-server -Xms128m -Xmx12 ...