Unity3d 对象池、子对象池的实现

ObjectPool.cs 对象池的实现

码云简单示例:https://gitee.com/xianglinlove/ObjectPool

using System.Collections.Generic;
using UnityEngine;

public class ObjectPool : Singleton
{
    // Resources目录
    public string ResourceDir = "";

    // 保存预设资源和子池子
    Dictionary<string, SubPool> _pools = new Dictionary<string, SubPool>(); 

    // 取 name是预设的名字
    public GameObject Spawn(string name)
    {
        // 判断对应的子池子是否存在
        // 不存在就创建一个子池子
        // 然后返回
        if(!_pools.ContainsKey(name))
            RegistreNewPool(name);
        SubPool pool = _pools[name];
        return pool.Spawn();
    }

    // 回收
    public void UnSpawn(GameObject go)
    {
        // 只回收池子中存在的对象
        // 遍历字典,找到包含go的子池子
        // 调用子池子的UnSpawn方法回收
        SubPool subPool = null;

        foreach (var pool in _pools.Values)
        {
            if (pool.Contains(go))
            {
                subPool = pool;
                break;
            }
        }

        if(subPool != null)
            subPool.UnSpawn(go);
    }

    // 回收所有
    public void UnSpawnAll()
    {
        if (_pools == null) return;

        foreach (var subPool in _pools.Values)
        {
            subPool.UnSpawnAll();
        }
    }

    // 创建新子池子
    void RegistreNewPool(string name)
    {
        // 获取预设
        string prefab = "";
        if (string.IsNullOrEmpty(ResourceDir))
            prefab = name;
        else
            prefab = ResourceDir + "/"+name;
        // 加载预设
        GameObject go = Resources.Load(prefab);
        // 创建新池子
        SubPool pool = new SubPool(transform,go);
        _pools.Add(pool.Name,pool);
    }
}

SubPool.cs 子对象池的实现

using System.Collections.Generic;
using UnityEngine;

public class SubPool
{
    // 对象池管理
    private Transform _parent;

    // 预设
    private GameObject _prefab;

    // 池子
    private List _objects = new List();

    // 标识
    public string Name
    {
        get { return _prefab.name; }
    }

    // 构造
    public SubPool(Transform parent, GameObject prefab)
    {
        this._parent = parent;
        this._prefab = prefab;
    }

    // 从池子中取对象
    public GameObject Spawn()
    {
        GameObject go = null;
        // 遍历池子,看是否存在未被使用的对象
        foreach (GameObject obj in _objects)
        {
            if (!obj.activeSelf)
            {
                go = obj;
                break;
            }
        }
        // 如果池子中不存在未被使用的就需要根据prefab实例化一个GameObject出来
        // 并将新的对象加入到池子当中
        if (go == null)
        {
            go = UnityEngine.Object.Instantiate(_prefab);
            go.transform.parent = _parent;
            _objects.Add(go);
        }
        // 激活对象,并通过该对象发送消息
        go.SetActive(true);
        go.SendMessage("OnSpawn",SendMessageOptions.DontRequireReceiver);   // 取出实例之后可能需要做一些操作,比如有些Player,可能有默认动画之类的

        return go;
    }

    // 回收对象
    public void UnSpawn(GameObject go)
    {
        // 只回收池子中存在的对象
        if (Contains(go))
        {
            go.SendMessage("OnUnspawn", SendMessageOptions.DontRequireReceiver); // 回收对象的时候需要设置 对象的属性至初始值
            go.SetActive(false);          
        }
    }

    // 回收所有对象
    public void UnSpawnAll()
    {
        if (_objects == null) return;
        // 只处理池子中所有标识为启用的对象
        foreach (GameObject obj in _objects)
        {
            if(obj.activeSelf)
                UnSpawn(obj);
        }
    }

    public bool Contains(GameObject go)
    {
       return _objects.Contains(go);
    }
}

接口 IReusable.cs

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

public interface IReusable
{
    // 当取出时调用
    void OnSpawn();   // 根据子对象池中设置的消息通知 每一个Spawn出来的对象上须包含这样的函数用来接收消息

    // 当回收时调用
    void OnUnspawn();
}

可复用对象

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

// 可重用的抽象对象类,由其子类来实现方法
public abstract class ReusableObject : MonoBehaviour, IReusable
{
    public abstract void OnSpawn();         // 子对象池Spawn出来的对象 都是需要继承自MonoBehavior的 需要使用Update Awake等函数

    public abstract void OnUnspawn();
}

你可能感兴趣的:(Unity3d)