获取组件的三种方式
在Unity中获取物体上的组件有三种方式
– public Component GetComponent (string type);
– public Component GetComponent (Type type);
– public T GetComponent ();
目前我们用的最多的是第三种,通过泛型获取组件。既然有三种方式可以获取组件,那么在正常的开发过程中应该使用哪种方式获取组件效率最高,接下来就测试一下三种方式分别执行一百万次,比较一下他们的效率差别。为了使结果相对客观和准确,我们分别获取Unity中自带的组件和我们自己写的组件,分别对比其效率
准备工作
为了方便测试,下面贴一个进行了简单封装的获取执行时间的类代码
using System;
using System.Diagnostics;
public class CustomTimer : IDisposable
{
private Stopwatch watch = null;
private string label = null;
public CustomTimer(string label)
{
this.label = label;
watch = Stopwatch.StartNew();
}
public void Dispose()
{
long time = watch.ElapsedMilliseconds;
watch.Stop();
watch = null;
UnityEngine.Debug.LogFormat("{0}测试耗时<color=#ff0000>{1}</color>ms", label, time);
}
}
测试Unity自带组件获取
这里我们直接将脚本挂在摄像机上,获取摄像机上的AudioListener组件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript1 : MonoBehaviour
{
private const int COUNT = 1000000; // 执行次数
private AudioListener component; // 存储获取的组件
private void Start()
{
Test1();
Test2();
Test3();
}
/// <summary>
/// String方式
/// </summary>
private void Test1()
{
using (new CustomTimer("string方式"))
{
for (int i = 0; i < COUNT; i++)
{
component = GetComponent("AudioListener") as AudioListener;
}
}
}
/// <summary>
/// typeof方式
/// </summary>
private void Test2()
{
using (new CustomTimer("typeof方式"))
{
for (int i = 0; i < COUNT; i++)
{
component = GetComponent(typeof(AudioListener)) as AudioListener;
}
}
}
/// <summary>
/// 泛型方式
/// </summary>
private void Test3()
{
using (new CustomTimer("generics方式"))
{
for (int i = 0; i < COUNT; i++)
{
component = GetComponent<AudioListener>();
}
}
}
}
点击运行,输出的如下结果
对比结果,发现使用泛型的方式耗时最少,一百万次耗时58毫秒,string方式和typeof方式相差不大,都在120毫秒左右。由此得出获取自带组件使用泛型的方式是效率是最高的,字符串次之,typeof的方式效率最差。
那么结果真的如此吗?如果是我们自己写的组件,得出的结果是否也和上面的一样呢?接下来验证一下获取自定义组件
测试自定义组件获取
测试总体过程还是和上面的一样,不同的是这次我们需要在摄像机上挂在一个我们自己写的组件,下面我们就自己建一个TestComponent的组件(就是创建一个TestComponent脚本,保存默认即可)如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestComponent : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
接下来将上面的测试脚本获取的AudioListener组件都改为TestComponent
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript1 : MonoBehaviour
{
private const int COUNT = 1000000; // 执行次数
private TestComponent component; // 存储获取的组件
private void Start()
{
Test1();
Test2();
Test3();
}
/// <summary>
/// String方式
/// </summary>
private void Test1()
{
using (new CustomTimer("string方式"))
{
for (int i = 0; i < COUNT; i++)
{
component = GetComponent("TestComponent") as TestComponent;
}
}
}
/// <summary>
/// typeof方式
/// </summary>
private void Test2()
{
using (new CustomTimer("typeof方式"))
{
for (int i = 0; i < COUNT; i++)
{
component = GetComponent(typeof(TestComponent)) as TestComponent;
}
}
}
/// <summary>
/// 泛型方式
/// </summary>
private void Test3()
{
using (new CustomTimer("generics方式"))
{
for (int i = 0; i < COUNT; i++)
{
component = GetComponent<TestComponent>();
}
}
}
}
运行,输入结果如下:
这次发现,字符串方式的耗时惊人,和另外两个不在一个数量级上,泛型的方式依旧是耗时最短的
结论
- 在开发过程中推荐使用泛型方式获取组件
- 获取自定义组件效率比获取自带组件效率低
- 应当避免在工程中使用字符串方式获取组件,除非不用考虑效率问题(例如编辑器功能开发)