Unity中直接使用transform和gameObject的效率测试

尽信书不如无书,更何况是网上开发者的博客。这里也包含我自己的博客,有的时候回过头来看是有错误的地方,但是我也懒得改了,而且很多时候我们看到的文章还不一定是原始地址,而是被各个网站七转八转的,更加不可能保证准确性。

这里测试了这么一个说法:“不要在脚本中直接使用transform或者gameObject,而应该在一开始缓存成成员变量如_transform和_gameObject来访问。因为前者每次执行的时候都要获取对应的组件,效率低。”

这种说法不能说完全是错误的,但是经过自己的测试明白其原理后,会对这个问题以及与其类似的问题都会有更加清晰的了解。

首先我们使用组件的时候尽量在一开始使用GetComponent缓存到成员变量里面,这个是完全合理的。但是tansform和gameObject如此常用的对象,Unity应该有更好的优化才对。否则就显得太低级了。我测试的结果也确实如此。如果不想看后面的分析,直接看结论就好了。

结论:Unity中直接访问transform效率会比缓存成成员变量慢一点点,这个只有量级非常大的时候才会体现出来。 Unity对transform和gameObject有足够的优化处理,不要自己再模拟Unity写属性来处理,多数情况效率更差。

请看下图:

测试代码是一个简单的transform坐标赋值,循环100w次。

其中Unity属性就是直接访问transform的时间消耗,而缓存的变量就是成员变量版本的。可以看到直接缓存成员变量确实会快一些,但是100w次执行,性能差别也就10%左右。个人感觉这点差别影响不大。是直接使用unity的属性,还是缓存成员变量看个人习惯了。

注意后面两个属性进行判断和属性直接获取变量。我们有可能会“自以为是”的这么写,如果_transform为空,则获取对应组件,否则直接返回成员变量。这种情况就是最慢的“属性进行判断”,这个时候属性会执行相对复杂的逻辑,速度慢就合情合理了。而如果属性直接返回成员变量,其效率是跟直接访问成员变量一致的。

测试代码如下:

using UnityEngine;
using System.Collections;

public class TestTransform : MonoBehaviour {
    private GameObject _go;
    private Transform _tr;

    protected Transform SimpleTr
    {
        get
        {
            return _tr;
        }
    }

    protected Transform Tr
    {
        get {
            if (_tr == null) {
                _tr = transform;
            }
            return _tr;
        }
    }

    protected GameObject SimpleGo
    {
        get
        {
            return _go;
        }
    }

    protected GameObject Go
    {
        get {
            if (_go == null) {
                _go = gameObject;
            }
            return _go;
        }
    }

	void Start ()
    {
        _go = gameObject;
        _tr = transform;

        DoTestTransform();

        DoTestGameObject();
    }

    public void DoTestTransform()
    {
        int count = 1000000;

        transform.position = Vector3.zero;
        int time = System.Environment.TickCount;
        for (int i = 0; i < count; ++i)
        {
            int index = i % 100;
            transform.position = Vector3.one * index;
        }
        Debug.Log("Unity属性: " + (System.Environment.TickCount - time) * 1000);

        _tr.position = Vector3.zero;
        int time2 = System.Environment.TickCount;
        for (int i = 0; i < count; ++i)
        {
            int index = i % 100;
            _tr.position = Vector3.one * index;
        }
        Debug.Log("缓存的变量: " + (System.Environment.TickCount - time2) * 1000);

        Tr.position = Vector3.zero;
        int time3 = System.Environment.TickCount;
        for (int i = 0; i < count; ++i)
        {
            int index = i % 100;
            Tr.position = Vector3.one * index;
        }
        Debug.Log("属性进行判断:" + (System.Environment.TickCount - time3) * 1000);

        SimpleTr.position = Vector3.zero;
        int time4 = System.Environment.TickCount;
        for (int i = 0; i < count; ++i)
        {
            int index = i % 100;
            SimpleTr.position = Vector3.one * index;
        }
        Debug.Log("属性直接获取变量: " + (System.Environment.TickCount - time4) * 1000);
    }

    public void DoTestGameObject()
    {
        int count = 1000000;

        gameObject.transform.position = Vector3.zero;
        int time = System.Environment.TickCount;
        for (int i = 0; i < count; ++i)
        {
            int index = i % 100;
            gameObject.transform.position = Vector3.one * index;
        }
        Debug.Log("Unity属性: " + (System.Environment.TickCount - time) * 1000);

        _go.transform.position = Vector3.zero;
        int time2 = System.Environment.TickCount;
        for (int i = 0; i < count; ++i)
        {
            int index = i % 100;
            _go.transform.position = Vector3.one * index;
        }
        Debug.Log("缓存的变量: " + (System.Environment.TickCount - time2) * 1000);

        Go.transform.position = Vector3.zero;
        int time3 = System.Environment.TickCount;
        for (int i = 0; i < count; ++i)
        {
            int index = i % 100;
            Go.transform.position = Vector3.one * index;
        }
        Debug.Log("属性进行判断:" + (System.Environment.TickCount - time3) * 1000);

        SimpleGo.transform.position = Vector3.zero;
        int time4 = System.Environment.TickCount;
        for (int i = 0; i < count; ++i)
        {
            int index = i % 100;
            SimpleGo.transform.position = Vector3.one * index;
        }
        Debug.Log("属性直接获取变量: " + (System.Environment.TickCount - time4) * 1000);
    }
}
时间: 2024-10-12 12:11:02

Unity中直接使用transform和gameObject的效率测试的相关文章

关于Unity中RectTransform和Transform

以前一直以为在Inspector面板上的是Transform,后来才发现原来是RectTransform 而我们平时用来联系节点之间的Transform其实是隐藏的组件,不在面板上显示,面板上显示的是位置坐标组件RectTransform,RectTransform是Transform的子类 可以这样强制转换,反过来则不行 RectTransform r_trans = (RectTransform)this.transform;

在Unity中使用事件/委托机制(event/delegate)进行GameObject之

欢迎来到unity学习.unity培训.unity企业培训教育专区,这里有很多U3D资源.U3D培训视频.U3D教程.U3D常见问题.U3D项目源码,[狗刨学习网]unity极致学院,致力于打造业内unity3d培训.学习第一品牌. 一对多的观察者模式机制有什么缺点? 如果你对如何在Unity中使用事件/委托机制还不太了解,建议您查看我的前一篇文章:[Unity3D技巧]在Unity中使用事件/委托机制(event/delegate)进行GameObject之间的通信 在前一篇博客里面,我们写到

【Unity3D技巧】在Unity中使用事件/委托机制(event/delegate)进行GameObject之间的通信

作者:王选易,出处:http://www.cnblogs.com/neverdie/ 欢迎转载,也请保留这段声明.如果你喜欢这篇文章,请点[推荐].谢谢! 引子 在前面两篇文章: [Unity3D基础教程]给初学者看的Unity教程(四):通过制作Flappy Bird了解Native 2D中的RigidBody2D和Collider2D [Unity3D基础教程]给初学者看的Unity教程(三):通过制作Flappy Bird了解Native 2D中的Sprite,Animation 我们了解

在Unity中定义统一的对象搜索接口

我们经常要在Unity中以各种方式搜索对象.比如按名字搜索.按tag.layer或者是查找名字为xxx开头的对象. 本文是介绍以一种统一的接口来搜索对象. 1.定义统一的搜索接口 /// <summary> /// 游戏对象搜索接口 /// </summary> public interface IGameObjectFinder { /// <summary> /// 搜索 /// </summary> /// <param name="r

菜鸟学习 - Unity中的热更新 - Lua和C#通信

孙广东 2015-4-6 热更新我是个菜鸟,感谢网上的各位的奉献,这次又当一回搬运工. 准备: 1.了解Lua的语法 推荐书籍<Lua程序设计 第二版> 2.使用ULua插件进行通信 尽量早上真机.因为Bug问题特别多. 大杂烩: 更新LUa其实也是更新资源. Lua被看作一个资源么.Lua代码都是运行时才编译的,不运行的时候就如同一张图片.一段音频一样,都是文件资源:所以更新逻辑只需要更新脚本,不需要再编译,因而Lua能轻松实现"热更新".运行效率由于使用反射,所以成为它

在Unity中使用贝塞尔曲线(转)

鼎鼎大名的贝塞尔曲线相信大家都耳熟能详.这两天因为工作的原因需要将贝塞尔曲线加在工程中,那么MOMO迅速的研究了一下成果就分享给大家了哦.贝塞尔曲线的原理是由两个点构成的任意角度的曲线,这两个点一个是起点,一个是终点.在这条曲线之上还会有两个可以任意移动的点来控制贝塞尔曲线的角度.如下图所示,点1 和点4 就是起点和终点,点2 和点3 就是控制曲线角度的两个动态点. 如下图所示.使用拖动条来让曲线发生旋转,大家会看的更加清晰.目前我们看到的被塞尔曲线是在平面中完成的,其实贝塞尔曲线是完全 支持3

Unity中场景解析成Json和XML并还原场景

其实关于这部分内容,雨松研究院已经写得很清楚了,也比较权威,链接在此:http://www.xuanyusong.com/archives/1919,但是现在还是想根据自己的思路整理一下 其实原理就是讲Hierarchy中所有的父物体(即transform.parent == null)都做成预设,然后记录下每个父物体的Transform里的属性,记录到Xml或者Json文件中,然后再解析文件,把其中的预设加载到新场景里,就会得到与原场景一模一样的场景了 首先在Project里新建一个Edito

Unity API 解析(3)&mdash;&mdash; GameObject 类

GameObject 类是Unity场景中所有实体的积累.一个GameObject对象通常由多个组件component组成,且至少含有一个transform组件.   activeSelf 属性 -- GameObject的Active标识 activeInHierarchy 属性的功能是返回GameObject实例在程序运行时的激活状态,它只有当GameObect实例的状态被激活时才会返回true.而且它会受父类对象激活状态的影响.如果其父类至最顶层的对象中有一个对象未被激活,activeIn

将Unity中的世界坐标转换成NGUI中的坐标

将Unity中的世界坐标转换成NGUI中的坐标,比如可用于自制血条等.代码如下: 1 using UnityEngine; 2 using System.Collections; 3 public class Healthbar : MonoBehaviour { 4 public GameObject TargetObject; //目标物体.这里是指Cube 5 public Camera worldcamera; //世界相机. 6 public Camera guiCamera; //U