对象池技术(unity3d)

11.5 网络联机对战11-1_哔哩哔哩_bilibili

优化技术

面临的问题:

经常生成重复的对象【可以是游戏对象,也可以是普通对象】

同样的对象,生命周期短

例如:子弹、怪物、特效、音效

问题在哪?频繁的生成和销毁

缺点:占用了一些内存

 池子是动态的

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeObject : PoolObject {

    private Rigidbody _rigidbody;

    private void Awake()
    {
        _rigidbody = GetComponent<Rigidbody>();
    }

    public override void OnSpawn()
    {
        //速度归零
        _rigidbody.velocity = Vector3.zero;

        _rigidbody.angularVelocity = Vector3.zero;
    }

    public override void OnPause()
    {
        base.OnPause();
    }
}
 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PoolObject : MonoBehaviour {
    [Header("对象的生命周期")]
    public float lifeTime = 2f;

    public virtual void OnEnable()
    {
        //启动协程
        StartCoroutine(DelayEnterPool());
    }

    /// <summary>
    /// 延迟进入对象池
    /// </summary>
    /// <returns></returns>
    private IEnumerator DelayEnterPool() {
        yield return new WaitForSeconds(lifeTime);
        //进入对象池
        GameObjectPool.Instance.SetGameObject(gameObject);
    }

    /// <summary>
    /// 对象出生后要做的事情【初始化操作】
    /// </summary>
    public virtual void OnSpawn() {

    }
    /// <summary>
    /// 对象进入对象池之前要做的事情
    /// </summary>
    public virtual void OnPause() {

    }
}
 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UsePool : MonoBehaviour {    
    // Update is called once per frame
    void Update () {
        if (Input.GetKeyDown(KeyCode.Space)) {
            //获取对象
            GameObjectPool.Instance.GetGameObject("Cube", Vector3.zero, Quaternion.identity);
        }
    }
}
 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Reflection;
using System;


namespace Utility
{
    public class Singleton<T> where T : class
    {
        //单例对象
        private static T _singleton;
        //获取单例
        public static T Instance
        {
            get
            {
                if (_singleton == null)
                {
                    //如果这样写,那么该类型T必有一个public的构造函数
                    //_singleton = new T();
                    //通过反射的方式,去实例化一个对象出来
                    //派生的单例类中必须要有一个私有的无参构造
                    _singleton = (T)Activator.CreateInstance(typeof(T), nonPublic: true);

                }
                return _singleton;
            }
        }
    }
}
 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


namespace Utility
{
    public class AssetsManager : Singleton<AssetsManager>
    {
        //私有构造
        private AssetsManager()
        {
            assetsCache = new Dictionary<string, Object>();
        }

        /// <summary>
        /// 资源缓存
        /// </summary>

        private Dictionary<string, Object> assetsCache;
        /// <summary>
        /// 获取资源
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="path">资源路径</param>
        /// <returns></returns>

        public Object OldGetAsset<T>(string path)
        {
            //要返回的资源
            Object assetObj = null;
            //如果缓存中没有该资源
            if (!assetsCache.ContainsKey(path))
            {
                //通过resources加载资源
                assetObj = Resources.Load(path);
                //将资源存进缓存
                assetsCache.Add(path, assetObj);
            }
            else
            {
                //如果缓存中有,则直接从缓存中拿
                assetObj = assetsCache[path];
            }

            return assetObj;
        }


        ///新方法---获取资源
        public Object GetAsset(string path)
        {
            //要返回的资源
            Object assetObj = null;
            //尝试从字典中获取该路径所对应的资源
            if (!assetsCache.TryGetValue(path, out assetObj))
            {
                //通过resources加载资源
                assetObj = Resources.Load(path);
                //将资源存进缓存
                assetsCache.Add(path, assetObj);
            }
            return assetObj;
        }
    }
}
 

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Utility;

public class GameObjectPool {
    #region Singleton
    //单例
    public readonly static GameObjectPool Instance = new GameObjectPool();

    private GameObjectPool() {
        pool = new Dictionary<string, List<GameObject>>();
    }

    #endregion

    #region Object Pool
    /// <summary>
    /// 对象池
    /// </summary>
    Dictionary<string, List<GameObject>> pool;

    ///取
    ///从对象池取对象
    ///
    public GameObject GetGameObject(string objName,Vector3 pos, Quaternion rotation) {
        //要返回的游戏对象
        GameObject obj;
        //没有对应的子对象池,或有对应的对象池但池子为空
        if (!pool.ContainsKey(objName) || pool[objName].Count == 0)
        {
            
            //先拿到预设体
            UnityEngine.Object prefab=AssetsManager.Instance.GetAsset(objName);
            //Instantiate生成
            obj=GameObject.Instantiate(prefab,pos,rotation) as GameObject;
            //改名字
            obj.name = objName;
        }
        else {
            //从池子中获取
            obj = pool[objName][0];
            //删除池中对象
            pool[objName].RemoveAt(0);
            //设置位置
            obj.transform.position = pos;
            //设置旋转
            obj.transform.rotation = rotation;
        }
        //激活对象
        obj.SetActive(true);
        try {
            //获取对象脚本
            obj.GetComponent<PoolObject>().OnSpawn();
        }
        catch (Exception e) {
            Debug.LogWarning(e);
        }
        //返回对象
        return obj;
    }


    ///存
    ///将对象存入对象池
    ///
    public void SetGameObject(GameObject obj) {
        try
        {
            //获取对象脚本
            obj.GetComponent<PoolObject>().OnPause();
        }
        catch (Exception e)
        {
            Debug.LogWarning(e);
        }
        //存入之前,先取消激活
        obj.SetActive(false);
        //判断有没有对应的子对象池
        if (!pool.ContainsKey(obj.name))
        {
            //新建子对象池,并将当前对象存入
            pool.Add(obj.name, new List<GameObject>() { obj });
        }
        else {
            //将当前对象存入对象池
            pool[obj.name].Add(obj);
        }        
    }

    #endregion
}
 

猜你喜欢

转载自blog.csdn.net/renwen1579/article/details/126452267