笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。
CSDN视频网址:http://edu.csdn.net/lecturer/144
Unity引擎优化技术,无非涉及到三点:CPU优化,GPU优化,内存优化。
先谈谈内存优化:大概可以分成三大部分:
1、 Unity3D内部的内存
2、 Mono的托管内存
3、 引入的DLL或者第三方DLL所需要的内存。
其中Unity3D内部的内存包括如下:
- 资源:纹理、网格、音频等等
- GameObject和各种组件。
- 引擎内部逻辑需要的内存:渲染器,物理系统,粒子系统等等
我们接下来通过代码执行的时间方式给读者介绍一下关于组件的使用效率问题,代码如下所示:
using UnityEngine;
public class CachedMB : MonoBehaviour
{
Transform _transform;
public Transform transform
{
get { return _transform ?? (_transform = base.transform); }
}
//for testing
public Transform uncachedTransform
{
get { return base.transform; }
}
Rigidbody _rigidbody;
public Rigidbody rigidbody
{
get { return _rigidbody ?? (_rigidbody = base.GetComponent<Rigidbody>()); }
}
Camera _camera;
public Camera camera
{
get { return _camera ?? (_camera = base.GetComponent<Camera>()); }
}
Light _light;
public Light light
{
get { return _light ?? (_light = base.GetComponent<Light>()); }
}
private Animation _animation;
public Animation animation
{
get { return _animation ?? (_animation = base.GetComponent<Animation>()); }
}
private ConstantForce _constantForce;
public ConstantForce constantForce
{
get { return _constantForce ?? (_constantForce = base.GetComponent<ConstantForce>()); }
}
private Renderer _renderer;
public Renderer renderer
{
get { return _renderer ?? (_renderer = base.GetComponent<Renderer>()); }
}
private AudioSource _audio;
public AudioSource audio
{
get { return _audio ?? (_audio = base.GetComponent<AudioSource>()); }
}
private GUIText _guiText;
public GUIText guiText
{
get { return _guiText ?? (_guiText = base.GetComponent<GUIText>()); }
}
private GUITexture _guiTexture;
public GUITexture guiTexture
{
get { return _guiTexture ?? (_guiTexture = base.GetComponent<GUITexture>()); }
}
private NetworkView _networkView;
public NetworkView networkView
{
get { return _networkView ?? (_networkView = base.GetComponent<NetworkView>()); }
}
private Collider _collider;
public Collider collider
{
get { return _collider ?? (_collider = base.GetComponent<Collider>()); }
}
private HingeJoint _hingeJoint;
public HingeJoint hingeJoint
{
get { return _hingeJoint ?? (_hingeJoint = base.GetComponent<HingeJoint>()); }
}
private ParticleEmitter _particleEmitter;
public ParticleEmitter particleEmitter
{
get { return _particleEmitter ?? (_particleEmitter = base.GetComponent<ParticleEmitter>()); }
}
private ParticleSystem _particleSystem;
public ParticleSystem particleSystem
{
get { return _particleSystem ?? (_particleSystem = base.GetComponent<ParticleSystem>()); }
}
private GameObject _gameObject;
public GameObject gameObject
{
get { return _gameObject ?? (_gameObject = base.gameObject); }
}
private string _tag;
public string tag
{
get { return _tag ?? (_tag = base.tag); }
set { _tag = value; base.tag = value; }
}
private string _name;
public string name
{
get { return _name ?? (_name = base.name); }
set { _tag = value; base.tag = value; }
}
}
接下来开始写测试代码案例:
using UnityEngine;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Collections.Generic;
public class CacheTest : CachedMB
{
const int ITERATIONS = 1000000;
// Use this for initialization
Transform cached;
IEnumerator Start()
{
cached = uncachedTransform;
for (; ; )
{
yield return null;
if (!Input.GetKeyDown(KeyCode.T)) continue;
var sw1 = Stopwatch.StartNew();
{
Transform trans1;
for (int i = 0; i < ITERATIONS; i++)
trans1 = GetComponent<Transform>();
} sw1.Stop();
var sw2 = Stopwatch.StartNew();
{
Transform trans2;
for (int i = 0; i < ITERATIONS; i++)
trans2 = transform;
} sw2.Stop();
var sw3 = Stopwatch.StartNew();
{
Transform trans3;
for (int i = 0; i < ITERATIONS; i++)
trans3 = cached;
} sw3.Stop();
var sw4 = Stopwatch.StartNew();
{
Transform trans4;
for (int i = 0; i < ITERATIONS; i++)
trans4 = uncachedTransform;
} sw4.Stop();
UnityEngine.Debug.LogWarning(ITERATIONS + " iterations");
UnityEngine.Debug.LogWarning("GetComponent " + sw1.ElapsedMilliseconds + "ms");
UnityEngine.Debug.LogWarning("MonoBehaviour " + sw4.ElapsedMilliseconds + "ms");
UnityEngine.Debug.LogWarning("CachedMB " + sw2.ElapsedMilliseconds + "ms");
UnityEngine.Debug.LogWarning("Manual Cache " + sw3.ElapsedMilliseconds + "ms");
}
}
}
执行结果如下所示:
通过显示的结果,我们知道,GetComponent是比较耗费时间的,在游戏开发中尤其是在每帧调用中少用。Manual Cache是耗费时间最少的,应该在游戏开发中尽量多用。