UPL5-7——GameObject 优化建议
UPL5-7——GameObject 优化建议
更快的空引用检测
我们在进行开发时,经常会进行 GameObject 对象判空处理,常常会使用类似这样的判空处理
1 | if (gameObject != null) |
其实不仅是 GameObject,MonoBehaviour 等等 Unity 自带的内容如果这样进行判空处理,都是最简单的方式,但是这种方式并不是效率最高的
这里推荐一种更快的判空处理方式,利用 System.Object 中的引用判断方法 ReferenceEquals
1 | if (!System.Object.ReferenceEquals(gameObject, null)) |
虽然它的写法有些复杂,但是但从性能上考虑,它的消耗更低,执行的更快,直接进行了引用地址的比较
这是因为通过 == / != 对 null 的判断,还是会进行桥接访问的方式,会有额外的桥接开销
而 System.Object 中的 ReferenceEquals 方法,并不会进行桥接访问,只做引用对比
但是,使用时需要注意陷阱,即如果销毁了
GameObject 对象,但是并没有对 GameObject 对象进行置空,那么通过两种判断方式,获取的结果是不同的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 public GameObject obj; // 在外部关联一个GameObject
private void Start()
{
DestroyImmediate(obj);
if (obj != null)
{
Debug.Log("!= null 对象不为空");
}
if (!ReferenceEquals(obj, null))
{
Debug.Log("ReferenceEquals(obj, null) 引用不为空");
}
}
避免检索字符串属性
我们应该尽量避免使用 GameObject 中的字符串属性直接进行判断,比如 tag、layer、name 等,因为会产生桥接
如果需要每帧使用这些属性进行逻辑处理,建议先缓存他们,或者用相关 API 替代
例如,针对 tag 的比较,可以将 gameObject.tag == "TagName" 改为 gameObject.CompareTag("123")
减少 Find 相关方法的使用
GameObject 中提供了很多 Find 相关方法
比如:
-
GameObject.Find(string name) -
GameObject.FindWithTag(string tag)
等等
我们应该减少这些方法的使用,因为他们的底层会进行遍历和字符串比较,性能表现非常差,由于是通过字符串查找,容错性也较差
我们应该通过以下方式来优化
- 初始化时找到对象并缓存
- 直接拖拽引用进行关联
- 对于需要全局使用的对象,可以通过单例模式的方式进行对象管理
等等
减少 SendMessage 相关方法的使用
Unity 中提供 SendMessage、BroadcastMessage()、SendMessageUpwards() 相关方法,用于基于字符串反射式的进行消息传递,通知其他组件执行某些逻辑
这些方法内部,会遍历 GameObject 上所有组件,对每个组件进行反射式调用判断,并且每次都需要重新查找,匹配字符串,效率非常低下
它们是 低性能、高开销、不可控的“黑箱通信”,应尽量避免使用
我们可以通过以下方式进行优化
- 缓存对应组件,直接调用对应组件中的方法
- 利用基于观察者设计模式的事件中心,实现低耦合跨脚本跨对象的逻辑调用
等等

