[卡卡西0旗木] [代码设计]对象池设计与打飞机演示

不好意思,最近实在忙的慌。好久没发文章了。不管怎样,先发个图压压惊。<br/>
       

是的。这就是大名鼎鼎的打飞机。看到那小飞机没有,是我用Cube拼出来的-_-。不过那不是重点。我们今天的重点是讲对象池。我们更多关注的是怎么管理子弹,而不是飞机~~~
不过文章最后还是会给出完整工程和可运行exe的下载地址。

0、为什么写
A、刚好项目需要,然后之前的对象池我胡写的(可以说没有)
B、刚好群里有人在问
C、刚好好久没发文章,不知道写什么

1、什么是对象池
我经常说的一点,理解概念,理解基础很重要。因为概念理解深刻了,代码也就出来了。
所以大家对这个概念如果还不懂的,要赶紧去查查。这里我不多说了,各种百科都可以找到。

2、我的设计
我的对象池主要由:对象池、对象、对象工厂组成。
为了拓展,对象池抽象为IObjectPool、对象为泛型、对象工厂为IObjectFactory。

3、IObjectPool
[C#]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
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
namespace Com.Duoyu001.Pool
{
     /* ==============================================================================
      * 功能描述:一个对象池接口 
      * 创 建 者:cjunhong
      * 邮    箱:[url=mailto:john.cha@qq.com]john.cha@qq.com[/url]
      * Q      Q:327112182
      * ==============================================================================*/
 
     /// <summary>
     /// 一个对象池接口 
     /// </summary>
     /// <typeparam name="T">该对象池中存放的对象类型</typeparam>
     public interface IObjectPool<T>
     {
         /// <summary>
         /// 从对象池中取对象
         /// </summary>
         /// <returns></returns>
         T Take();
 
         /// <summary>
         /// 把对象存回对象池
         /// </summary>
         /// <param name="t"></param>
         void Restore(T t);
 
         /// <summary>
         /// 对象池增加对象
         /// </summary>
         void AddObject();
 
         /// <summary>
         /// 对象池中空闲(可用)对象的数目
         /// </summary>
         /// <returns></returns>
         int IdleNum();
 
         /// <summary>
         /// 对象池中空闲(可用)对象的数目
         /// </summary>
         /// <returns></returns>
         int ActiveNum();
 
         /// <summary>
         /// 清除对象池中所有对象
         /// </summary>
         void Clear();
     }
}


接口比较简单,也做了注释。就不说明了。接着看


4、IObjectFactory
[C#]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
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
namespace Com.Duoyu001.Pool
{
     /* ==============================================================================
      * 功能描述:对象工厂,用于创建、销毁、激活、反激活对象 
      * 创 建 者:cjunhong
      * 邮    箱:[url=mailto:john.cha@qq.com]john.cha@qq.com[/url]
      * Q      Q:327112182
      * ==============================================================================*/
     public interface IObjectFactory<T>
     {
         /// <summary>
         /// 创建一个对象
         /// </summary>
         /// <returns></returns>
         T CreateObject( bool doActive);
 
         /// <summary>
         /// 销毁对象
         /// </summary>
         /// <param name="t"></param>
         void DestroyObject(T t);
 
         /// <summary>
         /// 激活对象
         /// </summary>
         /// <param name="t"></param>
         void ActivateObject(T t);
 
         /// <summary>
         /// 反激活对象
         /// </summary>
         /// <param name="t"></param>
         void UnActivateObject(T t);
     }
}


依旧很简单的接口。没错,对象池真的很简单。


5、对象池实现BaseObjectPool
[C#]  纯文本查看  复制代码
?
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
using System;
using System.Collections.Generic;
 
namespace Com.Duoyu001.Pool
{
     /* ==============================================================================
      * 功能描述:基础对象池实现 
      * 创 建 者:cjunhong
      * 邮    箱:[url=mailto:john.cha@qq.com]john.cha@qq.com[/url]
      * Q      Q:327112182
      * ==============================================================================*/
     public class BaseObjectPool<T> : IObjectPool<T>
     {
         private readonly List<T> pools = new List<T>();
         private readonly IObjectFactory<T> factory;
 
         /// <summary>
         /// 最大可达到的空闲对象数目
         /// </summary>
         private readonly int maxIdleNum;
 
         private int activeNum = 0;
 
         public BaseObjectPool(IObjectFactory<T> factory, int maxIdleNum)
         {
             if (factory == null )
             {
                 throw new ObjectPoolExeception( "factory can not be null" );
             }
             this .factory = factory;
             this .maxIdleNum = maxIdleNum;
         }
 
         public T Take()
         {
             T t;
 
             if (pools.Count == 0)
             {
                 t = factory.CreateObject( true );
             }
             else
             {
                 t = pools[0];
                 factory.ActivateObject(t);
                 pools.RemoveAt(0);
             }
             
             activeNum++;
             return t;
         }
 
         /// <summary>
         /// 将一个指定对象返回对象池,如果对象池已达到空闲对象上限,则指定对象直接被工厂销毁。
         /// </summary>
         /// <param name="t"></param>
         public void Restore(T t)
         {
             if (pools.Count >= maxIdleNum)
             {
                 factory.DestroyObject(t);
             }
             else
             {
                 factory.UnActivateObject(t);
                 pools.Add(t);
             }
             activeNum--;
         }
 
         /// <summary>
         /// 如果池没达到空闲对象上限,则往池中增加一个对象。
         /// 如果池已经达到空闲对象上限,则不进行任何处理。
         /// </summary>
         public void AddObject()
         {
             if (pools.Count < maxIdleNum){
                 T t = factory.CreateObject( false );
                 pools.Add(t);
             }
         }
 
         public int IdleNum()
         {
             return pools.Count;
         }
 
         public int ActiveNum()
         {
             return activeNum;
         }
 
         public void Clear()
         {
             foreach (T t in pools)
             {
                 factory.DestroyObject(t);
             }
             pools.Clear();
         }
     }
}


这是一个基础的对象池。他构造的时候指定工厂和最大空闲的对象数目。
最大空闲的对象数目是干嘛的?就是比如你一般情况同时只会存在10个对象A。但是某个峰值从池中取出了100个。那么当这些对象被存回对象池的时候,有些会被抛弃。最后池中可用的对象不超过构造时指定的最大数目。


6、休息一下
这时候,基本一个对象池已经完成了。就是你可以new BaseObjectPool。指定自己的工厂,然后就可以通过Take从池中取对象,通过Restore将对象存回。但是,还没完。
我们不会就此止步。
我还想着。这样我需要手动调用Restore来将对象存回对象池。有没有方便一点的。


7、定义一个主动回收的对象池IActiveRestoreObjectPool
[C#]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
namespace Com.Duoyu001.Pool
{
     /* ==============================================================================
      * 功能描述:一个能主动回收的对象池
      * 创 建 者:cjunhong
      * 邮    箱:[url=mailto:john.cha@qq.com]john.cha@qq.com[/url]
      * Q      Q:327112182
      * ==============================================================================*/
     public interface IActiveRestoreObjectPool<T> : IObjectPool<IAutoRestoreObject<T>>
     {
         /// <summary>
         /// 此方法必须能识别哪些对象可以回收,而且回收到池中
         /// </summary>
         void CheckRestore();
     }
}


可以看到这个接口是从我们前面的对象池接口中继承的,然后又增加了一个检查可回收对象的方法。


8、主动回收对象池的实现ActiveRestoreObjectPool
[C#]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
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
using System.Collections.Generic;
 
namespace Com.Duoyu001.Pool
{
     /* ==============================================================================
      * 功能描述:主动回收对象池 
      * 创 建 者:cjunhong
      * 邮    箱:[url=mailto:john.cha@qq.com]john.cha@qq.com[/url]
      * Q      Q:327112182
      * ==============================================================================*/
     /// <summary>
     ///
     /// </summary>
     /// <typeparam name="T"></typeparam>
     public class ActiveRestoreObjectPool<T> : IObjectPool<IAutoRestoreObject<T>>
     {
         private BaseObjectPool<T> baseObjectPool;
         private List<IAutoRestoreObject<T>> checkList = new List<IAutoRestoreObject<T>>();
         private IObjectFactory<T> factory;
 
         public ActiveRestoreObjectPool(IObjectFactory<T> factory, int maxIdleNum)
         {
             baseObjectPool = new BaseObjectPool<T>(factory, maxIdleNum);
             this .factory = factory;
         }
 
         public IAutoRestoreObject<T> Take()
         {
             T t = baseObjectPool.Take();
             AutoRestoreObject<T> autoRestoreObject = new AutoRestoreObject<T>(t);
             checkList.Add(autoRestoreObject);
             return autoRestoreObject;
         }
 
         /// <summary>
         /// 每次调用会把可回收的对象重新存入对象池
         /// </summary>
         public void CheckRestore()
         {
             for ( int i = 0; i < checkList.Count; i++)
             {
                 IAutoRestoreObject<T> check = checkList[i];
                 IAutoRestoreChecker autoRestoreChecker = check.Restore;
                 if (autoRestoreChecker != null && autoRestoreChecker.Restore)
                 {
                     baseObjectPool.Restore(check.Get());
                     checkList.RemoveAt(i);
                     i--;
                 }
             }
         }
 
         public void Restore(IAutoRestoreObject<T> t)
         {
             baseObjectPool.Restore(t.Get());
             checkList.Remove(t);
         }
 
         public void AddObject()
         {
             baseObjectPool.AddObject();
         }
 
         public int IdleNum()
         {
             return baseObjectPool.IdleNum();
         }
 
         public int ActiveNum()
         {
             return baseObjectPool.ActiveNum();
         }
 
         public void Clear()
         {
             baseObjectPool.Clear();
             foreach (IAutoRestoreObject<T> autoRestoreObject in checkList)
             {
                 factory.DestroyObject(autoRestoreObject.Get());
             }
             checkList.Clear();
         }
     }
}


可以看到,这个类其实很多接口的实现是托管给我们之前的BaseObjectPool来实现的。这样我们可以省下不少功夫~~
然后可以看到CheckRestore方法中是通过IAutoRestoreObject中的IAutoRestoreChecker来检查一个对象是否可以被回收到池中。
IAutoRestoreObject和IAutoRestoreChecker都是为了做主动回收而引入的新接口。
我们接着看
[C#]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
namespace Com.Duoyu001.Pool
{
     /* ==============================================================================
      * 功能描述:能被自动回收的对象 
      * 创 建 者:cjunhong
      * 邮    箱:[url=mailto:john.cha@qq.com]john.cha@qq.com[/url]
      * Q      Q:327112182
      * ==============================================================================*/
     public interface IAutoRestoreObject<T>
     {
 
         /// <summary>
         /// 是否能被回收的接口
         /// </summary>
         IAutoRestoreChecker Restore { get ; set ; }
 
         /// <summary>
         ///
         /// </summary>
         /// <returns></returns>
         T Get();
     }
}


[C#]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
namespace Com.Duoyu001.Pool
{
     /* ==============================================================================
      * 功能描述:自动回收检查器
      * 创 建 者:cjunhong
      * 邮    箱:[url=mailto:john.cha@qq.com]john.cha@qq.com[/url]
      * Q      Q:327112182
      * ==============================================================================*/
     public interface IAutoRestoreChecker
     {
         bool Restore { get ; }
     }
}


[C#]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
namespace Com.Duoyu001.Pool
{
     /* ==============================================================================
      * 功能描述:可主动回收的对象
      * 创 建 者:cjunhong
      * 邮    箱:[url=mailto:john.cha@qq.com]john.cha@qq.com[/url]
      * Q      Q:327112182
      * ==============================================================================*/
     public class AutoRestoreObject<T> : IAutoRestoreObject<T>
     {
         
         private T t;
 
         public AutoRestoreObject(T t)
         {
             this .t = t;
         }
 
         public IAutoRestoreChecker Restore { get ; set ; }
 
         public T Get()
         {
             return t;
         }
     }
}


这两个接口和实现都简单的没法说了。。。


9、为了更方便的和U3D结合,我继续提供了U3DAutoRestoreObjectPool
之前的类和接口都是与U3D无关的,没有引用到U3D的类。可以放到任何C#项目中使用。
其实大家设计代码也应该如此,应该一步步地,从最本质剥离出通用的东西。
到这一步,我们才设计出U3DAutoRestoreObjectPool,他是一个U3D组件。但是也具备了我们的对象池功能。
[C#]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
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
87
88
89
90
91
92
93
94
95
using UnityEngine;
using Com.Duoyu001.Pool;
namespace Com.Duoyu001.Pool.U3D
{
     /* ==============================================================================
      * 功能描述:对象池组件,可以挂在U3D对象上 
      * 创 建 者:cjunhong
      * 邮    箱:[url=mailto:john.cha@qq.com]john.cha@qq.com[/url]
      * Q      Q:327112182
      * ==============================================================================*/
     public class U3DAutoRestoreObjectPool : MonoBehaviour, IActiveRestoreObjectPool<GameObject>
     {
         private ActiveRestoreObjectPool<GameObject> pool;
 
         public GameObject prefab;
         public Transform parent;
         public int maxNum;
         public int initNum;
 
         private static int idGenerate;
         private int _id = -1;
         private int id
         {
             get
             {
                 if (_id == -1)
                 {
                     _id = idGenerate;
                     idGenerate++;
                 }
                 return _id;
             }
         }
 
         void Awake()
         {
             pool = new ActiveRestoreObjectPool<GameObject>( new PrefabFactory(prefab, parent), maxNum);
             if (initNum > maxNum)
             {
                 initNum = maxNum;
             }
             for ( int i = 0; i < initNum; i++)
             {
                 pool.AddObject();
             }
         }
 
         void OnGUI()
         {
             int y = 10+40*id;
             GUI.Label( new Rect(10, y, 300, 20),  "Idle num in pools#" +gameObject.name+ "  : " + pool.IdleNum());
             GUI.Label( new Rect(10, y+20, 300, 20), "Active num in pools#" +gameObject.name+ " : " + pool.ActiveNum());
         }
 
         public void Update()
         {
             pool.CheckRestore();
         }
 
         public IAutoRestoreObject<GameObject> Take()
         {
             return pool.Take();
         }
 
         public void Restore(IAutoRestoreObject<GameObject> t)
         {
             pool.Restore(t);
         }
 
         public void AddObject()
         {
             pool.AddObject();
         }
 
         public int IdleNum()
         {
             return pool.IdleNum();
         }
 
         public int ActiveNum()
         {
             return pool.ActiveNum();
         }
 
         public void Clear()
         {
             pool.Clear();
         }
 
         public void CheckRestore()
         {
             pool.CheckRestore();
         }
     }
}


从代码中可以看到这个组件引用了一个主动回收(ActiveRestoreObjectPool)的对象池,并且用PrefabFactory来构造这个对象池。
然后在Update的时候会调用对象池的CheckRestore来检查哪些对象可以被回收,并实施回收处理。
那么PrefabFactory是什么?
[C#]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
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
using UnityEngine;
 
namespace Com.Duoyu001.Pool.U3D
{
     /* ==============================================================================
      * 功能描述:U3D预设-对象池工厂 
      * 创 建 者:cjunhong
      * 邮    箱:[url=mailto:john.cha@qq.com]john.cha@qq.com[/url]
      * Q      Q:327112182
      * ==============================================================================*/
     public class PrefabFactory : IObjectFactory<GameObject>
     {
         private GameObject prefab;
         private Transform parent;
 
         public PrefabFactory(GameObject prefab, Transform parent)
         {
             this .prefab = prefab;
             this .parent = parent;
         }
 
         public GameObject CreateObject( bool doActive)
         {
             GameObject go =  GameObject.Instantiate(prefab) as GameObject;
             go.transform.parent = parent;
             go.transform.localPosition = Vector3.zero;
             if (doActive)
             {
                 ActivateObject(go);
             }
             else
             {
                 go.SetActive( false );
             }
             return go;
         }
 
         public void DestroyObject(GameObject t)
         {
             GameObject.Destroy(t);
         }
 
         public void ActivateObject(GameObject t)
         {
             t.SetActive( true );
         }
 
         public void UnActivateObject(GameObject t)
         {
             t.SetActive( false );
         }
     }
}


是的,就几行代码。他就是从预设创建GameObject、隐藏和显示GameObject而已。
看了那么多无聊的代码。或许应该看看怎么使用。

10、怎么调用对象池
A、你可以直接通过new创建具体的对象池实现,然后从中获取对象。
B、可以直接获取U3DAutoRestoreObjectPool组件,然后从中获取对象。
C、通过实现我们定义的IObjectPool或IActiveRestoreObjectPool接口来自定义对象池(不要以为自定义就很麻烦,从上面就可以看到自定义其实很多还是组合了我们已经实现的BaseObjectPool来实现的)。

11、具体案例-打飞机
A、打开我们工程中的场景
 


B、选择Airplane对象
 

这个就是飞机了。可以发现他上面有两个组件。
一个是我们之前定义的U3D对象池实现U3DAutoRestoreObjectPool
另一个是TestCastBullet组件。
这个组件主要就是控制飞机移动、发射3种类型的子弹的。好吧。写到这里。我发现这个类名取的不好,如果叫AirplaneController可能更好。。。
不管了。。先看代码
[C#]  纯文本查看  复制代码
?
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
using UnityEngine;
using System.Collections.Generic;
using Com.Duoyu001.Pool;
using Com.Duoyu001.Pool.U3D;
 
public class TestCastBullet : MonoBehaviour
{
     /// <summary>
     /// 开火口
     /// </summary>
     public Transform[] firePoint;
     /// <summary>
     /// 飞机移动速度
     /// </summary>
     public float velocity;
     /// <summary>
     /// 开火时间间隔
     /// </summary>
     public float castDuration;
 
     /// <summary>
     /// 子弹受力
     /// </summary>
     public float bulletForce;
     /// <summary>
     /// 子弹速度
     /// </summary>
     public float bulletVelocity;
     /// <summary>
     /// 子弹生命
     /// </summary>
     public float bulletLife;
     
     /// <summary>
     /// 子弹迸发特效的对象池
     /// </summary>
     public U3DAutoRestoreObjectPool burstEffectPool;
 
     /// <summary>
     /// 雷受力
     /// </summary>
     public float boomForce;
     /// <summary>
     /// 雷速度
     /// </summary>
     public float boomVelocity;
     /// <summary>
     /// 雷生命
     /// </summary>
     public float boomLife;
 
 
     /// <summary>
     /// 雷里每个单位的力大小
     /// </summary>
     public float boomUnitForce;
     /// <summary>
     /// 雷里每个单位的生命
     /// </summary>
     public float boomUnitInitLife;
     /// <summary>
     /// 雷里每个单位的速度
     /// </summary>
     public float boomUnitVelocity;
     /// <summary>
     /// 雷的单位数目
     /// </summary>
     public int boomUnitNum;
     /// <summary>
     /// 雷转圈数
     /// </summary>
     public float boomCircleNum;
     /// <summary>
     /// 雷的单位间隔
     /// </summary>
     public float boomDuration;
 
     //子弹特效的对象池
     private U3DAutoRestoreObjectPool pool;
     //飞机的Transform
     private Transform _CacheTransform;
     //下次可攻击事件
     private float nextCanCastTime;
 
     private List<TestBoom> booms = new List<TestBoom>();
 
     private void Awake()
     {
         pool = GetComponent<U3DAutoRestoreObjectPool>();
         _CacheTransform = gameObject.GetComponent<Transform>();
     }
 
     private void Update()
     {
         if (Input.GetKey(KeyCode.J) && Time.time >= nextCanCastTime)
         {
             nextCanCastTime = Time.time + castDuration;
             foreach (var tran in firePoint)
             {
                 IAutoRestoreObject<GameObject> restoreObj = null ;
                 GameObject go = null ;
 
                 //从迸发特效对象池中获取
                 restoreObj = burstEffectPool.Take();
                 //获取对象实体
                 go = restoreObj.Get();
                 go.transform.position = tran.position;
                 TimeBaseChecker checker = go.GetComponent<TimeBaseChecker>();
                 if (checker == null )
                 {
                     checker = go.AddComponent<TimeBaseChecker>();
                 }
                 checker.Init(0.5f); //特效时间大概是0.3秒。我们就让他0.5秒回收吧。这个暂时不需要很精确。
                 restoreObj.Restore = checker;   //将回收检查器用于对象
 
                 //从子弹特效对象池中取
                 restoreObj = pool.Take();
                 //获取子弹GameObject
                 go = restoreObj.Get();
                 go.transform.position = tran.position;
 
                 TestBullet bullet = go.GetComponent<TestBullet>();
                 bullet.Init(bulletForce, bulletLife, bulletVelocity, delegate (GameObject obj) { });
                 restoreObj.Restore = bullet;
             }
         }
 
         if (Input.GetKey(KeyCode.U) && Time.time >= nextCanCastTime)
         {
             nextCanCastTime = Time.time + castDuration;
             int [] angles = {-30, -20, -10, 0, 10, 20, 30};
             for ( int i =0; i<angles.Length; i++)
             {
                             int angle = angles[i];
                 IAutoRestoreObject<GameObject> restoreObj = null ;
                 GameObject go = null ;
 
                 //从迸发特效对象池中获取
                 restoreObj = burstEffectPool.Take();
                 //获取对象实体
                 go = restoreObj.Get();
                 go.transform.position = _CacheTransform.position;
                 TimeBaseChecker checker = go.GetComponent<TimeBaseChecker>();
                 if (checker == null )
                 {
                     checker = go.AddComponent<TimeBaseChecker>();
                 }
                 checker.Init(0.5f); //特效时间大概是0.3秒。我们就让他0.5秒回收吧。这个暂时不需要很精确。
                 restoreObj.Restore = checker;   //将回收检查器用于对象
 
                 //从子弹特效对象池中取
                 restoreObj = pool.Take();
                 //获取子弹GameObject
                 go = restoreObj.Get();
                 go.transform.position = _CacheTransform.position;
 
                 TestBullet bullet = go.GetComponent<TestBullet>();
                 bullet.Init(bulletForce, bulletLife, bulletVelocity, delegate (GameObject obj) { }, angle);
                 restoreObj.Restore = bullet;
             }
         }
 
         if (Input.GetKey(KeyCode.K))
         {
             //从子弹特效对象池中取
             IAutoRestoreObject<GameObject>  restoreObj = pool.Take();
             //获取子弹GameObject
             GameObject go = restoreObj.Get();
             go.transform.position = _CacheTransform.position;
             TestBullet bullet = go.GetComponent<TestBullet>();
             bullet.Init(boomForce, boomLife, boomVelocity, CreateBoom);
             restoreObj.Restore = bullet;
         }
 
         TryMovePlane();
         ProcessBooms();
     }
 
     /// <summary>
     /// 处理雷
     /// </summary>
     private void ProcessBooms()
     {
         for ( int i = 0; i < booms.Count; i++ )
         {
             var boom = booms[i];
             if (boom.End)
             {
                 booms.RemoveAt(i);
                 i--;
             }
             else
             {
                 boom.Update(Time.time);
             }
         }
     }
 
     private void CreateBoom(GameObject bullet)
     {
         booms.Add( new TestBoom(boomUnitNum, boomCircleNum, pool, boomDuration, bullet.gameObject.transform.position, boomUnitForce, boomUnitInitLife, boomUnitVelocity));
     }
 
     private void OnGUI()
     {
         int y = Screen.height - 45;
         int height = 20;
         GUI.Label( new Rect(10, y, 400, height),  "use `W`,`A`,`S`,`D` or `arrow` to move" );
         y -= height;
         GUI.Label( new Rect(10, y, 400, height), "use 'J' to shoot" );
         y -= height;
         GUI.Label( new Rect(10, y, 400, height), "use `U` to use shoot2" );
         y -= height;
         GUI.Label( new Rect(10, y, 400, height), "use `K` to use boom" );
         y -= height;
         GUI.Label( new Rect(10, y, 400, height), "---- Control ----" );
     }
 
     /// <summary>
     /// 根据实际情况看是否需要让飞机移动
     /// </summary>
     private void TryMovePlane()
     {
         Vector3 moveVelocity = Vector3.zero;
         if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
         {
             moveVelocity -= Vector3.right * velocity;
         }
         else if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
         {
             moveVelocity += Vector3.right * velocity;
         }
 
         if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
         {
             moveVelocity += Vector3.up * velocity;
         }
         else if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow))
         {
             moveVelocity -= Vector3.up * velocity;
         }
         if (moveVelocity != Vector3.zero)
         {
             _CacheTransform.position += moveVelocity * Time.deltaTime;
         }
     }
}


大家可以看到在Update里面,是怎么从池中取数据的。
 

至此,对象池从定义到实现到调用基本都讲完了。
项目中还有控制雷和子弹的类的,大家有兴趣就自己去翻翻咯。

是不是觉得一个对象池还是挺简单的,这。。怪我咯~~
最后大家有不懂的再讨论就OK啦。
然后可运行文件是免费下载的。工程是要蛮牛币的,大家觉得好就多支持!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值