Unity学习笔记:游戏对象池

      容器(用于存放缓存的对象) 

                游戏对象池  池=容器=【字典】 列表?
                 放元素=游戏对象{技能A,技能B,特效,.....}
                 专门针对 游戏场景中的游戏对象 使用池技术

using UnityEngine;
using System.Collections.Generic;
using System.Collections;
/// <summary>
/// 游戏对象池:
/// </summary>
public class GameObjectPool : MonoSingleton<GameObjectPool>{

     //单例模式对象池
    private GameObjectPool(){}     
	//1 创建池:
    private  Dictionary<string, List<GameObject>> cache = 
    new Dictionary<string, List<GameObject>>();
    //2 创建使用池的元素【游戏对象】一个对象并使用对象:
    //池中有从池中返回;池中没有加载,放入池中再返回   
    public GameObject CreateObject(string key,GameObject go,
        Vector3 positon, Quaternion quaternion)
    {
        //1)查找池中有无可用游戏对象
        GameObject temoGo = FindUsable(key);
        //2)池中有从池中返回;
        if (temoGo != null)
        {   temoGo.transform.position = positon;
            temoGo.transform.rotation = quaternion;
            temoGo.SetActive(true);//表示当前这个游戏对象在使用中
        }
        else//3)池中没有加载,放入池中再返回
        {
            temoGo = Instantiate(go, positon, quaternion) as GameObject;
            //放入池中
            Add(key, temoGo);
        }
        //作为池物体的子物体
        temoGo.transform.parent = this.transform;
        return temoGo;//
    }
    private GameObject FindUsable(string key)
    {
        if (cache.ContainsKey(key))
        {          
            //找列表 中找出 未激活【未活动】的游戏物体 
            return cache[key].Find(p => !p.activeSelf);
        }
        return null;
    }
    private void Add(string key,GameObject go)
    {
        //先检查池中是否 有需要的key,没有,需要向创建key和对应的列表。
        if (!cache.ContainsKey(key))
        {
            cache.Add(key, new List<GameObject>());
        }
        //把游戏对象添加到 池中
        cache[key].Add(go);    
    }

    //3 释放资源:从池中删除对象!
    //3.1释放部分:按Key释放 
    public void Clear(string key)
    {
        if (cache.ContainsKey(key))
        {
            //释放场景中 的游戏物体
            for (int i = 0; i < cache[key].Count; i++)
            {    Destroy(cache[key][i]);   }
            //移除了对象的地址
            cache.Remove(key);
        }        
    }
    //3.2释放全部 循环调用Clear(string key)
    public void ClearAll()
    {
         //string[] keys = cache.Keys;
          //List<string> keys = new List<string>(cache.Keys);
          //for (int i = 0; i < keys.Count; i++)
          //{
          //  Clear(keys[i]);
          //}
          foreach (var a in cache.Keys)
          {
              Clear(key);
          }
    }
    //4 回收对象:使用完对象返回池中【从画面中消失】
    //4.1即时回收对象
    public void CollectObject(GameObject go)
    {
        go.SetActive(false);//本质:画面小时 设置属性
    }
    //4.2延时回收对象 等待一定的时间 协程
    public void CollectObject(GameObject go,float delay)
    { 
        StartCoroutine(CollectDelay(go, delay));
    }
    private IEnumerator CollectDelay(GameObject go, float delay)
    {
        yield return new WaitForSeconds(delay);
        CollectObject(go);
    }
}

单例模式抽象类(取自easytouch插件)

/// <summary>
/// Generic Mono singleton.
/// </summary>
using UnityEngine;

public abstract class MonoSingleton<T> : MonoBehaviour
    where T : MonoSingleton<T>{
	//2
	private static T m_Instance = null;
    //3
    //设计阶段 写脚本  没有挂在物体上   希望脚本 单例模式
    //运行时 需要这个脚本的唯一实例,第1次 调用instance
    //第2,3,4,......次 调用instance
	public static T instance{
        get
        {
			if( m_Instance == null )
            {
            	m_Instance = GameObject.FindObjectOfType(typeof(T)) as T;
                if( m_Instance == null )
                {
                    m_Instance = 
                    new GameObject("Singleton of " + typeof(T).ToString(), typeof(T))
                    .GetComponent<T>();
                    //1 创建一个游戏物体 在层次面板中能看到
                    //2 把T这个脚本挂在这个游戏物体上,作为游戏物体的一个脚本组件
                    //3 GetComponent<T>(). 返回这个脚本组件,
                    //   这个脚本组件就是唯一实例,代码中用
					 m_Instance.Init();
                }
               
            }
            return m_Instance;
        }
    }
    // unity项目特点:
    //设计阶段 写脚本  挂在物体上 
    //项目运行时【系统 帮我们 把脚本类 实例化了new】 脚本》》对象了
    //项目运行时 在Awake时,从场景中找到 唯一实例 记录在  m_Instance中      
    private void Awake(){
   
        if( m_Instance == null ){
            m_Instance = this as T;
        }
    }
    //提供 初始化 一种选择 Init ,Start
    public virtual void Init(){} 
    //当应用程序 退出做 清理工作!单例模式对象=null
    private void OnApplicationQuit(){
        m_Instance = null;
    }
}

对象池使用案例↓

using UnityEngine;
using System.Collections;
//TestGameObjectPool 把GameObjectPool 方法都调用一下
public class TestGameObjectPool : MonoBehaviour {
    public GameObject[] prefabs;//记住赋值
    public string[] names = {"Cube","Sphere" };
	// Use this for initialization
    GameObjectPool poolobj = null;
	void Start () {
        poolobj = GameObjectPool.instance;
	    //调用创建的方法
        for (int i = 0; i < 3; i++)
        {
            Vector3 pos1 = new Vector3(Random.Range(-10, 10), 0,
                Random.Range(-10, 10));

            
            poolobj.CreateObject(names[0], prefabs[0],
                pos1, Quaternion.identity);
        }

	}
	
	// Update is called once per frame
	void OnGUI () {
        if (GUILayout.Button("创建"))
        {
            Vector3 pos1 = new Vector3(Random.Range(-10, 10), 0,
                Random.Range(-10, 10));           
            poolobj.CreateObject(names[0], prefabs[0],
                pos1, Quaternion.identity);
        }
        if (GUILayout.Button("释放 ,彻底删除"))
        {
            poolobj.ClearAll();
        }
        if (GUILayout.Button("回收"))
        {
            //找到某一个,回收
           var go= GameObject.FindGameObjectWithTag(names[0]);
           if (go != null) poolobj.CollectObject(go);
        }
	}
}

猜你喜欢

转载自blog.csdn.net/huanyu0127/article/details/107700329