老蒋的知识库

  • 首页
  • 文章归档
  • 关于页面

  • 搜索

Unity 对象池优化性能

发表于 2023-10-15 | 分类于 C# | 0 | 阅读次数 53

通过对象池减少对象的创建优化性能:空间换时间

常用切重复的对象可以通过对象池管理进行复用,减少重复创建。
例:同一个技能释放每次使用的都是预制体,只是技能伤害可能有所变化。技能每次释放结束通过gameObject.SetActive(false)隐藏对象,再次释放同一技能修改其伤害数值并gameObject.SetActive(true)展示对象。就可以避免大量的重复技能创建节约CPU运算性能。

示例代码

对象池代码

using System.Collections.Generic;
using UnityEngine;

public class GameObjectPool
{
    public GameObject gameObjectPool;

    private Dictionary<string, Queue<GameObject>> _pool;

    public GameObjectPool(string name)
    {
        _pool = new Dictionary<string, Queue<GameObject>>();
        gameObjectPool = new GameObject(name);
    }

    // 获取对象,通过预制体资源地址,分别获取、存储不同的队列中。
    public GameObject GetGameObject(string key)
    {
        if (!_pool.ContainsKey(key))
        {
            return null;
        }

        if (_pool[key].Count > 0)
        {
            return _pool[key].Dequeue();
        }
        else
        {
            return null;
        }
    }

    // 回收对象
    public void RecoveryGameObject(string key, GameObject gameObject)
    {

        if (!_pool.ContainsKey(key))
        {
            _pool[key] = new Queue<GameObject>();
        }

        gameObject.SetActive(false);
        gameObject.transform.SetParent(gameObjectPool.transform);
        _pool[key].Enqueue(gameObject);
    }
}

对象池的使用

using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;

public class SkillManager : MonoBehaviour
{
    public SkillEventSO skillManagerSO;

    private AsyncOperationHandle<GameObject> _gameObjectHandle;

    private GameObjectPool _bulletPool;

    #region Unity生命周期
    private void Awake()
    {
        _bulletPool = new GameObjectPool("BulletGameObjectPool");
        _bulletPool.gameObjectPool.transform.SetParent(transform);
    }
    #endregion

    // 释放技能
    public void CastSkill(SkillDTO skillDTO)
    {

        string prefabAddress = skillDTO.prefabAddress;

        // 对象池获取对象,如果池中存在对象就直接拿来用,如果没有就是实例化一个新的
        GameObject bullet = _bulletPool.GetGameObject(prefabAddress);
        if (bullet != null)
        {
            bullet.transform.SetParent(transform);
            bullet.GetComponent<BulletController>().skillDTO = skillDTO;
            bullet.SetActive(true);
        }
        else
        {
            _gameObjectHandle = Addressables.LoadAssetAsync<GameObject>(prefabAddress);
            _gameObjectHandle.Completed += (handle) =>
            {
                if (handle.Status == AsyncOperationStatus.Succeeded)
                {
                    bullet = Instantiate(handle.Result, transform);
                    bullet.transform.SetParent(transform);
                    bullet.GetComponent<BulletController>().skillDTO = skillDTO;
                    bullet.GetComponent<BulletController>().skillManager = this;
                }
                else
                {
                    Debug.LogError("Asset load failed: " + prefabAddress);
                }
            };
        }
    }
    // 回收技能
    public void RecoveryBulletGameObject(GameObject bulletGameObject)
    {
        _bulletPool.RecoveryGameObject(bulletGameObject.GetComponent<BulletController>().skillDTO.prefabAddress, bulletGameObject);
    }
}
  • 本文作者: jagger
  • 本文链接: /archives/unity-dui-xiang-chi-you-hua-xing-neng
  • 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!
Unity (避坑指南)
Unity 小技巧
jagger

jagger

66 日志
31 分类
0 标签
Creative Commons
0%
© 2026 jagger
由 Halo 强力驱动