传统对象池&AB对象池

说明:

   传统对象池与AB对象池 其实现原理一毛一样,其唯一区别在于游戏数据放在AB包中,如果按照传统对象池那样通过Resources的代码加载资源,会导致数据没有被打包,所以需要挂载资源。

原理图示:

传统对象池


使用方法:

  1. 挂载ObjectPool (场景中)
  2. 讲预制体(prefab)放入Resources资源中
  3. 然后就可以直接单例要数据!

代码:

/***************************************
作者: 蒋伟
版本: v1.0
最后修改时间: 2016-12-22
电话: 15928517727
功能&使用方法: 可重用接口
 * 
 *  void OnSpawn -------- 当生成时调用
 *  void OnUnspawn ------ 当回收时调用
***************************************/
using UnityEngine;
using System.Collections;
public interface IReusable
{
    //当生成时调用(初始化)
    void OnSpawn();
    //当回收时调用(销毁)
    void OnUnspawn();
}
View Code
/***************************************
作者: 蒋伟
版本: v1.3
最后修改时间: 2016/12/26
电话: 15928517727
功能&使用方法: 
 * 自定义顺序表, 注意存放在该表中的所有
 * 物体必须可比较,如果为自定义的类需要继
 * 自IComparable接口,并public实现接口汇总CompareTo(Object obj)
 * 接口!
 * 
 * 存在方法:
 * <0> ----------- MyArrayList<T>() -------- 无参构造
 * <1> ----------- Size() ------------------ 得到使用空间
 * <2> ----------- Expansion()(私有)------ 扩容
 * <3> ----------- Add(T data) ------------- 添加数据
 * <4> ----------- (r)T At(int index) ------ 得到数据
 * <5> ----------- Clear() ----------------- 清空数据
 * <6> ----------- (r)T this[int index] ---- 得到/设置 数据【索引器】
 * <7> ----------- SortSmallToBig() -------- 排序(从小到大)(冒泡排序)
 * <8> ----------- ConsoleShow() ----------- 显示(控制台) Unity程序别用
 * <9> ----------- DebugShow() ------------- 显示(Debug.Log) Unity调试使用
 * <10> ---------- Contains(T) ------------- bool类型返回是否包含这个东西
***************************************/
using UnityEngine;
using System.Collections;
using System;
namespace MyList
{

    //泛型顺序表 (IComparable) 可以比较的 
    //由于部分数据类型(GameObject)不支持数据比较,
    //然而它还不知羞耻的加了Sealed属性
    public class MyArrayList<T> /*where T : IComparable*/
    {
        //容量
        int capacity;
        //使用量
        int size;
        //堆 --- 指针
        T[] obj;
        //构造
        public MyArrayList()
        {
            //内存容量 (初始4 自动扩容)
            capacity = 4;
            //空间使用量归0
            size = 0;
            //开堆
            obj = new T[capacity];
        }
        //属性 --- 返回使用空间
        public int Size
        {
            //只写返回
            get { return size; }
        }
        //方法 --- 扩容
        void Expansion()
        {
            //容量 == 使用量
            if (size == capacity)
            {
                //容量扩大一倍
                capacity *= 2;
                //数据开堆
                T[] nt = new T[capacity];
                //复制数据
                for (int i = 0; i < size; ++i)
                {
                    nt[i] = obj[i];
                }
                //修改数据结构指针指向
                obj = nt;
            }
        }
        //方法 --- 数据添加
        public void Add(T data)
        {
            //扩容
            Expansion();
            //放入数据
            obj[size++] = data;
        }
        //方法 --- 得到数据[下标索引]
        public T At(int index)
        {
            //参数检查
            if (index < 0 || index >= size)
                return default(T);
            else
                return obj[index];
        }
        //方法 --- 清空
        public void Clear()
        {
            //使用空间修改为0就可以了
            size = 0;
        }
        //索引器a
        public T this[int index]
        {
            set
            {
                //设置数据 在 范围内
                if (index >= 0 && index < size)
                {
                    obj[index] = value;
                }
            }
            get
            {
                if (index >= 0 && index < size)
                    return obj[index];
                else
                    return default(T);
            }
        }
        //声明委托 
        //case 1  -------------- Left >  Right  
        //case 0  -------------- Left == Right
        //case -1  -------------- Left <  Right
        public delegate int CompareTo(T _objLeft, T _objRight);
        //方法 --- 排序(冒泡)
        public void SortSmallToBig(CompareTo CTF)
        {
            //冒泡排序
            for (int i = 0; i < size; ++i)
            {
                for (int j = size - 1; j > i; --j)
                {
                    if (CTF(obj[i], obj[j]) > 0)
                    {
                        T temp = obj[i];
                        obj[i] = obj[j];
                        obj[j] = temp;
                    }
                }
            }
        }
        //遍历显示(C#控制台显示)
        public void ConsoleShow()
        {
            //遍历 
            for (int i = 0; i < size; ++i)
            {
                //这个显示方式比
                Console.WriteLine(obj[i]);
            }
        }
        //遍历显示(Unity.Debug.Log(name))
        public void DebugShow()
        {
            //遍历 
            for (int i = 0; i < size; ++i)
            {
                //这个显示方式比
                Debug.Log(obj[i].ToString());
            }
        }
        //遍历查找
        public bool Contains(T t, CompareTo CTF)
        {
            //遍历
            for (int i = 0; i < size; ++i)
            {
                if (CTF(t, obj[i]) == 0)
                {
                    return true;
                }
            }
            //否则return false
            return false;
        }
    }

}
View Code
/***************************************
作者: 蒋伟
版本: v1.1
最后修改时间: 2018-06-05
电话: 15928517727
功能&使用方法: 传统对象池

1.挂载ObjectPool (场景中)
2.讲预制体(prefab)放入Resources资源中
3.然后就可以直接单例要数据了!

****************************************/
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class ObjectPool : Singleton<ObjectPool>
{
    //子对象池存储
    Dictionary<string, SubPool> m_pools;

    //初始化
    public override void Awake()
    {
        base.Awake();

        Init();
    }

    private void Init()
    {
        m_pools = new Dictionary<string, SubPool>();
    }


    //取对象 绝对路径
    public GameObject Spawn(string _name)
    {
        //返回的子对象池
        SubPool pool = null;
        //如果存在该子对象池
        if (m_pools.ContainsKey(_name))
        {
            pool = m_pools[_name];
        }
        else
            pool = CreateNewSubPool(_name);
        //返回一个新对象
        return pool.Spawn();
    }
    //回收对象
    public void Unspawn(GameObject _obj)
    {
        SubPool pool = null;

        //遍历查找所有子池子
        foreach (SubPool p in m_pools.Values)
        {
            //找到了
            if (p.Contains(_obj))
            {
                pool = p;
                break;
            }
        }
        //调用回收方法
        if (pool!= null)
            pool.Unspawn(_obj);
    }
    
    //回收所有对象
    public void UnspawnAll()
    {
        foreach (SubPool p in m_pools.Values)
            p.UnspawnAll();
    }

    //创建新的子对象池
    private SubPool CreateNewSubPool(string _name)
    {
        //预设路径
        string path = "";
        path = _name;
        //加载预设
        GameObject prefab = Resources.Load<GameObject>(path);
        SubPool np = new SubPool(prefab);
        //添加到池列表
        m_pools.Add(_name, np);

        //返回子对象池
        return np;
    }
    
}
View Code
/***************************************
作者: 蒋伟
版本: v1.0
最后修改时间: 2016-12-21
电话: 15928517727
功能&使用方法: 可被回收的类(抽象类)
*
***************************************/
using UnityEngine;
using System.Collections;
public abstract class ReusableObject : MonoBehaviour, IReusable
{
    //pS:纯虚类不能有本体 但如果用virtual 修饰则不会有这个问题
    public abstract void OnSpawn();
    public abstract void OnUnspawn();
}
View Code
/***************************************
作者: 蒋伟
版本: v1.0
最后修改时间: 2016-12-22
电话: 15928517727
功能&使用方法: 单例
 * 这个单例还需要理解
***************************************/
using UnityEngine;
using System.Collections;
public class Singleton<T> : MonoBehaviour
    where T : MonoBehaviour
{
    //指针
    protected static T m_instance = null;
    //属性
    public static T Instance
    {
        get { return m_instance; }
    }
    //偷懒的单例方式 在 Awake里面进行初始化
    public virtual void Awake()
    {
        m_instance = this as T;
    }
}
View Code
/***************************************
作者: 蒋伟
版本: v1.0
最后修改时间: 2016-12-22
电话: 15928517727
功能&使用方法:子对象池
 * 
 * --------------------------------------------
 * GameObject m_prefab    ------------- 预设
 *  MyArrayList<GameObject> m_objects - 存储物体用链表
 * --------------------------------------------
 * Name ------------------------------- 得到子对象池名字(属性)
 * SubPool(GameObject prefab)-------- 构造
 * Spawn()--------------------------- 喂!对象池!给我一个对象!(单身狗之咆哮~)
 * Unspawn(GameObject obj) ------------ 回收一个对象
 * UnspawnAll() --------------------- 回收所有对象s
 * Contains(GameObject obj) --------- 是否包含对象
***************************************/
using UnityEngine;
using System.Collections;
using MyList;
public class SubPool
{
    //预设
    GameObject m_prefab;
    //存储物体用链表(构造来)
    MyArrayList<GameObject> m_objects;
    //子对象池名字
    public string Name
    {
        get
        {
            return m_prefab.name;
        }
    }
    //构造
    public SubPool(GameObject prefab)
    {
        //赋值
        this.m_prefab = prefab;

        //开堆
        m_objects = new MyArrayList<GameObject>();
    }
    //取对象 池子中则拿出 无则新建
    public GameObject Spawn()
    {
        GameObject obj = null;
        for (int i = 0; i < m_objects.Size; ++i)
        {
            //池子中存在,拿出
            if (!m_objects[i].activeSelf)
            {
                obj = m_objects[i];
                break;
            }
        }
        //如果对象池没有了!
        if (obj == null)
        {
            obj = GameObject.Instantiate<GameObject>(m_prefab);
            m_objects.Add(obj);
        }
        //设置为启用
        obj.SetActive(true);
        //调用怪物的初始化函数 并且是预设体子树下所有组件的初始化
        //(厉害了我的哥!),参2保证不投射错误
        obj.SendMessage("OnSpawn", SendMessageOptions.DontRequireReceiver);
        return obj;
    }
    //回收对象
    public void Unspawn(GameObject obj)
    {
        //对象存在于子对象池
        if (Contains(obj))
        {
            obj.SendMessage("OnUnspawn", SendMessageOptions.DontRequireReceiver);
            obj.SetActive(false);
        }
    }
    //回收该池子的所有对象
    public void UnspawnAll()
    {
        for (int i = 0; i < m_objects.Size; ++i)
        {
            if (m_objects[i].activeSelf)
            {
                m_objects[i].SendMessage("OnUnspawn", SendMessageOptions.DontRequireReceiver);
                m_objects[i].SetActive(false);
            }
        }
    }
    //是否包含对象
    public bool Contains(GameObject go)
    {
        bool temp = false;
        //判断物体是否存在于顺序表中
        for (int i = 0; i < m_objects.Size; ++i)
        {
            if (m_objects[i] == go)
            {
                temp = true;
                break;
            }
        }
        return temp;
    }
}
View Code

猜你喜欢

转载自www.cnblogs.com/jwv5/p/9140359.html