├── .github
└── FUNDING.yml
├── .gitignore
├── CHANGELOG.md
├── CHANGELOG.md.meta
├── LICENSE.md
├── LICENSE.md.meta
├── README.md
├── README.md.meta
├── Source.meta
├── Source
├── AutoPool.cs
├── AutoPool.cs.meta
├── Demo.meta
├── Demo
│ ├── DemoScene.unity
│ ├── DemoScene.unity.meta
│ ├── Pools.meta
│ ├── Pools
│ │ ├── DeathFXPool.asset
│ │ ├── DeathFXPool.asset.meta
│ │ ├── TriggeredPool.asset
│ │ └── TriggeredPool.asset.meta
│ ├── Prefabs.meta
│ ├── Prefabs
│ │ ├── DeathFX.prefab
│ │ ├── DeathFX.prefab.meta
│ │ ├── TriggerCube.prefab
│ │ └── TriggerCube.prefab.meta
│ ├── QFSW.MOP2.Demo.asmdef
│ ├── QFSW.MOP2.Demo.asmdef.meta
│ ├── Scripts.meta
│ └── Scripts
│ │ ├── ReleaseOnCollision.cs
│ │ ├── ReleaseOnCollision.cs.meta
│ │ ├── TriggerSpawner.cs
│ │ └── TriggerSpawner.cs.meta
├── Editor.meta
├── Editor
│ ├── EditorHelpers.cs
│ ├── EditorHelpers.cs.meta
│ ├── MOPInspectorBase.cs
│ ├── MOPInspectorBase.cs.meta
│ ├── MasterObjectPoolerInspector.cs
│ ├── MasterObjectPoolerInspector.cs.meta
│ ├── ObjectPoolInspector.cs
│ ├── ObjectPoolInspector.cs.meta
│ ├── ObjectPoolPostProcessor.cs
│ ├── ObjectPoolPostProcessor.cs.meta
│ ├── QFSW.MOP2.Editor.asmdef
│ └── QFSW.MOP2.Editor.asmdef.meta
├── IPoolable.cs
├── IPoolable.cs.meta
├── MasterObjectPooler.cs
├── MasterObjectPooler.cs.meta
├── ObjectPool.cs
├── ObjectPool.cs.meta
├── PoolableMonoBehaviour.cs
├── PoolableMonoBehaviour.cs.meta
├── PopulateMethod.cs
├── PopulateMethod.cs.meta
├── QFSW.MOP2.asmdef
├── QFSW.MOP2.asmdef.meta
├── Textures.meta
└── Textures
│ ├── Banner.png
│ ├── Banner.png.meta
│ ├── BannerCutout.png
│ ├── BannerCutout.png.meta
│ ├── Pool.png
│ └── Pool.png.meta
├── package.json
└── package.json.meta
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: QFSW
2 | patreon: QFSW
3 | custom: paypal.me/QFSW
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.blend[1-9]
2 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | V1.0.3
2 | Addition 0002: Scale of objects is now properly reset by the pool
3 | Change 0001: Support for legacy .NET 3.5 has been dropped
4 |
5 | V1.0.2
6 | Bug Fix 0001: Fixed MasterObjectPooler.Destroy
7 |
8 | V1.0.1
9 | Addition 0001: Added GetAllActiveObjects to ObjectPool and MasterObjectPooler
10 |
11 | V1.0.0
12 | Initial release
--------------------------------------------------------------------------------
/CHANGELOG.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4b52b062418dde844bce68fe98ffba5b
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 QFSW
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/LICENSE.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8d8aa9c49a0d6d1428f4ae8776c3b80d
3 | DefaultImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Master Object Pooler 2 is a high performance, flexible and easy to use object pooling solution that can fit into any Unity project.
11 |
12 | [Full Documentation and API Reference](https://www.qfsw.co.uk/docs/MOP2)
13 |
14 | [Unity Asset Store](https://assetstore.unity.com/packages/tools/utilities/master-object-pooler-2-146525)
15 |
16 | ### Getting Started
17 |
18 | In order to get started, create an `ObjectPool` for your desired object.
19 |
20 | - Use `Create -> Master Object Pooler 2 -> Object Pool` to create it at edit time
21 | - Use `ObjectPool.CreateInstance()` to create one at runtime
22 |
23 | Once you have an `ObjectPool`, use `pool.GetObject()` and `pool.Release()` in place of all `Instantiate` and `Destroy` calls. This means objects will be recycled through the pool, reducing GC and greatly improving efficiency.
24 |
25 | Using a `MasterObjectPooler` can greatly ease the use of managing multiple pools. Pools can be added to it either in the inspector, or at runtime with `AddPool`. Once added to the pool, you can use all of the normal pool functions (or retrieve the pool) with a string reference.
26 |
27 | ### Extras
28 |
29 | `AutoPool` is a script that can be added to any object to make it automatically pool itself after a surpassed amount of time. The parent pool is injected to the pool via the `IPoolable` component, so you do not need to do it yourself
30 |
31 | You can make your own scripts that use the parent pool by implementing `IPoolable`
32 |
33 | Any script deriving from or using `PoolableMonoBehaviour` will have a new `Release` method, allowing you to release the object without needing a reference to its pool
34 |
35 | MOP2 also provides `GetObjectComponent`, a GC free method of getting the object component. This should be used whenever possible to improve efficiency.
36 |
37 | ### Installing via Package Manager
38 | #### 2019.3+
39 | Starting with Unity 2019.3, the package manager UI has support for git packages
40 |
41 | Click the `+` to add a new git package and add `https://github.com/QFSW/MasterObjectPooler2.git` as the source
42 |
43 | #### 2018.3 - 2019.2
44 | To install via package manager, add the file `Packages/manifest.json` and add the following line to the `"dependencies"`
45 | ```
46 | "com.qfsw.mop2": "https://github.com/QFSW/MasterObjectPooler2.git"
47 | ```
48 | Your file should end up like this
49 | ```
50 | {
51 | "dependencies": {
52 | "com.qfsw.mop2": "https://github.com/QFSW/MasterObjectPooler2.git",
53 | ...
54 | },
55 | }
56 | ```
57 |
58 | #### Install via OpenUPM
59 | The package is available on the [openupm registry](https://openupm.com). It's recommended to install it via [openupm-cli](https://github.com/openupm/openupm-cli).
60 |
61 | ```
62 | openupm add com.qfsw.mop2
63 | ```
64 |
65 | Thanks to [`caprapaul`](https://github.com/caprapaul) for logo work.
66 |
--------------------------------------------------------------------------------
/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c99400b1d9040774dac36259ed0ed45f
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Source.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9fe5e859fef53264087690e8591abe68
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Source/AutoPool.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace QFSW.MOP2
4 | {
5 | ///
6 | /// Automatically releases an object after the specified amount of time has surpassed.
7 | ///
8 | [DisallowMultipleComponent]
9 | public class AutoPool : PoolableMonoBehaviour
10 | {
11 | [Tooltip("The duration of time to wait before releasing the object to the pool.")]
12 | [SerializeField] private float _poolTimer = 1;
13 |
14 | [Tooltip("Whether to use scaled or unscaled time.")]
15 | [SerializeField] private bool _scaledTime = true;
16 |
17 | private float _elapsedTime;
18 |
19 | private void OnEnable()
20 | {
21 | _elapsedTime = 0;
22 | }
23 |
24 | private void Update()
25 | {
26 | if (_scaledTime) { _elapsedTime += Time.deltaTime; }
27 | else { _elapsedTime += Time.unscaledDeltaTime; }
28 |
29 | if (_elapsedTime > _poolTimer && PoolReady) { Release(); }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Source/AutoPool.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c1d21e76924a1114e9b72179a8c1bde7
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Source/Demo.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: cb6b8dfacb5303b4c998c664aab97d7b
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Source/Demo/DemoScene.unity:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!29 &1
4 | OcclusionCullingSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 2
7 | m_OcclusionBakeSettings:
8 | smallestOccluder: 5
9 | smallestHole: 0.25
10 | backfaceThreshold: 100
11 | m_SceneGUID: 00000000000000000000000000000000
12 | m_OcclusionCullingData: {fileID: 0}
13 | --- !u!104 &2
14 | RenderSettings:
15 | m_ObjectHideFlags: 0
16 | serializedVersion: 9
17 | m_Fog: 0
18 | m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
19 | m_FogMode: 3
20 | m_FogDensity: 0.01
21 | m_LinearFogStart: 0
22 | m_LinearFogEnd: 300
23 | m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
24 | m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
25 | m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
26 | m_AmbientIntensity: 1
27 | m_AmbientMode: 0
28 | m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
29 | m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
30 | m_HaloStrength: 0.5
31 | m_FlareStrength: 1
32 | m_FlareFadeSpeed: 3
33 | m_HaloTexture: {fileID: 0}
34 | m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
35 | m_DefaultReflectionMode: 0
36 | m_DefaultReflectionResolution: 128
37 | m_ReflectionBounces: 1
38 | m_ReflectionIntensity: 1
39 | m_CustomReflection: {fileID: 0}
40 | m_Sun: {fileID: 0}
41 | m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
42 | m_UseRadianceAmbientProbe: 0
43 | --- !u!157 &3
44 | LightmapSettings:
45 | m_ObjectHideFlags: 0
46 | serializedVersion: 11
47 | m_GIWorkflowMode: 1
48 | m_GISettings:
49 | serializedVersion: 2
50 | m_BounceScale: 1
51 | m_IndirectOutputScale: 1
52 | m_AlbedoBoost: 1
53 | m_EnvironmentLightingMode: 0
54 | m_EnableBakedLightmaps: 1
55 | m_EnableRealtimeLightmaps: 1
56 | m_LightmapEditorSettings:
57 | serializedVersion: 12
58 | m_Resolution: 2
59 | m_BakeResolution: 40
60 | m_AtlasSize: 1024
61 | m_AO: 0
62 | m_AOMaxDistance: 1
63 | m_CompAOExponent: 1
64 | m_CompAOExponentDirect: 0
65 | m_ExtractAmbientOcclusion: 0
66 | m_Padding: 2
67 | m_LightmapParameters: {fileID: 0}
68 | m_LightmapsBakeMode: 1
69 | m_TextureCompression: 1
70 | m_FinalGather: 0
71 | m_FinalGatherFiltering: 1
72 | m_FinalGatherRayCount: 256
73 | m_ReflectionCompression: 2
74 | m_MixedBakeMode: 2
75 | m_BakeBackend: 1
76 | m_PVRSampling: 1
77 | m_PVRDirectSampleCount: 32
78 | m_PVRSampleCount: 512
79 | m_PVRBounces: 2
80 | m_PVREnvironmentSampleCount: 256
81 | m_PVREnvironmentReferencePointCount: 2048
82 | m_PVRFilteringMode: 1
83 | m_PVRDenoiserTypeDirect: 1
84 | m_PVRDenoiserTypeIndirect: 1
85 | m_PVRDenoiserTypeAO: 1
86 | m_PVRFilterTypeDirect: 0
87 | m_PVRFilterTypeIndirect: 0
88 | m_PVRFilterTypeAO: 0
89 | m_PVREnvironmentMIS: 1
90 | m_PVRCulling: 1
91 | m_PVRFilteringGaussRadiusDirect: 1
92 | m_PVRFilteringGaussRadiusIndirect: 5
93 | m_PVRFilteringGaussRadiusAO: 2
94 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5
95 | m_PVRFilteringAtrousPositionSigmaIndirect: 2
96 | m_PVRFilteringAtrousPositionSigmaAO: 1
97 | m_ShowResolutionOverlay: 1
98 | m_ExportTrainingData: 0
99 | m_LightingDataAsset: {fileID: 0}
100 | m_UseShadowmask: 1
101 | --- !u!196 &4
102 | NavMeshSettings:
103 | serializedVersion: 2
104 | m_ObjectHideFlags: 0
105 | m_BuildSettings:
106 | serializedVersion: 2
107 | agentTypeID: 0
108 | agentRadius: 0.5
109 | agentHeight: 2
110 | agentSlope: 45
111 | agentClimb: 0.4
112 | ledgeDropHeight: 0
113 | maxJumpAcrossDistance: 0
114 | minRegionArea: 2
115 | manualCellSize: 0
116 | cellSize: 0.16666667
117 | manualTileSize: 0
118 | tileSize: 256
119 | accuratePlacement: 0
120 | debug:
121 | m_Flags: 0
122 | m_NavMeshData: {fileID: 0}
123 | --- !u!1 &258284261
124 | GameObject:
125 | m_ObjectHideFlags: 0
126 | m_CorrespondingSourceObject: {fileID: 0}
127 | m_PrefabInstance: {fileID: 0}
128 | m_PrefabAsset: {fileID: 0}
129 | serializedVersion: 6
130 | m_Component:
131 | - component: {fileID: 258284264}
132 | - component: {fileID: 258284263}
133 | - component: {fileID: 258284262}
134 | m_Layer: 0
135 | m_Name: EventSystem
136 | m_TagString: Untagged
137 | m_Icon: {fileID: 0}
138 | m_NavMeshLayer: 0
139 | m_StaticEditorFlags: 0
140 | m_IsActive: 1
141 | --- !u!114 &258284262
142 | MonoBehaviour:
143 | m_ObjectHideFlags: 0
144 | m_CorrespondingSourceObject: {fileID: 0}
145 | m_PrefabInstance: {fileID: 0}
146 | m_PrefabAsset: {fileID: 0}
147 | m_GameObject: {fileID: 258284261}
148 | m_Enabled: 1
149 | m_EditorHideFlags: 0
150 | m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, type: 3}
151 | m_Name:
152 | m_EditorClassIdentifier:
153 | m_HorizontalAxis: Horizontal
154 | m_VerticalAxis: Vertical
155 | m_SubmitButton: Submit
156 | m_CancelButton: Cancel
157 | m_InputActionsPerSecond: 10
158 | m_RepeatDelay: 0.5
159 | m_ForceModuleActive: 0
160 | --- !u!114 &258284263
161 | MonoBehaviour:
162 | m_ObjectHideFlags: 0
163 | m_CorrespondingSourceObject: {fileID: 0}
164 | m_PrefabInstance: {fileID: 0}
165 | m_PrefabAsset: {fileID: 0}
166 | m_GameObject: {fileID: 258284261}
167 | m_Enabled: 1
168 | m_EditorHideFlags: 0
169 | m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3}
170 | m_Name:
171 | m_EditorClassIdentifier:
172 | m_FirstSelected: {fileID: 0}
173 | m_sendNavigationEvents: 1
174 | m_DragThreshold: 10
175 | --- !u!4 &258284264
176 | Transform:
177 | m_ObjectHideFlags: 0
178 | m_CorrespondingSourceObject: {fileID: 0}
179 | m_PrefabInstance: {fileID: 0}
180 | m_PrefabAsset: {fileID: 0}
181 | m_GameObject: {fileID: 258284261}
182 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
183 | m_LocalPosition: {x: 0, y: 0, z: 0}
184 | m_LocalScale: {x: 1, y: 1, z: 1}
185 | m_Children: []
186 | m_Father: {fileID: 0}
187 | m_RootOrder: 5
188 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
189 | --- !u!1 &319436628
190 | GameObject:
191 | m_ObjectHideFlags: 0
192 | m_CorrespondingSourceObject: {fileID: 0}
193 | m_PrefabInstance: {fileID: 0}
194 | m_PrefabAsset: {fileID: 0}
195 | serializedVersion: 6
196 | m_Component:
197 | - component: {fileID: 319436630}
198 | - component: {fileID: 319436629}
199 | m_Layer: 0
200 | m_Name: MOP
201 | m_TagString: Untagged
202 | m_Icon: {fileID: 0}
203 | m_NavMeshLayer: 0
204 | m_StaticEditorFlags: 0
205 | m_IsActive: 1
206 | --- !u!114 &319436629
207 | MonoBehaviour:
208 | m_ObjectHideFlags: 0
209 | m_CorrespondingSourceObject: {fileID: 0}
210 | m_PrefabInstance: {fileID: 0}
211 | m_PrefabAsset: {fileID: 0}
212 | m_GameObject: {fileID: 319436628}
213 | m_Enabled: 1
214 | m_EditorHideFlags: 0
215 | m_Script: {fileID: 11500000, guid: ae7d75d4e54c16b42b11bb89b17dc809, type: 3}
216 | m_Name:
217 | m_EditorClassIdentifier:
218 | _pools:
219 | - {fileID: 11400000, guid: fda3ff401ed679a42b9bfa77cd0e5e9e, type: 2}
220 | --- !u!4 &319436630
221 | Transform:
222 | m_ObjectHideFlags: 0
223 | m_CorrespondingSourceObject: {fileID: 0}
224 | m_PrefabInstance: {fileID: 0}
225 | m_PrefabAsset: {fileID: 0}
226 | m_GameObject: {fileID: 319436628}
227 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
228 | m_LocalPosition: {x: -1.3635218, y: -1.9983577, z: -1.1701345}
229 | m_LocalScale: {x: 1, y: 1, z: 1}
230 | m_Children: []
231 | m_Father: {fileID: 0}
232 | m_RootOrder: 4
233 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
234 | --- !u!1 &565502365
235 | GameObject:
236 | m_ObjectHideFlags: 0
237 | m_CorrespondingSourceObject: {fileID: 0}
238 | m_PrefabInstance: {fileID: 0}
239 | m_PrefabAsset: {fileID: 0}
240 | serializedVersion: 6
241 | m_Component:
242 | - component: {fileID: 565502366}
243 | - component: {fileID: 565502367}
244 | m_Layer: 0
245 | m_Name: TriggerSpawner
246 | m_TagString: Untagged
247 | m_Icon: {fileID: 0}
248 | m_NavMeshLayer: 0
249 | m_StaticEditorFlags: 0
250 | m_IsActive: 1
251 | --- !u!4 &565502366
252 | Transform:
253 | m_ObjectHideFlags: 0
254 | m_CorrespondingSourceObject: {fileID: 0}
255 | m_PrefabInstance: {fileID: 0}
256 | m_PrefabAsset: {fileID: 0}
257 | m_GameObject: {fileID: 565502365}
258 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
259 | m_LocalPosition: {x: 0, y: 4, z: 0}
260 | m_LocalScale: {x: 1, y: 1, z: 1}
261 | m_Children: []
262 | m_Father: {fileID: 0}
263 | m_RootOrder: 3
264 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
265 | --- !u!114 &565502367
266 | MonoBehaviour:
267 | m_ObjectHideFlags: 0
268 | m_CorrespondingSourceObject: {fileID: 0}
269 | m_PrefabInstance: {fileID: 0}
270 | m_PrefabAsset: {fileID: 0}
271 | m_GameObject: {fileID: 565502365}
272 | m_Enabled: 1
273 | m_EditorHideFlags: 0
274 | m_Script: {fileID: 11500000, guid: b15da39ad248b4348b731fd31367dd7c, type: 3}
275 | m_Name:
276 | m_EditorClassIdentifier:
277 | _triggerPool: {fileID: 11400000, guid: e683e348e50fc3b469897aaad3d5c342, type: 2}
278 | _spawnRate: 8
279 | _spawnSpeed: 3
280 | _spawnAngularSpeed: 6
281 | --- !u!1 &1183111172
282 | GameObject:
283 | m_ObjectHideFlags: 0
284 | m_CorrespondingSourceObject: {fileID: 0}
285 | m_PrefabInstance: {fileID: 0}
286 | m_PrefabAsset: {fileID: 0}
287 | serializedVersion: 6
288 | m_Component:
289 | - component: {fileID: 1183111176}
290 | - component: {fileID: 1183111175}
291 | - component: {fileID: 1183111174}
292 | - component: {fileID: 1183111173}
293 | m_Layer: 0
294 | m_Name: Floor
295 | m_TagString: Untagged
296 | m_Icon: {fileID: 0}
297 | m_NavMeshLayer: 0
298 | m_StaticEditorFlags: 0
299 | m_IsActive: 1
300 | --- !u!65 &1183111173
301 | BoxCollider:
302 | m_ObjectHideFlags: 0
303 | m_CorrespondingSourceObject: {fileID: 0}
304 | m_PrefabInstance: {fileID: 0}
305 | m_PrefabAsset: {fileID: 0}
306 | m_GameObject: {fileID: 1183111172}
307 | m_Material: {fileID: 0}
308 | m_IsTrigger: 0
309 | m_Enabled: 1
310 | serializedVersion: 2
311 | m_Size: {x: 1, y: 1, z: 1}
312 | m_Center: {x: 0, y: 0, z: 0}
313 | --- !u!23 &1183111174
314 | MeshRenderer:
315 | m_ObjectHideFlags: 0
316 | m_CorrespondingSourceObject: {fileID: 0}
317 | m_PrefabInstance: {fileID: 0}
318 | m_PrefabAsset: {fileID: 0}
319 | m_GameObject: {fileID: 1183111172}
320 | m_Enabled: 1
321 | m_CastShadows: 1
322 | m_ReceiveShadows: 1
323 | m_DynamicOccludee: 1
324 | m_MotionVectors: 1
325 | m_LightProbeUsage: 1
326 | m_ReflectionProbeUsage: 1
327 | m_RenderingLayerMask: 1
328 | m_RendererPriority: 0
329 | m_Materials:
330 | - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
331 | m_StaticBatchInfo:
332 | firstSubMesh: 0
333 | subMeshCount: 0
334 | m_StaticBatchRoot: {fileID: 0}
335 | m_ProbeAnchor: {fileID: 0}
336 | m_LightProbeVolumeOverride: {fileID: 0}
337 | m_ScaleInLightmap: 1
338 | m_PreserveUVs: 0
339 | m_IgnoreNormalsForChartDetection: 0
340 | m_ImportantGI: 0
341 | m_StitchLightmapSeams: 1
342 | m_SelectedEditorRenderState: 3
343 | m_MinimumChartSize: 4
344 | m_AutoUVMaxDistance: 0.5
345 | m_AutoUVMaxAngle: 89
346 | m_LightmapParameters: {fileID: 0}
347 | m_SortingLayerID: 0
348 | m_SortingLayer: 0
349 | m_SortingOrder: 0
350 | --- !u!33 &1183111175
351 | MeshFilter:
352 | m_ObjectHideFlags: 0
353 | m_CorrespondingSourceObject: {fileID: 0}
354 | m_PrefabInstance: {fileID: 0}
355 | m_PrefabAsset: {fileID: 0}
356 | m_GameObject: {fileID: 1183111172}
357 | m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
358 | --- !u!4 &1183111176
359 | Transform:
360 | m_ObjectHideFlags: 0
361 | m_CorrespondingSourceObject: {fileID: 0}
362 | m_PrefabInstance: {fileID: 0}
363 | m_PrefabAsset: {fileID: 0}
364 | m_GameObject: {fileID: 1183111172}
365 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
366 | m_LocalPosition: {x: 0, y: 0, z: 0}
367 | m_LocalScale: {x: 30, y: 1, z: 30}
368 | m_Children: []
369 | m_Father: {fileID: 0}
370 | m_RootOrder: 2
371 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
372 | --- !u!1 &1568048506
373 | GameObject:
374 | m_ObjectHideFlags: 0
375 | m_CorrespondingSourceObject: {fileID: 0}
376 | m_PrefabInstance: {fileID: 0}
377 | m_PrefabAsset: {fileID: 0}
378 | serializedVersion: 6
379 | m_Component:
380 | - component: {fileID: 1568048508}
381 | - component: {fileID: 1568048507}
382 | m_Layer: 0
383 | m_Name: Directional Light
384 | m_TagString: Untagged
385 | m_Icon: {fileID: 0}
386 | m_NavMeshLayer: 0
387 | m_StaticEditorFlags: 0
388 | m_IsActive: 1
389 | --- !u!108 &1568048507
390 | Light:
391 | m_ObjectHideFlags: 0
392 | m_CorrespondingSourceObject: {fileID: 0}
393 | m_PrefabInstance: {fileID: 0}
394 | m_PrefabAsset: {fileID: 0}
395 | m_GameObject: {fileID: 1568048506}
396 | m_Enabled: 1
397 | serializedVersion: 9
398 | m_Type: 1
399 | m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
400 | m_Intensity: 1
401 | m_Range: 10
402 | m_SpotAngle: 30
403 | m_InnerSpotAngle: 21.80208
404 | m_CookieSize: 10
405 | m_Shadows:
406 | m_Type: 2
407 | m_Resolution: -1
408 | m_CustomResolution: -1
409 | m_Strength: 1
410 | m_Bias: 0.05
411 | m_NormalBias: 0.4
412 | m_NearPlane: 0.2
413 | m_CullingMatrixOverride:
414 | e00: 1
415 | e01: 0
416 | e02: 0
417 | e03: 0
418 | e10: 0
419 | e11: 1
420 | e12: 0
421 | e13: 0
422 | e20: 0
423 | e21: 0
424 | e22: 1
425 | e23: 0
426 | e30: 0
427 | e31: 0
428 | e32: 0
429 | e33: 1
430 | m_UseCullingMatrixOverride: 0
431 | m_Cookie: {fileID: 0}
432 | m_DrawHalo: 0
433 | m_Flare: {fileID: 0}
434 | m_RenderMode: 0
435 | m_CullingMask:
436 | serializedVersion: 2
437 | m_Bits: 4294967295
438 | m_RenderingLayerMask: 1
439 | m_Lightmapping: 4
440 | m_LightShadowCasterMode: 0
441 | m_AreaSize: {x: 1, y: 1}
442 | m_BounceIntensity: 1
443 | m_ColorTemperature: 6570
444 | m_UseColorTemperature: 0
445 | m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
446 | m_UseBoundingSphereOverride: 0
447 | m_ShadowRadius: 0
448 | m_ShadowAngle: 0
449 | --- !u!4 &1568048508
450 | Transform:
451 | m_ObjectHideFlags: 0
452 | m_CorrespondingSourceObject: {fileID: 0}
453 | m_PrefabInstance: {fileID: 0}
454 | m_PrefabAsset: {fileID: 0}
455 | m_GameObject: {fileID: 1568048506}
456 | m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
457 | m_LocalPosition: {x: 0, y: 3, z: 0}
458 | m_LocalScale: {x: 1, y: 1, z: 1}
459 | m_Children: []
460 | m_Father: {fileID: 0}
461 | m_RootOrder: 1
462 | m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
463 | --- !u!1 &1761232578
464 | GameObject:
465 | m_ObjectHideFlags: 0
466 | m_CorrespondingSourceObject: {fileID: 0}
467 | m_PrefabInstance: {fileID: 0}
468 | m_PrefabAsset: {fileID: 0}
469 | serializedVersion: 6
470 | m_Component:
471 | - component: {fileID: 1761232581}
472 | - component: {fileID: 1761232580}
473 | - component: {fileID: 1761232579}
474 | m_Layer: 0
475 | m_Name: Main Camera
476 | m_TagString: MainCamera
477 | m_Icon: {fileID: 0}
478 | m_NavMeshLayer: 0
479 | m_StaticEditorFlags: 0
480 | m_IsActive: 1
481 | --- !u!81 &1761232579
482 | AudioListener:
483 | m_ObjectHideFlags: 0
484 | m_CorrespondingSourceObject: {fileID: 0}
485 | m_PrefabInstance: {fileID: 0}
486 | m_PrefabAsset: {fileID: 0}
487 | m_GameObject: {fileID: 1761232578}
488 | m_Enabled: 1
489 | --- !u!20 &1761232580
490 | Camera:
491 | m_ObjectHideFlags: 0
492 | m_CorrespondingSourceObject: {fileID: 0}
493 | m_PrefabInstance: {fileID: 0}
494 | m_PrefabAsset: {fileID: 0}
495 | m_GameObject: {fileID: 1761232578}
496 | m_Enabled: 1
497 | serializedVersion: 2
498 | m_ClearFlags: 2
499 | m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
500 | m_projectionMatrixMode: 1
501 | m_GateFitMode: 2
502 | m_FOVAxisMode: 0
503 | m_SensorSize: {x: 36, y: 24}
504 | m_LensShift: {x: 0, y: 0}
505 | m_FocalLength: 50
506 | m_NormalizedViewPortRect:
507 | serializedVersion: 2
508 | x: 0
509 | y: 0
510 | width: 1
511 | height: 1
512 | near clip plane: 0.3
513 | far clip plane: 1000
514 | field of view: 60
515 | orthographic: 0
516 | orthographic size: 5
517 | m_Depth: -1
518 | m_CullingMask:
519 | serializedVersion: 2
520 | m_Bits: 4294967295
521 | m_RenderingPath: -1
522 | m_TargetTexture: {fileID: 0}
523 | m_TargetDisplay: 0
524 | m_TargetEye: 3
525 | m_HDR: 1
526 | m_AllowMSAA: 1
527 | m_AllowDynamicResolution: 0
528 | m_ForceIntoRT: 0
529 | m_OcclusionCulling: 1
530 | m_StereoConvergence: 10
531 | m_StereoSeparation: 0.022
532 | --- !u!4 &1761232581
533 | Transform:
534 | m_ObjectHideFlags: 0
535 | m_CorrespondingSourceObject: {fileID: 0}
536 | m_PrefabInstance: {fileID: 0}
537 | m_PrefabAsset: {fileID: 0}
538 | m_GameObject: {fileID: 1761232578}
539 | m_LocalRotation: {x: 0.084186025, y: 0.25783423, z: -0.02255758, w: 0.9622502}
540 | m_LocalPosition: {x: -5.3, y: 2.52, z: -3.69}
541 | m_LocalScale: {x: 1, y: 1, z: 1}
542 | m_Children: []
543 | m_Father: {fileID: 0}
544 | m_RootOrder: 0
545 | m_LocalEulerAnglesHint: {x: 10, y: 30, z: 0}
546 |
--------------------------------------------------------------------------------
/Source/Demo/DemoScene.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1c8dfb90e965eda48ab238ea9ffb482d
3 | DefaultImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Source/Demo/Pools.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: cf62e450cd52c594fae99d9eb05978aa
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Source/Demo/Pools/DeathFXPool.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &11400000
4 | MonoBehaviour:
5 | m_ObjectHideFlags: 0
6 | m_CorrespondingSourceObject: {fileID: 0}
7 | m_PrefabInstance: {fileID: 0}
8 | m_PrefabAsset: {fileID: 0}
9 | m_GameObject: {fileID: 0}
10 | m_Enabled: 1
11 | m_EditorHideFlags: 0
12 | m_Script: {fileID: 11500000, guid: 5ad40add42ecce646952aaa9475056c8, type: 3}
13 | m_Name: DeathFXPool
14 | m_EditorClassIdentifier:
15 | _name: DeathFX
16 | _template: {fileID: 3826700234699233003, guid: fe040d82f7e1e9d499f8ac16d09a9489,
17 | type: 3}
18 | _defaultSize: 5
19 | _maxSize: -1
20 | _incrementalInstanceNames: 0
21 |
--------------------------------------------------------------------------------
/Source/Demo/Pools/DeathFXPool.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fda3ff401ed679a42b9bfa77cd0e5e9e
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 11400000
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Source/Demo/Pools/TriggeredPool.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &11400000
4 | MonoBehaviour:
5 | m_ObjectHideFlags: 0
6 | m_CorrespondingSourceObject: {fileID: 0}
7 | m_PrefabInstance: {fileID: 0}
8 | m_PrefabAsset: {fileID: 0}
9 | m_GameObject: {fileID: 0}
10 | m_Enabled: 1
11 | m_EditorHideFlags: 0
12 | m_Script: {fileID: 11500000, guid: 5ad40add42ecce646952aaa9475056c8, type: 3}
13 | m_Name: TriggeredPool
14 | m_EditorClassIdentifier:
15 | _name: Triggered
16 | _template: {fileID: 1761364006608128336, guid: 31b9b4976e28c8d4f8da076b3cc39ae6,
17 | type: 3}
18 | _defaultSize: 4
19 | _maxSize: -1
20 | _incrementalInstanceNames: 1
21 |
--------------------------------------------------------------------------------
/Source/Demo/Pools/TriggeredPool.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e683e348e50fc3b469897aaad3d5c342
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 11400000
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Source/Demo/Prefabs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 13799146d655c7e45bbec54b42625657
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Source/Demo/Prefabs/DeathFX.prefab.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fe040d82f7e1e9d499f8ac16d09a9489
3 | PrefabImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Source/Demo/Prefabs/TriggerCube.prefab:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!1 &1761364006608128336
4 | GameObject:
5 | m_ObjectHideFlags: 0
6 | m_CorrespondingSourceObject: {fileID: 0}
7 | m_PrefabInstance: {fileID: 0}
8 | m_PrefabAsset: {fileID: 0}
9 | serializedVersion: 6
10 | m_Component:
11 | - component: {fileID: 1761364006608128332}
12 | - component: {fileID: 1761364006608128333}
13 | - component: {fileID: 1761364006608128334}
14 | - component: {fileID: 1761364006608128335}
15 | - component: {fileID: 1761364006608128330}
16 | - component: {fileID: 1761364006608128331}
17 | m_Layer: 2
18 | m_Name: TriggerCube
19 | m_TagString: Untagged
20 | m_Icon: {fileID: 0}
21 | m_NavMeshLayer: 0
22 | m_StaticEditorFlags: 0
23 | m_IsActive: 1
24 | --- !u!4 &1761364006608128332
25 | Transform:
26 | m_ObjectHideFlags: 0
27 | m_CorrespondingSourceObject: {fileID: 0}
28 | m_PrefabInstance: {fileID: 0}
29 | m_PrefabAsset: {fileID: 0}
30 | m_GameObject: {fileID: 1761364006608128336}
31 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
32 | m_LocalPosition: {x: -0.7161716, y: 1.1577829, z: 0}
33 | m_LocalScale: {x: 0.25, y: 0.25, z: 0.25}
34 | m_Children: []
35 | m_Father: {fileID: 0}
36 | m_RootOrder: 0
37 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
38 | --- !u!33 &1761364006608128333
39 | MeshFilter:
40 | m_ObjectHideFlags: 0
41 | m_CorrespondingSourceObject: {fileID: 0}
42 | m_PrefabInstance: {fileID: 0}
43 | m_PrefabAsset: {fileID: 0}
44 | m_GameObject: {fileID: 1761364006608128336}
45 | m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
46 | --- !u!23 &1761364006608128334
47 | MeshRenderer:
48 | m_ObjectHideFlags: 0
49 | m_CorrespondingSourceObject: {fileID: 0}
50 | m_PrefabInstance: {fileID: 0}
51 | m_PrefabAsset: {fileID: 0}
52 | m_GameObject: {fileID: 1761364006608128336}
53 | m_Enabled: 1
54 | m_CastShadows: 1
55 | m_ReceiveShadows: 1
56 | m_DynamicOccludee: 1
57 | m_MotionVectors: 1
58 | m_LightProbeUsage: 1
59 | m_ReflectionProbeUsage: 1
60 | m_RenderingLayerMask: 1
61 | m_RendererPriority: 0
62 | m_Materials:
63 | - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
64 | m_StaticBatchInfo:
65 | firstSubMesh: 0
66 | subMeshCount: 0
67 | m_StaticBatchRoot: {fileID: 0}
68 | m_ProbeAnchor: {fileID: 0}
69 | m_LightProbeVolumeOverride: {fileID: 0}
70 | m_ScaleInLightmap: 1
71 | m_PreserveUVs: 0
72 | m_IgnoreNormalsForChartDetection: 0
73 | m_ImportantGI: 0
74 | m_StitchLightmapSeams: 1
75 | m_SelectedEditorRenderState: 3
76 | m_MinimumChartSize: 4
77 | m_AutoUVMaxDistance: 0.5
78 | m_AutoUVMaxAngle: 89
79 | m_LightmapParameters: {fileID: 0}
80 | m_SortingLayerID: 0
81 | m_SortingLayer: 0
82 | m_SortingOrder: 0
83 | --- !u!65 &1761364006608128335
84 | BoxCollider:
85 | m_ObjectHideFlags: 0
86 | m_CorrespondingSourceObject: {fileID: 0}
87 | m_PrefabInstance: {fileID: 0}
88 | m_PrefabAsset: {fileID: 0}
89 | m_GameObject: {fileID: 1761364006608128336}
90 | m_Material: {fileID: 0}
91 | m_IsTrigger: 0
92 | m_Enabled: 1
93 | serializedVersion: 2
94 | m_Size: {x: 1, y: 1, z: 1}
95 | m_Center: {x: 0, y: 0, z: 0}
96 | --- !u!54 &1761364006608128330
97 | Rigidbody:
98 | m_ObjectHideFlags: 0
99 | m_CorrespondingSourceObject: {fileID: 0}
100 | m_PrefabInstance: {fileID: 0}
101 | m_PrefabAsset: {fileID: 0}
102 | m_GameObject: {fileID: 1761364006608128336}
103 | serializedVersion: 2
104 | m_Mass: 1
105 | m_Drag: 0
106 | m_AngularDrag: 0.05
107 | m_UseGravity: 1
108 | m_IsKinematic: 0
109 | m_Interpolate: 0
110 | m_Constraints: 0
111 | m_CollisionDetection: 0
112 | --- !u!114 &1761364006608128331
113 | MonoBehaviour:
114 | m_ObjectHideFlags: 0
115 | m_CorrespondingSourceObject: {fileID: 0}
116 | m_PrefabInstance: {fileID: 0}
117 | m_PrefabAsset: {fileID: 0}
118 | m_GameObject: {fileID: 1761364006608128336}
119 | m_Enabled: 1
120 | m_EditorHideFlags: 0
121 | m_Script: {fileID: 11500000, guid: 6df570c2ded90594da9e95f6ce518553, type: 3}
122 | m_Name:
123 | m_EditorClassIdentifier:
124 | _parentPool: {fileID: 11400000, guid: e683e348e50fc3b469897aaad3d5c342, type: 2}
125 | _collisionLayer:
126 | serializedVersion: 2
127 | m_Bits: 1
128 | _deathFX: {fileID: 11400000, guid: fda3ff401ed679a42b9bfa77cd0e5e9e, type: 2}
129 |
--------------------------------------------------------------------------------
/Source/Demo/Prefabs/TriggerCube.prefab.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 31b9b4976e28c8d4f8da076b3cc39ae6
3 | PrefabImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Source/Demo/QFSW.MOP2.Demo.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "QFSW.MOP2.Demo",
3 | "references": [
4 | "QFSW.MOP2"
5 | ],
6 | "optionalUnityReferences": [],
7 | "includePlatforms": [],
8 | "excludePlatforms": [],
9 | "allowUnsafeCode": false,
10 | "overrideReferences": false,
11 | "precompiledReferences": [],
12 | "autoReferenced": true,
13 | "defineConstraints": []
14 | }
--------------------------------------------------------------------------------
/Source/Demo/QFSW.MOP2.Demo.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 486a1a47e7ab42b42b7d6a63fe61df55
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Source/Demo/Scripts.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c882f024cd3c20e4ea7c5ebb7097b222
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Source/Demo/Scripts/ReleaseOnCollision.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace QFSW.MOP2.Demo
4 | {
5 | [RequireComponent(typeof(Collider))]
6 | public class ReleaseOnCollision : PoolableMonoBehaviour
7 | {
8 | [SerializeField] private LayerMask _collisionLayer = 0;
9 | [SerializeField] private ObjectPool _deathFX = null;
10 |
11 | private void OnCollisionEnter(Collision collision)
12 | {
13 | if ((_collisionLayer.value & 1 << collision.gameObject.layer) != 0)
14 | {
15 | Release();
16 | if (_deathFX)
17 | {
18 | _deathFX.GetObject(transform.position);
19 | }
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Source/Demo/Scripts/ReleaseOnCollision.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6df570c2ded90594da9e95f6ce518553
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Source/Demo/Scripts/TriggerSpawner.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace QFSW.MOP2.Demo
4 | {
5 | public class TriggerSpawner : MonoBehaviour
6 | {
7 | [SerializeField] ObjectPool _triggerPool = null;
8 | [SerializeField] float _spawnRate = 2;
9 | [SerializeField] float _spawnSpeed = 3;
10 | [SerializeField] float _spawnAngularSpeed = 6;
11 |
12 | private bool ShouldSpawn => Time.time > _lastSpawned + 1 / _spawnRate;
13 |
14 | private float _lastSpawned;
15 |
16 | private void Start()
17 | {
18 | _triggerPool.Initialize();
19 | _triggerPool.ObjectParent.parent = transform;
20 | }
21 |
22 | private void Update()
23 | {
24 | if (ShouldSpawn)
25 | {
26 | _lastSpawned = Time.time;
27 | Rigidbody rb = _triggerPool.GetObjectComponent(transform.position);
28 | rb.angularVelocity = new Vector3(Random.Range(-1, 1), Random.Range(-1, 1), Random.Range(-1, 1)) * _spawnAngularSpeed;
29 | rb.velocity = new Vector3(Random.Range(-1, 1), Random.Range(-1, 1), Random.Range(-1, 1)) * _spawnSpeed;
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Source/Demo/Scripts/TriggerSpawner.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b15da39ad248b4348b731fd31367dd7c
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Source/Editor.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e70e922606f708648b8c4670db309c10
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Source/Editor/EditorHelpers.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | namespace QFSW.MOP2.Editor
6 | {
7 | public static class EditorHelpers
8 | {
9 | public static void DrawBanner(Texture2D banner, float sizeMultiplier = 1f)
10 | {
11 | if (banner)
12 | {
13 | sizeMultiplier = Mathf.Clamp01(sizeMultiplier);
14 |
15 | Rect bannerRect = GUILayoutUtility.GetRect(0.0f, 0.0f);
16 | bannerRect.height = Screen.width * banner.height / banner.width;
17 | bannerRect.x += bannerRect.width * (1 - sizeMultiplier) / 2;
18 | bannerRect.width *= sizeMultiplier;
19 | bannerRect.height *= sizeMultiplier;
20 |
21 | GUILayout.Space(bannerRect.height);
22 | GUI.Label(bannerRect, banner);
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Source/Editor/EditorHelpers.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 36bca9ccd1104134ba547ed7558b57ee
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Source/Editor/MOPInspectorBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Linq;
4 | using UnityEditor;
5 | using UnityEngine;
6 |
7 | namespace QFSW.MOP2.Editor
8 | {
9 | public class MOPInspectorBase : UnityEditor.Editor
10 | {
11 | const string ROOT_PATH = "Source";
12 | protected string BannerName => "Banner.png";
13 | protected Texture2D Banner { get; private set; }
14 |
15 | protected T LoadAssetInSource(string assetName, string root) where T : UnityEngine.Object
16 | {
17 | MonoScript src = MonoScript.FromScriptableObject(this);
18 | string srcPath = AssetDatabase.GetAssetPath(src);
19 | string dirPath = Path.GetDirectoryName(srcPath);
20 | string[] pathParts = dirPath.Split(new string[] { root }, StringSplitOptions.None);
21 | string rootPath = $"{string.Join(root, pathParts.Reverse().Skip(1).Reverse())}{root}";
22 | string[] files = Directory.GetFiles(rootPath, assetName, SearchOption.AllDirectories);
23 |
24 | if (files.Length > 0)
25 | {
26 | string bannerPath = files[0];
27 | return AssetDatabase.LoadAssetAtPath(bannerPath);
28 | }
29 |
30 | return null;
31 | }
32 |
33 | protected virtual void OnEnable()
34 | {
35 | if (!Banner)
36 | {
37 | Banner = LoadAssetInSource(BannerName, ROOT_PATH);
38 | }
39 | }
40 |
41 | public override void OnInspectorGUI()
42 | {
43 | EditorHelpers.DrawBanner(Banner);
44 | base.OnInspectorGUI();
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Source/Editor/MOPInspectorBase.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a9e1f820b15245943b7144babbc642a5
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Source/Editor/MasterObjectPoolerInspector.cs:
--------------------------------------------------------------------------------
1 | using UnityEditor;
2 | using UnityEngine;
3 |
4 | namespace QFSW.MOP2.Editor
5 | {
6 | [CustomEditor(typeof(MasterObjectPooler))]
7 | public class MasterObjectPoolerInspector : MOPInspectorBase
8 | {
9 |
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Source/Editor/MasterObjectPoolerInspector.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: af407970fcb3c1f4d87b6bef69df368d
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences:
7 | - _banner: {fileID: 2800000, guid: c7f059f3dce2784499e881a7f8462d56, type: 3}
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Source/Editor/ObjectPoolInspector.cs:
--------------------------------------------------------------------------------
1 | using UnityEditor;
2 | using UnityEngine;
3 |
4 | namespace QFSW.MOP2.Editor
5 | {
6 | [CustomEditor(typeof(ObjectPool))]
7 | public class ObjectPoolInspector : MOPInspectorBase
8 | {
9 | private ObjectPool _objectPool;
10 |
11 | protected override void OnEnable()
12 | {
13 | base.OnEnable();
14 |
15 | _objectPool = (ObjectPool)target;
16 | }
17 |
18 | public override void OnInspectorGUI()
19 | {
20 | EditorHelpers.DrawBanner(Banner);
21 |
22 | if (Application.isPlaying)
23 | {
24 | if (!_objectPool.Initialized)
25 | {
26 | EditorGUILayout.HelpBox("Pool has not been initialized: if you attempt to use the pool before initializing it, unintended behaviour may occur", MessageType.Warning);
27 | }
28 | }
29 |
30 | DrawDefaultInspector();
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Source/Editor/ObjectPoolInspector.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8f957eafbb005ad428e2e97c39220e6f
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences:
7 | - _banner: {fileID: 2800000, guid: c7f059f3dce2784499e881a7f8462d56, type: 3}
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Source/Editor/ObjectPoolPostProcessor.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using UnityEditor;
3 |
4 | namespace QFSW.MOP2.Editor
5 | {
6 | public class ObjectPoolPostProcessor : AssetPostprocessor
7 | {
8 | static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
9 | {
10 | foreach (string assetPath in importedAssets)
11 | {
12 | if (Path.GetExtension(assetPath) == ".asset")
13 | {
14 | ObjectPool pool = AssetDatabase.LoadAssetAtPath(assetPath);
15 | if (pool)
16 | {
17 | pool.AutoFillName();
18 | }
19 | }
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Source/Editor/ObjectPoolPostProcessor.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3d25de96d6ca99742a1255966e0f1941
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Source/Editor/QFSW.MOP2.Editor.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "QFSW.MOP2.Editor",
3 | "references": [
4 | "QFSW.MOP2"
5 | ],
6 | "optionalUnityReferences": [],
7 | "includePlatforms": [
8 | "Editor"
9 | ],
10 | "excludePlatforms": [],
11 | "allowUnsafeCode": false,
12 | "overrideReferences": false,
13 | "precompiledReferences": [],
14 | "autoReferenced": true,
15 | "defineConstraints": []
16 | }
--------------------------------------------------------------------------------
/Source/Editor/QFSW.MOP2.Editor.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f024c38aac696874d9516e4d7e340c9c
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Source/IPoolable.cs:
--------------------------------------------------------------------------------
1 | namespace QFSW.MOP2
2 | {
3 | ///
4 | /// Allows the object to receive information about the pool that it is a part of.
5 | ///
6 | public interface IPoolable
7 | {
8 | ///
9 | /// Initializes the template object with the parent pool.
10 | ///
11 | /// The pool that this template belongs to.
12 | void InitializeTemplate(ObjectPool pool);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Source/IPoolable.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: bcdc0715b8261ff4fa0320e4d875e617
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Source/MasterObjectPooler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 | using Object = UnityEngine.Object;
5 |
6 | namespace QFSW.MOP2
7 | {
8 | ///
9 | /// MasterObjectPooler manages various ObjectPools. By using a MasterObjectPooler, you can perform a large variety of pool operations with a named string reference
10 | /// instead of requiring an object reference to the ObjectPool. Furthermore, initialization of the pools is handled by the MOP.
11 | /// Pools can be added either via the inspector or at runtime.
12 | ///
13 | public class MasterObjectPooler : MonoBehaviour
14 | {
15 | [Tooltip("Forces the MOP into singleton mode. This means the MOP will be made scene persistent and will not be destroyed when new scenes are loaded.")]
16 | [SerializeField] private bool _singletonMode = false;
17 | [SerializeField] private ObjectPool[] _pools = new ObjectPool[0];
18 |
19 | ///
20 | /// Singleton reference to the MOP. Only valid and set if the singleton option is enabled for the MOP.
21 | ///
22 | public static MasterObjectPooler Instance { get; private set; }
23 |
24 | private readonly Dictionary _poolTable = new Dictionary();
25 |
26 | #region Initialization
27 | private void Awake()
28 | {
29 | if (_singletonMode)
30 | {
31 | if (Instance == null)
32 | {
33 | Instance = this;
34 |
35 | if (transform.parent == null)
36 | {
37 | DontDestroyOnLoad(gameObject);
38 | }
39 | else
40 | {
41 | Debug.LogWarning($"Singleton mode enabled for the Master Object Pooler '{name}' which is not a root GameObject; this means it cannot be made scene persistent");
42 | }
43 | }
44 | else
45 | {
46 | Object.Destroy(gameObject);
47 | }
48 | }
49 | }
50 |
51 | private void Start()
52 | {
53 | foreach (ObjectPool pool in _pools)
54 | {
55 | AddPool(pool);
56 | }
57 | }
58 | #endregion
59 |
60 | #region Internal
61 | private void DestroyPoolInternal(ObjectPool pool)
62 | {
63 | pool.Purge();
64 | Object.Destroy(pool.ObjectParent.gameObject);
65 | }
66 | #endregion
67 |
68 | #region PoolManagement
69 | ///
70 | /// Adds an ObjectPool to the MasterObjectPooler and initializes it.
71 | ///
72 | /// The ObjectPool to add to the MasterObjectPooler.
73 | public void AddPool(ObjectPool pool) { AddPool(pool.PoolName, pool); }
74 |
75 | ///
76 | /// Adds an ObjectPool to the MasterObjectPooler and initializes it.
77 | ///
78 | /// Override for the named string reference to use for this pool. By default uses the ObjectPool's name.
79 | /// The ObjectPool to add to the MasterObjectPooler.
80 | public void AddPool(string poolName, ObjectPool pool)
81 | {
82 | pool.Initialize();
83 | pool.ObjectParent.parent = transform;
84 |
85 | if (_poolTable.ContainsKey(poolName))
86 | {
87 | Debug.LogWarning($"{poolName} could not be added to the pool table as a pool with the same name already exists");
88 | }
89 | else
90 | {
91 | _poolTable.Add(poolName, pool);
92 | }
93 | }
94 |
95 | ///
96 | /// Retrieves a pool.
97 | ///
98 | /// The name of the pool to retrieve.
99 | /// The retrieved pool.
100 | public ObjectPool GetPool(string poolName)
101 | {
102 | if (_poolTable.ContainsKey(poolName))
103 | {
104 | return _poolTable[poolName];
105 | }
106 |
107 | throw new ArgumentException($"Cannot get pool {poolName} as it is not present in the pool table");
108 | }
109 |
110 | ///
111 | /// Retrieves/adds a pool.
112 | ///
113 | /// The name of the pool to retrieve/add.
114 | /// The retrieved pool.
115 | public ObjectPool this[string poolName]
116 | {
117 | get => GetPool(poolName);
118 | set
119 | {
120 | _poolTable.Remove(poolName);
121 | AddPool(poolName, value);
122 | }
123 | }
124 |
125 | ///
126 | /// Destroys every pool, purging all of their contents then removing them from the MasterObjectPooler.
127 | ///
128 | public void DestroyAllPools()
129 | {
130 | foreach (ObjectPool pool in _poolTable.Values)
131 | {
132 | DestroyPoolInternal(pool);
133 | }
134 |
135 | _poolTable.Clear();
136 | }
137 |
138 | ///
139 | /// Destroys a specified pool, purging its contents and removing it from the MasterObjectPooler.
140 | ///
141 | /// The pool to destroy.
142 | public void DestroyPool(string poolName)
143 | {
144 | ObjectPool pool = GetPool(poolName);
145 | DestroyPoolInternal(pool);
146 | _poolTable.Remove(poolName);
147 | }
148 | #endregion
149 |
150 | #region GetObject/Component
151 | ///
152 | /// Gets an object from the specified pool.
153 | ///
154 | /// The name of the pool to get an object from.
155 | /// The retrieved object.
156 | public GameObject GetObject(string poolName)
157 | {
158 | return GetPool(poolName).GetObject();
159 | }
160 |
161 | ///
162 | /// Gets an object from the specified pool.
163 | ///
164 | /// The name of the pool to get an object from.
165 | /// The position to set the object to.
166 | /// The retrieved object.
167 | public GameObject GetObject(string poolName, Vector3 position)
168 | {
169 | return GetPool(poolName).GetObject(position);
170 | }
171 |
172 | ///
173 | /// Gets an object from the specified pool.
174 | ///
175 | /// The name of the pool to get an object from.
176 | /// The position to set the object to.
177 | /// The rotation to set the object to.
178 | /// The retrieved object.
179 | public GameObject GetObject(string poolName, Vector3 position, Quaternion rotation)
180 | {
181 | return GetPool(poolName).GetObject(position, rotation);
182 | }
183 |
184 | ///
185 | /// Gets an object from the specified pool, and then retrieves the specified component using a cache to improve performance.
186 | /// Note: this should not be used if multiple components of the same type exist on the object, or if the component will be dynamically removed/added at runtime.
187 | ///
188 | /// The component type to get.
189 | /// The name of the pool to get the component from.
190 | /// The retrieved component.
191 | public T GetObjectComponent(string poolName) where T : class
192 | {
193 | return GetPool(poolName).GetObjectComponent();
194 | }
195 |
196 | ///
197 | /// Gets an object from the specified pool, and then retrieves the specified component using a cache to improve performance.
198 | /// Note: this should not be used if multiple components of the same type exist on the object, or if the component will be dynamically removed/added at runtime.
199 | ///
200 | /// The component type to get.
201 | /// The name of the pool to get the component from.
202 | /// The position to set the object to.
203 | /// The retrieved component.
204 | public T GetObjectComponent(string poolName, Vector3 position) where T : class
205 | {
206 | return GetPool(poolName).GetObjectComponent(position);
207 | }
208 |
209 | ///
210 | /// Gets an object from the specified pool, and then retrieves the specified component using a cache to improve performance.
211 | /// Note: this should not be used if multiple components of the same type exist on the object, or if the component will be dynamically removed/added at runtime.
212 | ///
213 | /// The component type to get.
214 | /// The name of the pool to get the component from.
215 | /// The position to set the object to.
216 | /// The rotation to set the object to.
217 | /// The retrieved component.
218 | public T GetObjectComponent(string poolName, Vector3 position, Quaternion rotation) where T : class
219 | {
220 | return GetPool(poolName).GetObjectComponent(position, rotation);
221 | }
222 | #endregion
223 |
224 | #region Release/Destroys
225 | ///
226 | /// Releases an object and returns it back to the specified pool, effectively 'destroying' it from the scene.
227 | /// Pool equivalent of Destroy.
228 | ///
229 | /// The object to release.
230 | /// The name of the pool to return the object to.
231 | public void Release(GameObject obj, string poolName)
232 | {
233 | GetPool(poolName).Release(obj);
234 | }
235 |
236 | ///
237 | /// Releases a collection of objects and returns them back to the specified pool, effectively 'destroying' them from the scene.
238 | ///
239 | /// the objects to release.
240 | /// The name of the pool to return the objects to.
241 | public void Release(IEnumerable objs, string poolName)
242 | {
243 | GetPool(poolName).Release(objs);
244 | }
245 |
246 | ///
247 | /// Releases every active object in the specified pool.
248 | ///
249 | /// The name of the pool.
250 | public void ReleaseAll(string poolName)
251 | {
252 | GetPool(poolName).ReleaseAll();
253 | }
254 |
255 | ///
256 | /// Forcibly destroys the object and does not return it to a pool.
257 | ///
258 | /// The object to destroy.
259 | public void Destroy(GameObject obj) { Destroy(obj, obj.name); }
260 |
261 | ///
262 | /// Forcibly destroys the object and does not return it to a pool.
263 | ///
264 | /// The object to destroy.
265 | /// The name of the pool that the object belonged to.
266 | public void Destroy(GameObject obj, string poolName)
267 | {
268 | ObjectPool pool = GetPool(poolName);
269 | if (pool) { pool.Destroy(obj); }
270 | else { Object.Destroy(obj); }
271 | }
272 |
273 | ///
274 | /// Forcibly destroys a collection of objects and does not return them to a pool.
275 | ///
276 | /// The objects to destroy.
277 | /// The name of the pool that the objects belonged to.
278 | public void Destroy(IEnumerable objs, string poolName)
279 | {
280 | ObjectPool pool = GetPool(poolName);
281 | if (pool) { pool.Destroy(objs); }
282 | else
283 | {
284 | foreach (GameObject obj in objs)
285 | {
286 | Object.Destroy(obj);
287 | }
288 | }
289 | }
290 |
291 | ///
292 | /// Releases every active object in every pool.
293 | ///
294 | public void ReleaseAllInAllPools()
295 | {
296 | foreach (ObjectPool pool in _poolTable.Values)
297 | {
298 | pool.ReleaseAll();
299 | }
300 | }
301 | #endregion
302 |
303 | #region Miscellaneous
304 | ///
305 | /// Populates the specified pool with the specified number of objects, so that they do not need instantiating later.
306 | ///
307 | /// The name of the pool to populate.
308 | /// The number of objects to populate it with.
309 | /// The population mode.
310 | public void Populate(string poolName, int quantity, PopulateMethod method = PopulateMethod.Set)
311 | {
312 | GetPool(poolName).Populate(quantity, method);
313 | }
314 |
315 | ///
316 | /// Destroys every object in the specified pool, both alive and pooled.
317 | ///
318 | /// The name of the pool to populate.
319 | public void Purge(string poolName)
320 | {
321 | GetPool(poolName).Purge();
322 | }
323 |
324 | ///
325 | /// Destroys every object in every pool, both alive and pooled.
326 | ///
327 | public void PurgeAll()
328 | {
329 | foreach (ObjectPool pool in _poolTable.Values)
330 | {
331 | pool.Purge();
332 | }
333 | }
334 |
335 | ///
336 | /// Gets all active objects in the specified pool.
337 | ///
338 | /// The name of the pool to populate.
339 | /// The active objects.
340 | public IEnumerable GetAllActiveObjects(string poolName)
341 | {
342 | return GetPool(poolName).GetAllActiveObjects();
343 | }
344 | #endregion
345 | }
346 | }
347 |
--------------------------------------------------------------------------------
/Source/MasterObjectPooler.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ae7d75d4e54c16b42b11bb89b17dc809
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Source/ObjectPool.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text.RegularExpressions;
5 | using UnityEngine;
6 | using UnityEngine.SceneManagement;
7 | using Object = UnityEngine.Object;
8 |
9 | [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("QFSW.MOP2.Editor")]
10 |
11 | namespace QFSW.MOP2
12 | {
13 | ///
14 | /// Object pool containing several copies of a template object (usually a prefab). Using the pool with GetObject and Release
15 | /// provides a high speed alternative to repeatedly calling Instantiate and Destroy.
16 | ///
17 | [CreateAssetMenu(fileName = "Untitled Pool", menuName = "Master Object Pooler 2/Object Pool", order = 0)]
18 | public class ObjectPool : ScriptableObject
19 | {
20 | [Tooltip("The name of the pool. Used for identification and as the key when using a MasterObjectPooler.")]
21 | [SerializeField] private string _name = string.Empty;
22 |
23 | [Tooltip("The template object to center the pool on. All objects in the pool will be a copy of this object.")]
24 | [SerializeField] private GameObject _template = null;
25 |
26 | [Tooltip("The default number of objects to create in this pool when initializing it.")]
27 | [SerializeField] private int _defaultSize;
28 |
29 | [Tooltip("The maximum number of objects that can be kept in this pool. If it is exceeded, objects will be destroyed instead of pooled when returned. Set to -1 for no limit.")]
30 | [SerializeField] private int _maxSize = -1;
31 |
32 | [Tooltip("If enabled, object instances will be renamed to ObjectName#XXX where XXX is the instance number. This is useful if you want them all to be uniquely named.")]
33 | [SerializeField] private bool _incrementalInstanceNames = false;
34 |
35 | [Tooltip("Auto initializes the pool. In the editor this occurs when play-mode is entered. In builds, this occurs on startup")]
36 | [SerializeField] private bool _autoInitialize = false;
37 |
38 | [Tooltip("Repopulate the pool with objects when the scene changes to replace objects that were unloaded/destroyed.")]
39 | [SerializeField] private bool _repopulateOnSceneChange = false;
40 |
41 | ///
42 | /// If enabled, object instances will be renamed to ObjectName#XXX where XXX is the instance number. This is useful if you want them all to be uniquely named.
43 | ///
44 | public bool IncrementalInstanceNames
45 | {
46 | get => _incrementalInstanceNames;
47 | set => _incrementalInstanceNames = value;
48 | }
49 |
50 | ///
51 | /// The name of the pool. Used for identification and as the key when using a MasterObjectPooler.
52 | ///
53 | public string PoolName => _name;
54 |
55 | ///
56 | /// Parent transform for all pooled objects.
57 | ///
58 | public Transform ObjectParent
59 | {
60 | get
61 | {
62 | if (!_objectParent)
63 | {
64 | _objectParent = new GameObject($"{_name} Pool").transform;
65 | }
66 |
67 | return _objectParent;
68 | }
69 | }
70 | private Transform _objectParent;
71 |
72 | private bool HasMaxSize => _maxSize > 0;
73 | private bool HasPooledObjects => _pooledObjects.Count > 0;
74 | public bool Initialized { get; private set; }
75 |
76 | private int _instanceCounter = 0;
77 | private readonly Regex _poolRegex = new Regex("[_ ]*[Pp]ool");
78 |
79 | #region Caches
80 | private readonly List _pooledObjects = new List();
81 | private readonly Dictionary _aliveObjects = new Dictionary();
82 |
83 | private readonly List _releaseAllBuffer = new List();
84 | private readonly Dictionary<(int id, Type type), object> _componentCache = new Dictionary<(int id, Type type), object>();
85 | #endregion
86 |
87 | #region Initialization/Creation
88 | private ObjectPool() { }
89 |
90 | ///
91 | /// Creates an ObjectPool.
92 | ///
93 | /// The template object to center the pool on. All objects in the pool will be a copy of this object.
94 | /// The default number of objects to create in this pool when initializing it.
95 | /// The maximum number of objects that can be kept in this pool. If it is exceeded, objects will be destroyed instead of pooled when returned. Set to -1 for no limit.
96 | /// The created ObjectPool.
97 | public static ObjectPool Create(GameObject template, int defaultSize = 0, int maxSize = -1)
98 | {
99 | return Create(template, template.name, defaultSize, maxSize);
100 | }
101 |
102 | ///
103 | /// Creates an ObjectPool.
104 | ///
105 | /// The template object to center the pool on. All objects in the pool will be a copy of this object.
106 | /// The name of the pool. Used for identification and as the key when using a MasterObjectPooler.
107 | /// The default number of objects to create in this pool when initializing it.
108 | /// The maximum number of objects that can be kept in this pool. If it is exceeded, objects will be destroyed instead of pooled when returned. Set to -1 for no limit.
109 | /// The created ObjectPool.
110 | public static ObjectPool Create(GameObject template, string name, int defaultSize = 0, int maxSize = -1)
111 | {
112 | ObjectPool pool = CreateInstance();
113 | pool._name = name;
114 | pool._template = template;
115 | pool._defaultSize = defaultSize;
116 | pool._maxSize = maxSize;
117 |
118 | return pool;
119 | }
120 |
121 | ///
122 | /// Creates an ObjectPool and initializes it.
123 | ///
124 | /// The template object to center the pool on. All objects in the pool will be a copy of this object.
125 | /// The default number of objects to create in this pool when initializing it.
126 | /// The maximum number of objects that can be kept in this pool. If it is exceeded, objects will be destroyed instead of pooled when returned. Set to -1 for no limit.
127 | /// The created ObjectPool.
128 | public static ObjectPool CreateAndInitialize(GameObject template, int defaultSize = 0, int maxSize = -1)
129 | {
130 | ObjectPool pool = Create(template, defaultSize, maxSize);
131 | pool.Initialize();
132 |
133 | return pool;
134 | }
135 |
136 | ///
137 | /// Creates an ObjectPool and initializes it.
138 | ///
139 | /// The template object to center the pool on. All objects in the pool will be a copy of this object.
140 | /// The name of the pool. Used for identification and as the key when using a MasterObjectPooler.
141 | /// The default number of objects to create in this pool when initializing it.
142 | /// The maximum number of objects that can be kept in this pool. If it is exceeded, objects will be destroyed instead of pooled when returned. Set to -1 for no limit.
143 | /// The created ObjectPool.
144 | public static ObjectPool CreateAndInitialize(GameObject template, string name, int defaultSize = 0, int maxSize = -1)
145 | {
146 | ObjectPool pool = Create(template, name, defaultSize, maxSize);
147 | pool.Initialize();
148 |
149 | return pool;
150 | }
151 |
152 | private void OnEnable()
153 | {
154 | _instanceCounter = 0;
155 | SceneManager.sceneUnloaded += OnSceneUnload;
156 | #if UNITY_EDITOR
157 | UnityEditor.EditorApplication.playModeStateChanged += OnPlayModeStateChange;
158 | #endif
159 | }
160 |
161 | private void OnDisable()
162 | {
163 | SceneManager.sceneUnloaded -= OnSceneUnload;
164 | #if UNITY_EDITOR
165 | UnityEditor.EditorApplication.playModeStateChanged -= OnPlayModeStateChange;
166 | #endif
167 | }
168 |
169 | ///
170 | /// Initializes the ObjectPool.
171 | ///
172 | public void Initialize(bool forceReinitialization = false)
173 | {
174 | if (!Initialized || forceReinitialization)
175 | {
176 | Initialized = true;
177 |
178 | AutoFillName();
179 | InitializeIPoolables();
180 | Populate(_defaultSize, PopulateMethod.Set);
181 | }
182 | }
183 |
184 | internal void AutoFillName()
185 | {
186 | if (string.IsNullOrWhiteSpace(_name))
187 | {
188 | _name = _poolRegex.Replace(name, string.Empty);
189 | ObjectParent.name = _name;
190 | }
191 | else if (string.IsNullOrWhiteSpace(name))
192 | {
193 | name = _name;
194 | }
195 | }
196 |
197 | private void InitializeIPoolables()
198 | {
199 | foreach (IPoolable poolable in _template.GetComponentsInChildren())
200 | {
201 | poolable.InitializeTemplate(this);
202 | }
203 | }
204 | #endregion
205 |
206 | #region Internal
207 | private GameObject CreateNewObject() { return CreateNewObject(_template.transform.position, _template.transform.rotation); }
208 | private GameObject CreateNewObject(Vector3 position, Quaternion rotation)
209 | {
210 | GameObject newObj = Instantiate(_template, position, rotation);
211 | newObj.transform.SetParent(ObjectParent, false);
212 |
213 | if (_incrementalInstanceNames)
214 | {
215 | newObj.name = string.Format("{0}#{1:000}", _template.name, _instanceCounter);
216 | }
217 | else
218 | {
219 | newObj.name = _template.name;
220 | }
221 |
222 | _instanceCounter++;
223 | return newObj;
224 | }
225 |
226 | private void CleanseInternal()
227 | {
228 | if (!_objectParent)
229 | {
230 | _pooledObjects.Clear();
231 | _aliveObjects.Clear();
232 | _componentCache.Clear();
233 | }
234 | else
235 | {
236 | _pooledObjects.RemoveAll(x => !x);
237 | }
238 | }
239 | #endregion
240 |
241 | #region GetObject/Component
242 | ///
243 | /// Gets an object from the pool.
244 | ///
245 | /// The retrieved object.
246 | public GameObject GetObject() { return GetObject(_template.transform.position); }
247 |
248 | ///
249 | /// Gets an object from the pool.
250 | ///
251 | /// The position to set the object to.
252 | /// The retrieved object.
253 | public GameObject GetObject(Vector3 position) { return GetObject(position, _template.transform.rotation); }
254 |
255 | ///
256 | /// Gets an object from the pool.
257 | ///
258 | /// The position to set the object to.
259 | /// The rotation to set the object to.
260 | /// The retrieved object.
261 | public GameObject GetObject(Vector3 position, Quaternion rotation)
262 | {
263 | GameObject obj;
264 | if (HasPooledObjects)
265 | {
266 | obj = _pooledObjects[_pooledObjects.Count - 1];
267 | _pooledObjects.RemoveAt(_pooledObjects.Count - 1);
268 |
269 | if (!obj)
270 | {
271 | Debug.LogWarning($"Object in pool '{_name}' was null or destroyed; it may have been destroyed externally. Attempting to retrieve a new object");
272 | return GetObject(position, rotation);
273 | }
274 |
275 | obj.transform.SetPositionAndRotation(position, rotation);
276 | obj.transform.localScale = _template.transform.localScale;
277 | }
278 | else
279 | {
280 | obj = CreateNewObject(position, rotation);
281 | }
282 |
283 | obj.SetActive(true);
284 |
285 | _aliveObjects.Add(obj.GetInstanceID(), obj);
286 | return obj;
287 | }
288 |
289 | ///
290 | /// Gets an object from the pool, and then retrieves the specified component using a cache to improve performance.
291 | ///
292 | /// The component type to get.
293 | /// The retrieved component.
294 | public T GetObjectComponent() where T : class
295 | {
296 | return GetObjectComponent(_template.transform.position);
297 | }
298 |
299 | ///
300 | /// Gets an object from the pool, and then retrieves the specified component using a cache to improve performance.
301 | ///
302 | /// The component type to get.
303 | /// The position to set the object to.
304 | /// The retrieved component.
305 | public T GetObjectComponent(Vector3 position) where T : class
306 | {
307 | return GetObjectComponent(position, _template.transform.rotation);
308 | }
309 |
310 | ///
311 | /// Gets an object from the pool, and then retrieves the specified component using a cache to improve performance.
312 | ///
313 | /// The component type to get.
314 | /// The position to set the object to.
315 | /// The rotation to set the object to.
316 | /// The retrieved component.
317 | public T GetObjectComponent(Vector3 position, Quaternion rotation) where T : class
318 | {
319 | GameObject obj = GetObject(position, rotation);
320 | return GetObjectComponent(obj);
321 | }
322 |
323 | ///
324 | /// Retrieves the specified component from an object using a cache to improve performance.
325 | ///
326 | /// The component type to get.
327 | /// The object to get the component from.
328 | /// The retrieved component.
329 | public T GetObjectComponent(GameObject obj) where T : class
330 | {
331 | (int id, Type type) key = (obj.GetInstanceID(), typeof(T));
332 | T component;
333 |
334 | if (_componentCache.ContainsKey(key))
335 | {
336 | component = _componentCache[key] as T;
337 | if (component == null) { _componentCache.Remove(key); }
338 | else { return component; }
339 | }
340 |
341 | component = obj.GetComponent();
342 | if (component != null) { _componentCache[key] = component; }
343 | return component;
344 | }
345 | #endregion
346 |
347 | #region Release/Destroy
348 | ///
349 | /// Releases an object and returns it back to the pool, effectively 'destroying' it from the scene.
350 | /// Pool equivalent of Destroy.
351 | ///
352 | /// The object to release.
353 | public void Release(GameObject obj)
354 | {
355 | if (!_aliveObjects.Remove(obj.GetInstanceID()))
356 | {
357 | Debug.LogWarning($"Object '{obj}' could not be found in pool '{_name}'; it may have already been released.");
358 | return;
359 | }
360 |
361 | if (obj)
362 | {
363 | if (HasMaxSize && _pooledObjects.Count >= _maxSize)
364 | {
365 | Object.Destroy(obj);
366 | }
367 | else
368 | {
369 | _pooledObjects.Add(obj);
370 | obj.SetActive(false);
371 | obj.transform.SetParent(ObjectParent, false);
372 | }
373 | }
374 | }
375 |
376 | ///
377 | /// Releases a collection of objects and returns them back to the pool, effectively 'destroying' them from the scene.
378 | ///
379 | /// the objects to release.
380 | public void Release(IEnumerable objs)
381 | {
382 | foreach (GameObject obj in objs)
383 | {
384 | Release(obj);
385 | }
386 | }
387 |
388 | ///
389 | /// Releases every active object in this pool.
390 | ///
391 | public void ReleaseAll()
392 | {
393 | _releaseAllBuffer.Clear();
394 | _releaseAllBuffer.AddRange(_aliveObjects.Values);
395 | Release(_releaseAllBuffer);
396 | }
397 |
398 | ///
399 | /// Forcibly destroys the object and does not return it to the pool.
400 | ///
401 | /// The object to destroy.
402 | public void Destroy(GameObject obj)
403 | {
404 | _aliveObjects.Remove(obj.GetInstanceID());
405 | Object.Destroy(obj);
406 | }
407 |
408 | ///
409 | /// Forcibly destroys a collection of objects and does not return them to the pool.
410 | ///
411 | /// The objects to destroy.
412 | public void Destroy(IEnumerable objs)
413 | {
414 | foreach (GameObject obj in objs)
415 | {
416 | Destroy(obj);
417 | }
418 | }
419 | #endregion
420 |
421 | #region Miscellaneous
422 | ///
423 | /// Populates the pool with the specified number of objects, so that they do not need instantiating later.
424 | ///
425 | /// The number of objects to populate it with.
426 | /// The population mode.
427 | public void Populate(int quantity, PopulateMethod method = PopulateMethod.Set)
428 | {
429 | int newObjCount;
430 | switch (method)
431 | {
432 | case PopulateMethod.Set: newObjCount = quantity - _pooledObjects.Count; break;
433 | case PopulateMethod.Add: newObjCount = quantity; break;
434 | default: newObjCount = 0; break;
435 | }
436 |
437 | if (HasMaxSize) { newObjCount = Mathf.Min(newObjCount, _maxSize - _pooledObjects.Count); }
438 | if (newObjCount < 0) { newObjCount = 0; }
439 |
440 | for (int i = 0; i < newObjCount; i++)
441 | {
442 | GameObject newObj = CreateNewObject();
443 | newObj.SetActive(false);
444 | _pooledObjects.Add(newObj);
445 | }
446 | }
447 |
448 | ///
449 | /// Destroys every object in the pool, both alive and pooled.
450 | ///
451 | public void Purge()
452 | {
453 | foreach (GameObject obj in _pooledObjects) { Object.Destroy(obj); }
454 | foreach (GameObject obj in _aliveObjects.Values) { Object.Destroy(obj); }
455 | _pooledObjects.Clear();
456 | _aliveObjects.Clear();
457 | _componentCache.Clear();
458 | }
459 |
460 | ///
461 | /// Gets all active objects in the pool.
462 | ///
463 | /// The active objects.
464 | public IEnumerable GetAllActiveObjects()
465 | {
466 | return _aliveObjects.Values
467 | .Where(x => x);
468 | }
469 | #endregion
470 |
471 | #region Callbacks
472 | private void Awake()
473 | {
474 | Initialized = false;
475 |
476 | #if !UNITY_EDITOR
477 | if (_autoInitialize)
478 | {
479 | Initialize();
480 | }
481 | #endif
482 | }
483 |
484 | private void OnSceneUnload(Scene scene)
485 | {
486 | CleanseInternal();
487 |
488 | if (_repopulateOnSceneChange)
489 | {
490 | Populate(_defaultSize, PopulateMethod.Set);
491 | }
492 | }
493 |
494 | #if UNITY_EDITOR
495 | private void OnPlayModeStateChange(UnityEditor.PlayModeStateChange state)
496 | {
497 | if (state == UnityEditor.PlayModeStateChange.EnteredPlayMode)
498 | {
499 | _instanceCounter = 0;
500 | Initialized = false;
501 | CleanseInternal();
502 |
503 | if (_autoInitialize)
504 | {
505 | Initialize();
506 | }
507 | }
508 | }
509 | #endif
510 | #endregion
511 | }
512 | }
513 |
--------------------------------------------------------------------------------
/Source/ObjectPool.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5ad40add42ecce646952aaa9475056c8
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {fileID: 2800000, guid: 20484e3aa77c0634dafa269c9ad3ca1b, type: 3}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Source/PoolableMonoBehaviour.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace QFSW.MOP2
4 | {
5 | ///
6 | /// MonoBehaviour that has a reference to its parent pool, and can thus be released to the pool without the user needing a reference to its pool, making it self contained.
7 | /// Usable either as a standalone component or as a base class for other components.
8 | ///
9 | public class PoolableMonoBehaviour : MonoBehaviour, IPoolable
10 | {
11 | ///
12 | /// If its parent pool has been initialized yet.
13 | ///
14 | public bool PoolReady => _parentPool;
15 |
16 | [SerializeField]
17 | [HideInInspector]
18 | private ObjectPool _parentPool;
19 |
20 | void IPoolable.InitializeTemplate(ObjectPool pool)
21 | {
22 | _parentPool = pool;
23 | }
24 |
25 | ///
26 | /// Releases the object and returns it back to its pool, effectively 'destroying' it from the scene.
27 | ///
28 | public void Release()
29 | {
30 | _parentPool.Release(gameObject);
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Source/PoolableMonoBehaviour.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7821b7230681c6f4d94a8fa7f8825ac2
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Source/PopulateMethod.cs:
--------------------------------------------------------------------------------
1 | namespace QFSW.MOP2
2 | {
3 | ///
4 | /// Determines how many objects are needed when populating a pool.
5 | ///
6 | public enum PopulateMethod
7 | {
8 | /// If set is used, then populate will ensure the final population is the specified count.
9 | Set = 0,
10 |
11 | /// If add is used, then populate will add the specified count to the current population.
12 | Add = 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Source/PopulateMethod.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 307ba4f079a9a7244b4509f5e19d821f
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Source/QFSW.MOP2.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "QFSW.MOP2",
3 | "references": [],
4 | "optionalUnityReferences": [],
5 | "includePlatforms": [],
6 | "excludePlatforms": [],
7 | "allowUnsafeCode": false,
8 | "overrideReferences": false,
9 | "precompiledReferences": [],
10 | "autoReferenced": true,
11 | "defineConstraints": []
12 | }
--------------------------------------------------------------------------------
/Source/QFSW.MOP2.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: adb0f400804b2c0448682f502e5eb39b
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Source/Textures.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f137be7750778694fb3fcdcdb5aea9a8
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Source/Textures/Banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QFSW/MasterObjectPooler2/5a9129f1f1a6a3c0031573ac9b0933ed64de811f/Source/Textures/Banner.png
--------------------------------------------------------------------------------
/Source/Textures/Banner.png.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c7f059f3dce2784499e881a7f8462d56
3 | TextureImporter:
4 | fileIDToRecycleName: {}
5 | externalObjects: {}
6 | serializedVersion: 9
7 | mipmaps:
8 | mipMapMode: 0
9 | enableMipMap: 1
10 | sRGBTexture: 1
11 | linearTexture: 0
12 | fadeOut: 0
13 | borderMipMap: 0
14 | mipMapsPreserveCoverage: 0
15 | alphaTestReferenceValue: 0.5
16 | mipMapFadeDistanceStart: 1
17 | mipMapFadeDistanceEnd: 3
18 | bumpmap:
19 | convertToNormalMap: 0
20 | externalNormalMap: 0
21 | heightScale: 0.25
22 | normalMapFilter: 0
23 | isReadable: 0
24 | streamingMipmaps: 0
25 | streamingMipmapsPriority: 0
26 | grayScaleToAlpha: 0
27 | generateCubemap: 6
28 | cubemapConvolution: 0
29 | seamlessCubemap: 0
30 | textureFormat: 1
31 | maxTextureSize: 2048
32 | textureSettings:
33 | serializedVersion: 2
34 | filterMode: 2
35 | aniso: 1
36 | mipBias: -100
37 | wrapU: 1
38 | wrapV: 1
39 | wrapW: -1
40 | nPOTScale: 0
41 | lightmap: 0
42 | compressionQuality: 50
43 | spriteMode: 1
44 | spriteExtrude: 1
45 | spriteMeshType: 1
46 | alignment: 0
47 | spritePivot: {x: 0.5, y: 0.5}
48 | spritePixelsToUnits: 100
49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0}
50 | spriteGenerateFallbackPhysicsShape: 1
51 | alphaUsage: 1
52 | alphaIsTransparency: 1
53 | spriteTessellationDetail: -1
54 | textureType: 2
55 | textureShape: 1
56 | singleChannelComponent: 0
57 | maxTextureSizeSet: 0
58 | compressionQualitySet: 0
59 | textureFormatSet: 0
60 | platformSettings:
61 | - serializedVersion: 2
62 | buildTarget: DefaultTexturePlatform
63 | maxTextureSize: 4096
64 | resizeAlgorithm: 0
65 | textureFormat: -1
66 | textureCompression: 2
67 | compressionQuality: 50
68 | crunchedCompression: 0
69 | allowsAlphaSplitting: 0
70 | overridden: 0
71 | androidETC2FallbackOverride: 0
72 | - serializedVersion: 2
73 | buildTarget: Standalone
74 | maxTextureSize: 4096
75 | resizeAlgorithm: 0
76 | textureFormat: -1
77 | textureCompression: 2
78 | compressionQuality: 50
79 | crunchedCompression: 0
80 | allowsAlphaSplitting: 0
81 | overridden: 0
82 | androidETC2FallbackOverride: 0
83 | - serializedVersion: 2
84 | buildTarget: Windows Store Apps
85 | maxTextureSize: 2048
86 | resizeAlgorithm: 0
87 | textureFormat: -1
88 | textureCompression: 1
89 | compressionQuality: 50
90 | crunchedCompression: 0
91 | allowsAlphaSplitting: 0
92 | overridden: 0
93 | androidETC2FallbackOverride: 0
94 | - serializedVersion: 2
95 | buildTarget: Android
96 | maxTextureSize: 2048
97 | resizeAlgorithm: 0
98 | textureFormat: -1
99 | textureCompression: 1
100 | compressionQuality: 50
101 | crunchedCompression: 0
102 | allowsAlphaSplitting: 0
103 | overridden: 0
104 | androidETC2FallbackOverride: 0
105 | - serializedVersion: 2
106 | buildTarget: WebGL
107 | maxTextureSize: 2048
108 | resizeAlgorithm: 0
109 | textureFormat: -1
110 | textureCompression: 1
111 | compressionQuality: 50
112 | crunchedCompression: 0
113 | allowsAlphaSplitting: 0
114 | overridden: 0
115 | androidETC2FallbackOverride: 0
116 | spriteSheet:
117 | serializedVersion: 2
118 | sprites: []
119 | outline: []
120 | physicsShape: []
121 | bones: []
122 | spriteID: 4c884f7d4f2f0784ca8758e0b62946fc
123 | vertices: []
124 | indices:
125 | edges: []
126 | weights: []
127 | spritePackingTag:
128 | pSDRemoveMatte: 0
129 | pSDShowRemoveMatteOption: 0
130 | userData:
131 | assetBundleName:
132 | assetBundleVariant:
133 |
--------------------------------------------------------------------------------
/Source/Textures/BannerCutout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QFSW/MasterObjectPooler2/5a9129f1f1a6a3c0031573ac9b0933ed64de811f/Source/Textures/BannerCutout.png
--------------------------------------------------------------------------------
/Source/Textures/BannerCutout.png.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0077622ae1b3e8040bd798043be536da
3 | TextureImporter:
4 | fileIDToRecycleName: {}
5 | externalObjects: {}
6 | serializedVersion: 9
7 | mipmaps:
8 | mipMapMode: 0
9 | enableMipMap: 1
10 | sRGBTexture: 1
11 | linearTexture: 0
12 | fadeOut: 0
13 | borderMipMap: 0
14 | mipMapsPreserveCoverage: 0
15 | alphaTestReferenceValue: 0.5
16 | mipMapFadeDistanceStart: 1
17 | mipMapFadeDistanceEnd: 3
18 | bumpmap:
19 | convertToNormalMap: 0
20 | externalNormalMap: 0
21 | heightScale: 0.25
22 | normalMapFilter: 0
23 | isReadable: 0
24 | streamingMipmaps: 0
25 | streamingMipmapsPriority: 0
26 | grayScaleToAlpha: 0
27 | generateCubemap: 6
28 | cubemapConvolution: 0
29 | seamlessCubemap: 0
30 | textureFormat: 1
31 | maxTextureSize: 2048
32 | textureSettings:
33 | serializedVersion: 2
34 | filterMode: 2
35 | aniso: 1
36 | mipBias: -100
37 | wrapU: 1
38 | wrapV: 1
39 | wrapW: -1
40 | nPOTScale: 0
41 | lightmap: 0
42 | compressionQuality: 50
43 | spriteMode: 1
44 | spriteExtrude: 1
45 | spriteMeshType: 1
46 | alignment: 0
47 | spritePivot: {x: 0.5, y: 0.5}
48 | spritePixelsToUnits: 100
49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0}
50 | spriteGenerateFallbackPhysicsShape: 1
51 | alphaUsage: 1
52 | alphaIsTransparency: 1
53 | spriteTessellationDetail: -1
54 | textureType: 2
55 | textureShape: 1
56 | singleChannelComponent: 0
57 | maxTextureSizeSet: 0
58 | compressionQualitySet: 0
59 | textureFormatSet: 0
60 | platformSettings:
61 | - serializedVersion: 2
62 | buildTarget: DefaultTexturePlatform
63 | maxTextureSize: 4096
64 | resizeAlgorithm: 0
65 | textureFormat: -1
66 | textureCompression: 2
67 | compressionQuality: 50
68 | crunchedCompression: 0
69 | allowsAlphaSplitting: 0
70 | overridden: 0
71 | androidETC2FallbackOverride: 0
72 | - serializedVersion: 2
73 | buildTarget: Standalone
74 | maxTextureSize: 4096
75 | resizeAlgorithm: 0
76 | textureFormat: -1
77 | textureCompression: 2
78 | compressionQuality: 50
79 | crunchedCompression: 0
80 | allowsAlphaSplitting: 0
81 | overridden: 0
82 | androidETC2FallbackOverride: 0
83 | - serializedVersion: 2
84 | buildTarget: Windows Store Apps
85 | maxTextureSize: 2048
86 | resizeAlgorithm: 0
87 | textureFormat: -1
88 | textureCompression: 1
89 | compressionQuality: 50
90 | crunchedCompression: 0
91 | allowsAlphaSplitting: 0
92 | overridden: 0
93 | androidETC2FallbackOverride: 0
94 | - serializedVersion: 2
95 | buildTarget: Android
96 | maxTextureSize: 2048
97 | resizeAlgorithm: 0
98 | textureFormat: -1
99 | textureCompression: 1
100 | compressionQuality: 50
101 | crunchedCompression: 0
102 | allowsAlphaSplitting: 0
103 | overridden: 0
104 | androidETC2FallbackOverride: 0
105 | - serializedVersion: 2
106 | buildTarget: WebGL
107 | maxTextureSize: 2048
108 | resizeAlgorithm: 0
109 | textureFormat: -1
110 | textureCompression: 1
111 | compressionQuality: 50
112 | crunchedCompression: 0
113 | allowsAlphaSplitting: 0
114 | overridden: 0
115 | androidETC2FallbackOverride: 0
116 | spriteSheet:
117 | serializedVersion: 2
118 | sprites: []
119 | outline: []
120 | physicsShape: []
121 | bones: []
122 | spriteID: 0755d778ef45dc84fa397370a99aabb2
123 | vertices: []
124 | indices:
125 | edges: []
126 | weights: []
127 | spritePackingTag:
128 | pSDRemoveMatte: 0
129 | pSDShowRemoveMatteOption: 0
130 | userData:
131 | assetBundleName:
132 | assetBundleVariant:
133 |
--------------------------------------------------------------------------------
/Source/Textures/Pool.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QFSW/MasterObjectPooler2/5a9129f1f1a6a3c0031573ac9b0933ed64de811f/Source/Textures/Pool.png
--------------------------------------------------------------------------------
/Source/Textures/Pool.png.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 20484e3aa77c0634dafa269c9ad3ca1b
3 | TextureImporter:
4 | internalIDToNameTable: []
5 | externalObjects: {}
6 | serializedVersion: 10
7 | mipmaps:
8 | mipMapMode: 0
9 | enableMipMap: 1
10 | sRGBTexture: 1
11 | linearTexture: 0
12 | fadeOut: 0
13 | borderMipMap: 0
14 | mipMapsPreserveCoverage: 0
15 | alphaTestReferenceValue: 0.5
16 | mipMapFadeDistanceStart: 1
17 | mipMapFadeDistanceEnd: 3
18 | bumpmap:
19 | convertToNormalMap: 0
20 | externalNormalMap: 0
21 | heightScale: 0.25
22 | normalMapFilter: 0
23 | isReadable: 0
24 | streamingMipmaps: 0
25 | streamingMipmapsPriority: 0
26 | grayScaleToAlpha: 0
27 | generateCubemap: 6
28 | cubemapConvolution: 0
29 | seamlessCubemap: 0
30 | textureFormat: 1
31 | maxTextureSize: 2048
32 | textureSettings:
33 | serializedVersion: 2
34 | filterMode: -1
35 | aniso: 1
36 | mipBias: -100
37 | wrapU: 1
38 | wrapV: 1
39 | wrapW: -1
40 | nPOTScale: 0
41 | lightmap: 0
42 | compressionQuality: 50
43 | spriteMode: 0
44 | spriteExtrude: 1
45 | spriteMeshType: 1
46 | alignment: 0
47 | spritePivot: {x: 0.5, y: 0.5}
48 | spritePixelsToUnits: 100
49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0}
50 | spriteGenerateFallbackPhysicsShape: 1
51 | alphaUsage: 1
52 | alphaIsTransparency: 1
53 | spriteTessellationDetail: -1
54 | textureType: 2
55 | textureShape: 1
56 | singleChannelComponent: 0
57 | maxTextureSizeSet: 0
58 | compressionQualitySet: 0
59 | textureFormatSet: 0
60 | platformSettings:
61 | - serializedVersion: 2
62 | buildTarget: DefaultTexturePlatform
63 | maxTextureSize: 2048
64 | resizeAlgorithm: 0
65 | textureFormat: -1
66 | textureCompression: 2
67 | compressionQuality: 50
68 | crunchedCompression: 0
69 | allowsAlphaSplitting: 0
70 | overridden: 0
71 | androidETC2FallbackOverride: 0
72 | - serializedVersion: 2
73 | buildTarget: Standalone
74 | maxTextureSize: 2048
75 | resizeAlgorithm: 0
76 | textureFormat: -1
77 | textureCompression: 2
78 | compressionQuality: 50
79 | crunchedCompression: 0
80 | allowsAlphaSplitting: 0
81 | overridden: 0
82 | androidETC2FallbackOverride: 0
83 | - serializedVersion: 2
84 | buildTarget: Windows Store Apps
85 | maxTextureSize: 2048
86 | resizeAlgorithm: 0
87 | textureFormat: -1
88 | textureCompression: 2
89 | compressionQuality: 50
90 | crunchedCompression: 0
91 | allowsAlphaSplitting: 0
92 | overridden: 0
93 | androidETC2FallbackOverride: 0
94 | - serializedVersion: 2
95 | buildTarget: Android
96 | maxTextureSize: 2048
97 | resizeAlgorithm: 0
98 | textureFormat: -1
99 | textureCompression: 2
100 | compressionQuality: 50
101 | crunchedCompression: 0
102 | allowsAlphaSplitting: 0
103 | overridden: 0
104 | androidETC2FallbackOverride: 0
105 | - serializedVersion: 2
106 | buildTarget: WebGL
107 | maxTextureSize: 2048
108 | resizeAlgorithm: 0
109 | textureFormat: -1
110 | textureCompression: 2
111 | compressionQuality: 50
112 | crunchedCompression: 0
113 | allowsAlphaSplitting: 0
114 | overridden: 0
115 | androidETC2FallbackOverride: 0
116 | spriteSheet:
117 | serializedVersion: 2
118 | sprites: []
119 | outline: []
120 | physicsShape: []
121 | bones: []
122 | spriteID:
123 | internalID: 0
124 | vertices: []
125 | indices:
126 | edges: []
127 | weights: []
128 | secondaryTextures: []
129 | spritePackingTag:
130 | pSDRemoveMatte: 0
131 | pSDShowRemoveMatteOption: 0
132 | userData:
133 | assetBundleName:
134 | assetBundleVariant:
135 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "com.qfsw.mop2",
3 | "displayName": "Master Object Pooler 2",
4 | "author": "QFSW",
5 | "description": "Master Object Pooler 2 is a high performance, flexible and easy to use object pooling solution that can fit into any project.",
6 | "bugs": {
7 | "email": "support@qfsw.co.uk",
8 | "url": "https://github.com/QFSW/MasterObjectPooler2/issues"
9 | },
10 | "version": "1.0.3",
11 | "unity": "2018.4",
12 | "license": "LICENSE.md",
13 | "readme": "README.md"
14 | }
15 |
--------------------------------------------------------------------------------
/package.json.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 58fc6d79371bc73458edfc66080955ec
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------