Unity的GC机制,使用了Boehm GC算法Boehm,是非分代(non-generational)和非压缩(non-compacting)的。"非分代"是指GC执行清理操作时,必须遍历整个内存,并且随着内存的增长,它的性能就会降低。“非压缩”意味着内存中的对象不会被重新定位,去缩小对象之间的内存空隙。注意啦,这点和传统c#的GC机制不同。
//bad code
private List<GameObject> objectsList;
void Update()
{
objectsList = new List<GameObject>();
objectsList.Add(......)
}
//better code
private List<GameObject> objectsList;
void Start()
{
objectsList = new List<GameObject>();
}
void Update()
{
objectsList.Clear();
objectsList.Add(......)
}
//bad code
void Update()
{
var levelObstacles = FindObjectsOfType<Obstacle>();
foreach(var obstacle in levelObstacles)
{ ....... }
}
//better code
private Object[] levelObstacles;
void Start()
{
levelObstacles = FindObjectsOfType<Obstacle>();
}
void Update()
{
foreach(var obstacle in levelObstacles)
{ ....... }
}
//bad code
void Start()
{
text = GetComponent<Text>();
}
void Update()
{
text.text = "Player " + name + " has score " + score.toString();
}
//better code
void Start()
{
text = GetComponent<Text>();
builder = new StringBuilder(50);
}
void Update()
{
//StringBuilder为所有类型重载了Append方法
builder.Length = 0;
builder.Append("Player ");
builder.Append(name);
builder.Append(" has score ");
builder.Append(score);
text.text = builder.ToString();
}
//bad code
void Update()
{
//分配包含所有touches的新数组
Input.touches[0];
}
//better code
void Update()
{
Input.GetTouch(0);
}
// bad code
void Update()
{
//返回新的字符串(垃圾),然后对比2个字符串
gameObject.Tag == "MyTag";
}
// better code
void Update()
{
gameObject.CompareTag("MyTag");
}
// bad code
Physics2D.CircleCast();
// better code
Physics2D.CircleCastNonAlloc();
public class ObjectPool<T> where T : new()
{
private Stack<T> objs;
public ObjectPool(){
objs = new Stack<T>();
}
// 获取对象池里的对象
public T GetObject(){
T obj = objs.Count > 0 ? objs.Pop() : new T();
return obj;
}
// 回收对象池里的对象
public void ReturnObject(T obj){
if (obj != null)
objs.Push(obj);
}
}
// bad code
Dicitonary<enum,Transform> _dic; // enum作为key, add时会进行boxing
// better code
Dictionary<int, Transform> _dic;
}
//bad code
Dictionary<int, object> _dic;
void Update()
{
foreach(var value in _dic.values)
{
...
}
}
// better code
object[] _arr; //容器改为内置数组
bool _isUpdate //添加判定条件,减少遍历次数
void Update()
{
if(_isUpdate)
{
foreach(var value in _arr)
{
...
}
}
}
// bad code
void Update()
{
gameObject.GetComponent<LineRenderer>();
gameObject.GetComponent<CircleCollider2D>();
//Examples of calculations returning same result every frame
Mathf.FloorToInt(Screen.width / 2);
var width = 2f * mainCamera.orthographicSize * mainCamera.aspect;
var castRadius = circleCollider.radius * transform.lossyScale.x;
var halfSize = GetComponent<SpriteRenderer>().bounds.size.x / 2f;
//Finding objects
var levelObstacles = FindObjectsOfType<Obstacle>();
var levelCollectibles = FindGameObjectsWithTag("COLLECTIBLE");
//References
objectTransform = gameObject.transform;
mainCamera = Camera.main;
}
// better code
void Start()
{
gameObject.GetComponent<LineRenderer>();
gameObject.GetComponent<CircleCollider2D>();
//Examples of calculations returning same result every frame
Mathf.FloorToInt(Screen.width / 2);
var width = 2f * mainCamera.orthographicSize * mainCamera.aspect;
var castRadius = circleCollider.radius * transform.lossyScale.x;
var halfSize = GetComponent<SpriteRenderer>().bounds.size.x / 2f;
//Finding objects
var levelObstacles = FindObjectsOfType<Obstacle>();
var levelCollectibles = FindGameObjectsWithTag("COLLECTIBLE");
//References
objectTransform = gameObject.transform;
mainCamera = Camera.main;
}
// bad code
Text text;
GameState gameState;
void Start()
{
gameState = StoreProvider.Get<GameState>();
text = GetComponent<Text>();
}
void Update()
{
text.text = gameState.CollectedCollectibles.ToString();
}
// better code
Text text;
GameState gameState;
int collectiblesCount;
void Start()
{
gameState = StoreProvider.Get<GameState>();
text = GetComponent<Text>();
collectiblesCount = gameState.CollectedCollectibles;
}
void Update()
{
if(collectiblesCount != gameState.CollectedCollectibles) {
//This code is ran only about 5 times each level
collectiblesCount = gameState.CollectedCollectibles;
text.text = collectiblesCount.ToString();
}
}
// bad code
foreach (GameObject obstacle in obstacles)
// better code
var count = obstacles.Count;
for (int i = 0; i < count; i++)
{
obstacles[i];
}
// bad code
List<string> list = new List<string>(100);
// better code
string[] arr = new string[100];
Vector3 pos1 = new Vector3(1,2,3);
Vector3 pos2 = new Vector3(4,5,6);
//Bad code
var pos3 = pos1 + pos2;
//Better code
var pos3 = new Vector3(pos1.x + pos2.x, pos1.y + pos2.y, ......);
Vector3 pos1 = new Vector3(1,2,3);
//Bad code
var pos2 = pos1 * 2f;
//Better code
var pos2 = new Vector3(pos1.x * 2f, pos1.y * 2f, ......);
// Bad Code
GameObject player;
void Start()
{
player = GameObject.Find("PLAYER");
}
// Better Code
//在场景编辑器中序列化
[SerializeField]
GameObject player;
void Start()
{
}
//Bad Code
void DetectCollision()
{
var count = Physics2D.CircleCastNonAlloc(
position, radius, direction, results, distance);
for (int i = 0; i < count; i++) {
var obj = results[i].collider.transform.gameObject;
if(obj.CompareTag("FOO")) {
ProcessCollision(results[i]);
}
}
}
//Better Code
void DetectCollision()
{
//设置检测layer
var mask = 1 << 8;
var count = Physics2D.CircleCastNonAlloc(
position, radius, direction, results, distance, mask);
for (int i = 0; i < count; i++) {
ProcessCollision(results[i]);
}
}
//Bad Code
gameObject.Tag == "MyTag";
//Better Code
gameObject.CompareTag("MyTag");
//Bad code
void Update()
{
Camera.main.orthographicSize //Some operation with camera
}
//Better Code
private Camera cam;
void Start()
{
cam = Camera.main;
}
void Update()
{
cam.orthographicSize //Some operation with camera
}
[How We Optimised Our Scripts in Unity]https://medium.com/lonely-vertex-development/how-we-optimised-our-scripts-in-unity-447924863b3a
[BestPracticeUnderstandingPerformanceInUnity]https://docs.unity3d.com/Manual/BestPracticeUnderstandingPerformanceInUnity8.html
[UnityPerformanceTest]https://github.com/fchsg/UnityPerformanceTest.git