Skip to main content

Unity中使用List

List<T>是Unity开发中最常用的数据结构之一,它提供了动态数组的功能,可以高效地存储和管理游戏对象、组件或自定义数据。面试中偶尔也会考察Unity 中如何高效使用 List<T>。

以下内容提供参考。

管理游戏对象

public class EnemyManager : MonoBehaviour {
private List<GameObject> activeEnemies = new List<GameObject>();

public void SpawnEnemy(GameObject prefab) {
GameObject enemy = Instantiate(prefab);
activeEnemies.Add(enemy);
}

public void CleanDeadEnemies() {
activeEnemies.RemoveAll(e => e == null || !e.activeSelf);
}
}

存储组件引用

List<Renderer> allRenderers = new List<Renderer>();
void Start() {
GetComponentsInChildren(allRenderers);
allRenderers.ForEach(r => r.enabled = false);
}

与协程配合使用

IEnumerator ProcessEnemies() {
foreach(GameObject enemy in enemyList) {
enemy.GetComponent<AI>().Process();
yield return new WaitForSeconds(0.1f);
}
}

预分配容量

// 预先分配足够容量
List<Vector3> pathPoints = new List<Vector3>(1000);

这可以避免频繁扩容带来的性能损耗。

使用对象池

对于频繁创建销毁的对象,使用对象池替代List的直接管理:

public class GameObjectPool {
private Stack<GameObject> pool = new Stack<GameObject>();
private GameObject prefab;

public GameObject Get() {
return pool.Count > ? pool.Pop() : Instantiate(prefab);
}

public void Release(GameObject obj) {
obj.SetActive(false);
pool.Push(obj);
}
}

避免装箱拆箱

使用泛型List而非ArrayList等非泛型集合:

// 推荐
List<int> scores = new List<int>();

// 不推荐(会导致装箱拆箱)
ArrayList scores = new ArrayList();

批量操作优先

// 批量添加
enemyList.AddRange(newEnemies);

// 批量删除
enemyList.RemoveAll(e => e == null);

批量操作比单个操作更高效。

多线程访问

List<T>不是线程安全的,多线程环境下需要使用锁或并发集合:

private List<GameObject> enemyList = new List<GameObject>();
private readonly object listLock = new object();

void AddEnemy(GameObject enemy) {
lock(listLock) {
enemyList.Add(enemy);
}
}

序列化问题

Unity默认不序列化泛型集合,需要特殊处理

[System.Serializable]
public class EnemyWrapper {
public List<GameObject> enemies;
}

// 在MonoBehaviour中
public EnemyWrapper enemyWrapper;

UI列表优化

对于长列表(如排行榜),使用循环复用技术而非直接创建所有元素:

// 使用ScrollView循环复用组件
public class RecyclableScrollView : MonoBehaviour {
[SerializeField] private RectTransform content;
[SerializeField] private GameObject itemPrefab;
[SerializeField] private float itemHeight;

private List<ItemData> dataList;
private List<GameObject> activeItems = new List<GameObject>();

public void Initialize(List<ItemData> data) {
dataList = data;
content.sizeDelta = new Vector2(content.sizeDelta.x, data.Count * itemHeight);
UpdateVisibleItems();
}

private void UpdateVisibleItems() {
// 根据滚动位置更新可见项
}
}