(网页转载)Unity对象池的创建与使用

Chinar 教程效果:

1
MonoSingleton —— 单例基类
2
ObjectPool —— 对象池
3
PoolTest —— 测试对象池的使用
支持
May Be —— 搞开发,总有一天要做的事!


1

MonoSingleton —— 单例基类

using UnityEngine;


/// <summary>
/// 泛型单例基类 —— 任何继承自该类的类,都是单例类
/// </summary>
/// <typeparam name="T">泛型</typeparam>
public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T>
{
    private static T instance;
    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                instance = FindObjectOfType(typeof(T)) as T;
                if (instance == null) instance = new GameObject("Chinar Single of " + typeof(T).ToString(), typeof(T)).GetComponent<T>();
            }

            return instance;
        }
    }


    private void Awake()
    {
        if (instance == null) instance = this as T;
    }


    private void OnApplicationQuit()
    {
        instance = null;
    }
}

2

ObjectPool —— 对象池

新建一个脚本 ObjectPool 继承自泛型基类 MonoSingleton《ObjectPool》

是以 ObjectPool 就会是一个单例类 

  1 using System.Collections;
  2 using System.Collections.Generic;
  3 using UnityEngine;
  4 
  5 
  6 /// <summary>
  7 /// 对象池(重复调用/使用的游戏物体)  子弹,技能,导弹,敌人
  8 /// </summary>
  9 public class ObjectPool : MonoSingleton<ObjectPool>
 10 {
 11     //字段  池 技能预设物(因为一个技能可能有多个预制件) 技能的复用性
 12     private Dictionary<string, List<GameObject>> cache = new Dictionary<string, List<GameObject>>();
 13     int                                          i     = 0; //标记 0
 14 
 15 
 16     /// <summary>
 17     /// 创建显示对象
 18     /// </summary>
 19     /// <returns>The object.</returns>
 20     /// <param name="key">对象名称</param>
 21     /// <param name="go">对象的预制件</param>
 22     /// <param name="position">对象的新位置</param>
 23     /// <param name="quaternion">对象的角度</param>
 24     public GameObject CreateObject(string key, GameObject go, Vector3 position, Quaternion quaternion)
 25     {
 26         GameObject tempgo = cache.ContainsKey(key) ? cache[key].Find(p => !p.activeSelf) : null; //返回池中未激活的对象,所有都被激活就返回空,赋值给临时对象
 27         if (tempgo != null)                                                                      //如果临时对象不为空
 28         {
 29             tempgo.transform.position = position;   //设置位置
 30             tempgo.transform.rotation = quaternion; //旋转信息
 31         }
 32         else //否则,就是空了。(也就是没能从池子里取出对象)
 33         {
 34             tempgo = Instantiate(go, position, quaternion); //那就根据传入的预设物,生成一个新物体
 35             print("实例化物体数量:" + i++);
 36             if (!cache.ContainsKey(key)) //池中没有键
 37             {
 38                 cache.Add(key, new List<GameObject>()); //新建一个 列表
 39             }
 40 
 41             cache[key].Add(tempgo); //给字典中的列表加入/add 临时物体,如果有键就直接添加了
 42         }
 43 
 44         tempgo.SetActive(true); //并启用临时物体
 45         return tempgo;          //返回
 46     }
 47 
 48 
 49     /// <summary>
 50     /// 直接回收
 51     /// </summary>
 52     /// <param name="go">Go.</param>
 53     public void CollectObject(GameObject go)
 54     {
 55         go.SetActive(false);
 56     }
 57 
 58 
 59     /// <summary>
 60     /// 延迟回收
 61     /// </summary>
 62     /// <param name="go">Go.</param>
 63     /// <param name="delay">Delay.</param>
 64     public void CollectObject(GameObject go, float delay)
 65     {
 66         StartCoroutine(Collect(go, delay));
 67     }
 68 
 69 
 70     private IEnumerator Collect(GameObject go, float delay)
 71     {
 72         yield return new WaitForSeconds(delay);
 73         CollectObject(go);
 74     }
 75 
 76 
 77     /// <summary>
 78     /// 释放资源
 79     /// </summary>
 80     /// <returns>The clear.</returns>
 81     /// <param name="key">Key.</param>
 82     public void Clear(string key)
 83     {
 84         if (cache.ContainsKey(key))
 85         {
 86             //Destroy当中所有的对象
 87             for (int i = 0; i < cache[key].Count; i++)
 88             {
 89                 Destroy(cache[key][i]);
 90             }
 91 
 92             //清除键当中的所有值
 93             //cache[key].Clear();
 94             //清除这个键(键值一起清除)
 95             cache.Remove(key);
 96         }
 97     }
 98 
 99 
100     /// <summary>
101     /// 释放所有对象池
102     /// </summary>
103     public void ClearAll()
104     {
105         var list = new List<string>(cache.Keys);
106         for (int i = 0; i < list.Count; i++)
107         {
108             Clear(list[i]);
109         }
110     }
111 }

3

PoolTest —— 测试对象池的使用

新建一个脚本 PoolTest 用来测试对象池的使用 

 1 using UnityEngine;
 2 
 3 
 4 /// <summary>
 5 /// 测试对象池的调用
 6 /// </summary>
 7 public class PoolTest : MonoBehaviour
 8 {
 9     GameObject go;   //临时对象
10     GameObject item; //临时对象池对象
11 
12 
13     void Start()
14     {
15         go = Resources.Load<GameObject>("Cube"); //在Resources文件目录下做一个Cube预设物
16     }
17 
18 
19     void Update()
20     {
21         if (Input.GetKey(KeyCode.Space)) //按下空格创建一个Cube
22         {
23             item                    =  ObjectPool.Instance.CreateObject("Object1", go, Vector3.zero, new Quaternion(0, 0, 0, 0));
24             item.transform.position += new Vector3(0, 0, 1);
25         }
26 
27 
28         if (Input.GetMouseButtonDown(0)) //按下左键执行回收对象
29         {
30             if (item != null)
31             {
32                 ObjectPool.Instance.CollectObject(item, 0.2f);
33             }
34         }
35 
36 
37         if (Input.GetMouseButtonDown(1)) //按下右键执行清除已经生成的对象
38         {
39             ObjectPool.Instance.Clear("Object1");
40         }
41     }
42 }

猜你喜欢

转载自www.cnblogs.com/satanj/p/9785632.html