GameObject和MonoBehaviour是特殊对象,它们在内存中有2种表示:一个表示存在于管理C#代码的相同系统管理的内存中,C#代码是用户编写的(托管代码);另一个表示存在于另一个单独处理的内存空间中(本机代码)。数据可以在两个内存空间之间移动,但是每次移动都会导致额外的CPU开销和可能的额外内存分配。这种现象称为“跨越本机-托管的桥接”。如果发生这种情况,就可能会为对象的数据生成额外的内存分配,以便跨桥复制,这需要垃圾收集器最终执行一些内存自动清理操作。这里以GameObject对象空引用检查和字符串属性做讲解
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
* Author:W
* 关于游戏对象的性能优化
* 1.关于GameObject游戏对象的Null引用检查
* 2.尽量避免从GameObject游戏对象取出字符串属性如tag或name
*/
public class GameObjectTest : MonoBehaviour {
// Use this for initialization
void Start () {
}
/// <summary>
/// 针对GameObject MonoBehaviour等Unity对象的空引用检查
/// </summary>
private void Test()
{
//方式1:空检查处理,但会引起本机-托管的桥接复制现象,会导致额外的CPU开销和可能的额外内存分配
if (gameObject != null)
{
}
//方式2:空检查处理,其速度大约是上面的2倍
if (!System.Object.ReferenceEquals(gameObject, null))
{
}
}
private int numTest = 1000000;
// Update is called once per frame
void Update () {
if (Input.GetKeyDown(KeyCode.A))
{
for (int i = 0; i < numTest; i++)
{
//取出游戏对象的tag字符串属性会产生本地-托管桥接复制。【name属性也是如此】会触发GC垃圾回收机制
if (gameObject.tag == "Player")
{
}
}
}
if (Input.GetKeyDown(KeyCode.B))
{
for (int i = 0; i < numTest; i++)
{
//比较tag属性,它可以完全避免本地-托管的桥接复制,可以节省开销成本
if (gameObject.CompareTag("Player"))
{
}
}
}
}
}
关于tag字符串属性和comparetag API 性能面板截图如下