C# 对象池应用

C# 对象池应用·

对象池是游戏编程中非常常用的优化策略以及设计模式。

游戏中,我们常常会遇到频繁地创建销毁大量相同对象的场景。频繁的创建对象会造成GC[1]压力,可能导致卡顿,进而影响游戏体验。

核心思想

将需要重复创建的对象先缓存下来,需要时激活,不需要时停用,从而避免频繁创建对象。

原理

当创建对象时,对象池将对象放入池管理的某种内存连续的数据结构中(数组或者栈等)。当不需要对象时,对象池并不销毁对象,而是将对象回收到池中,下次需要的时候再次从池中拿出来。
因为,对象储存在内存连续的数据结构中,所以解决了内存碎片的问题。
因为,对象每次用完以后就放回池中循环利用而不是再次创建和销毁,这样就解决了频繁的内存分配和销毁的问题。

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/// <summary>
/// 对象池本体
/// </summary>
public List<GameObject> pooledObjects;
/// <summary>
/// 对象池要管理的对象
/// </summary>
public GameObject objectToPool;
/// <summary>
/// 对象池中需要初始化对象的个数
/// </summary>
public int amountToPool;

void Start()
{
PoolStart(); // 初始化对象池
}

/// <summary>
/// 初始化对象池,克隆对象并将它们添加到列表中
/// </summary>
void PoolStart()
{
pooledObjects = new List<GameObject>();
for (int i = 0; i < amountToPool; i++)
{
GameObject obj = (GameObject)Instantiate(objectToPool);
obj.SetActive(false);
pooledObjects.Add(obj);
obj.transform.SetParent(this.transform); // 设置其父对象是 脚本所附加对象
}
}

GameObject GetPooledObject()
{
// For as many objects as are in the pooledObjects list
for (int i = 0; i < pooledObjects.Count; i++)
{
// if the pooled objects is NOT active, return that object
if (!pooledObjects[i].activeInHierarchy)
{
return pooledObjects[i];
}
}
// otherwise, return null
return null;
}

参考资料·

  1. 对象池_百度百科 (baidu.com)
  2. [游戏编程技巧]-对象池 - 知乎 (zhihu.com)
  3. 对象池(Object Pool) - 知乎 (zhihu.com)

  1. Garbage Collection,垃圾回收 ↩︎