空池触发和借用模式 空池触发,顾名思义就是在对象池空的时候获取对象会直接去生成,首先上一个简单的空池触发和借用模式的对象池
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 public  sealed  class  GameObjectPool  : MonoBehaviour {     public  static  GameObjectPool Instance { get ; private  set ; }     private  Dictionary<string , List<GameObject>> pool = new  Dictionary<string , List<GameObject>>();     private  void  Awake ()         if  (Instance == null ) {             Instance = this ;         } else  {             Destroy(gameObject);         }     }     public  GameObject Get (string  prefabName, Vector3 position, Quaternion rotation         var  key = prefabName;         GameObject obj;                           if  (pool.ContainsKey(key) && pool[key].Count > 0 ) {             var  list = pool[key];             obj = list[0 ];             list.RemoveAt(0 );                          obj.SetActive(true );             obj.transform.position = position;             obj.transform.rotation = rotation;         } else  {                          obj = Instantiate(Resources.Load(prefabName), position, rotation, transform) as  GameObject;         }         return  obj;     }     public  void  Store (GameObject obj )         var  key = obj.name.Replace("(Clone)" , string .Empty);         if  (pool.ContainsKey(key)) {             pool[key].Add(obj);         } else  {             pool[key] = new  List<GameObject>() { obj };         }         obj.SetActive(false );     } } 
此为一个很简单也很经典的对象池实现,很容易我们就可以发现一个问题:
如果我对象获取的频率太高了获取还能连贯吗? 
很明显,不能。当某次对象获取请求太快。前面一部分可能是正常获取池中已有物品,但是后面空池的时候,会阻断这次获取,改为先去执行生成。生成本身就是一个耗时的操作,这必然会导致我们的获取不连贯,导致卡顿。
水位线 为了优化空池触发的性能,此处我们引入水位线模式的对象池。和空池类似,只不过水位线加入了一个触发分配的阈值,比如池子里面还剩10个物体的时候就要开始分配了。此时,分配过程 和 get 相互独立
同时我们需要明确一下空池触发的缺点:即 get 的时候现场生成导致 get 时间变成,而空池补充这个操作,我们就得放在非 get 时机,也就是生成和 get 分离
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 public  sealed  class  GameObjectPool  : MonoBehaviour {     public  static  GameObjectPool Instance { get ; private  set ; }     private  Dictionary<string , List<GameObject>> pool = new  Dictionary<string , List<GameObject>>();     public  int  WaterLevel { get ; private  set ; } = 10 ;     private  bool  isNeedGenerate = false ;     private  string  generateName;     private  void  Awake ()         if  (Instance == null ) {             Instance = this ;         } else  {             Destroy(gameObject);         }     }     public  GameObject Get (string  prefabName, Vector3 position, Quaternion rotation         var  key = prefabName;                  if  (!pool.ContainsKey(key)) {             pool[key] = new  List<GameObject>();             InitializeToWaterLevel(key);         }         GameObject obj;                  if  (pool[key].Count > 0 ) {             var  list = pool[key];             obj = list[0 ];             list.RemoveAt(0 );                          obj.SetActive(true );             obj.transform.position = position;             obj.transform.rotation = rotation;                          if  (pool[key].Count < WaterLevel) {                 isNeedGenerate = true ;                 generateName = prefabName;             }         } else  {             Debug.Log("水位线可能较低" );             obj = Instantiate(Resources.Load(key), position, rotation, transform) as  GameObject;         }         return  obj;     }     public  void  Store (GameObject obj )         var  key = obj.name.Replace("(Clone)" , string .Empty);         if  (pool.ContainsKey(key)) {             pool[key].Add(obj);         } else  {             pool[key] = new  List<GameObject>() { obj };         }         obj.SetActive(false );     }     private  void  InitializeToWaterLevel (string  key         GenerateToPool(key, WaterLevel);     }     private  void  GenerateToWaterLevel (string  key         var  currCount = pool[key].Count;         GenerateToPool(key, WaterLevel - currCount);     }     private  void  GenerateToPool (string  key, int  num         for  (int  i = 0 ; i < num; i++) {             var  obj = Instantiate(Resources.Load(key), transform) as  GameObject;             obj.SetActive(false );             pool[key].Add(obj);         }     }     private  void  Update ()         if  (isNeedGenerate) {             GenerateToWaterLevel(generateName);             isNeedGenerate = false ;         }     } } 
此处我实现了一个较为简单的水位线对象池,在 get 时对不足水位线的物体进行标记,然后在 update 里面轮询标记来生成缺少的物体。我没有在 get 里面做一个 Action 之类的东西,因为感觉在返回之前这样还是会导致 get 在生成物体时阻塞掉,以至于 get 速度变慢
TODO:lease/return 对象池 和 借用模式和引用计数模式