Skip to content

Commit 79f5c5e

Browse files
Merge pull request #863 from isaiahgrant/main
Return cached objects when pooling
2 parents b4b00df + f2b44a4 commit 79f5c5e

File tree

1 file changed

+1
-321
lines changed

1 file changed

+1
-321
lines changed
Lines changed: 1 addition & 321 deletions
Original file line numberDiff line numberDiff line change
@@ -1,321 +1 @@
1-
using FishNet.Managing;
2-
using FishNet.Managing.Object;
3-
using FishNet.Object;
4-
using FishNet.Utility.Extension;
5-
using GameKit.Dependencies.Utilities;
6-
using System;
7-
using System.Collections.Generic;
8-
using System.Runtime.CompilerServices;
9-
using UnityEngine;
10-
11-
namespace FishNet.Utility.Performance
12-
{
13-
public class DefaultObjectPool : ObjectPool
14-
{
15-
#region Public.
16-
/// <summary>
17-
/// Cache for pooled NetworkObjects.
18-
/// Key: CollectionId.
19-
/// </summary>
20-
public IReadOnlyList<Dictionary<int, Stack<NetworkObject>>> Cache => _cache;
21-
private List<Dictionary<int, Stack<NetworkObject>>> _cache = new();
22-
#endregion
23-
24-
#region Serialized.
25-
/// <summary>
26-
/// True if to use object pooling.
27-
/// </summary>
28-
[Tooltip("True if to use object pooling.")]
29-
[SerializeField]
30-
private bool _enabled = true;
31-
#endregion
32-
33-
#region Private.
34-
/// <summary>
35-
/// Current count of the cache collection.
36-
/// </summary>
37-
private int _cacheCount = 0;
38-
#endregion
39-
40-
#pragma warning disable CS0672 // Member overrides obsolete member
41-
public override NetworkObject RetrieveObject(int prefabId, ushort collectionId, Transform parent = null, Vector3? nullablePosition = null, Quaternion? nullableRotation = null, Vector3? nullableScale = null, bool makeActive = true, bool asServer = true)
42-
#pragma warning restore CS0672 // Member overrides obsolete member
43-
{
44-
ObjectPoolRetrieveOption options = ObjectPoolRetrieveOption.Unset;
45-
if (makeActive)
46-
options |= ObjectPoolRetrieveOption.MakeActive;
47-
48-
return RetrieveObject(prefabId, collectionId, options, parent, nullablePosition, nullableRotation, nullableScale, asServer);
49-
}
50-
51-
/// <summary>
52-
/// Returns an object that has been stored. A new object will be created if no stored objects are available.
53-
/// </summary>
54-
/// <param name="prefabId">PrefabId of the object to return.</param>
55-
/// <param name="collectionId">CollectionId of the object to return.</param>
56-
/// <param name="asServer">True if being called on the server side.</param>
57-
/// <returns></returns>
58-
public override NetworkObject RetrieveObject(int prefabId, ushort collectionId, ObjectPoolRetrieveOption options, Transform parent = null, Vector3? nullablePosition = null, Quaternion? nullableRotation = null, Vector3? nullableScale = null, bool asServer = true)
59-
{
60-
bool makeActive = options.FastContains(ObjectPoolRetrieveOption.MakeActive);
61-
bool localSpace = options.FastContains(ObjectPoolRetrieveOption.LocalSpace);
62-
63-
if (!_enabled)
64-
return GetFromInstantiate();
65-
66-
Stack<NetworkObject> cache = GetCache(collectionId, prefabId, createIfMissing: true);
67-
NetworkObject nob = null;
68-
69-
//Iterate until nob is populated just in case cache entries have been destroyed.
70-
while (nob == null)
71-
{
72-
if (cache.TryPop(out nob))
73-
{
74-
if (nob != null)
75-
{
76-
nob.transform.SetParent(parent);
77-
if (localSpace)
78-
nob.transform.SetLocalPositionRotationAndScale(nullablePosition, nullableRotation, nullableScale);
79-
else
80-
nob.transform.SetWorldPositionRotationAndScale(nullablePosition, nullableRotation, nullableScale);
81-
82-
if (makeActive)
83-
nob.gameObject.SetActive(true);
84-
85-
return nob;
86-
}
87-
}
88-
//Nothing left in cache.
89-
else
90-
{
91-
break;
92-
}
93-
}
94-
95-
//Fall through, nothing in cache.
96-
return GetFromInstantiate();
97-
98-
//Returns a network object via instantation.
99-
NetworkObject GetFromInstantiate()
100-
{
101-
NetworkObject prefab = GetPrefab(prefabId, collectionId, asServer);
102-
if (prefab == null)
103-
{
104-
return null;
105-
}
106-
else
107-
{
108-
NetworkObject result;
109-
Vector3 scale;
110-
111-
if (localSpace)
112-
{
113-
prefab.transform.OutLocalPropertyValues(nullablePosition, nullableRotation, nullableScale, out Vector3 pos, out Quaternion rot, out scale);
114-
if (parent != null)
115-
{
116-
//Convert pos and rot to world values for the instantiate.
117-
pos = parent.TransformPoint(pos);
118-
rot = (parent.rotation * rot);
119-
}
120-
result = Instantiate(prefab, pos, rot, parent);
121-
}
122-
else
123-
{
124-
prefab.transform.OutWorldPropertyValues(nullablePosition, nullableRotation, nullableScale, out Vector3 pos, out Quaternion rot, out scale);
125-
result = Instantiate(prefab, pos, rot, parent);
126-
}
127-
128-
result.transform.localScale = scale;
129-
130-
if (makeActive)
131-
result.gameObject.SetActive(true);
132-
return result;
133-
}
134-
}
135-
}
136-
137-
/// <summary>
138-
/// Returns a prefab for prefab and collectionId.
139-
/// </summary>
140-
public override NetworkObject GetPrefab(int prefabId, ushort collectionId, bool asServer)
141-
{
142-
PrefabObjects po = base.NetworkManager.GetPrefabObjects<PrefabObjects>(collectionId, false);
143-
return po.GetObject(asServer, prefabId);
144-
}
145-
146-
/// <summary>
147-
/// Stores an object into the pool.
148-
/// </summary>
149-
/// <param name="instantiated">Object to store.</param>
150-
/// <param name="asServer">True if being called on the server side.</param>
151-
/// <returns></returns>
152-
public override void StoreObject(NetworkObject instantiated, bool asServer)
153-
{
154-
//Pooling is not enabled.
155-
if (!_enabled)
156-
{
157-
Destroy(instantiated.gameObject);
158-
return;
159-
}
160-
161-
//Get all children as well and reset state on them.
162-
List<NetworkObject> nestedNobs = instantiated.GetNetworkObjects(GetNetworkObjectOption.All);
163-
164-
foreach (NetworkObject nob in nestedNobs)
165-
nob.ResetState(asServer);
166-
167-
CollectionCaches<NetworkObject>.Store(nestedNobs);
168-
169-
//Set root inactive.
170-
instantiated.gameObject.SetActive(false);
171-
172-
Stack<NetworkObject> cache = GetCache(instantiated.SpawnableCollectionId, instantiated.PrefabId, createIfMissing: true);
173-
cache.Push(instantiated);
174-
}
175-
176-
/// <summary>
177-
/// Instantiates a number of objects and adds them to the pool.
178-
/// </summary>
179-
/// <param name="prefab">Prefab to cache.</param>
180-
/// <param name="count">Quantity to spawn.</param>
181-
/// <param name="asServer">True if storing prefabs for the server collection. This is only applicable when using DualPrefabObjects.</param>
182-
#pragma warning disable CS0672 // Member overrides obsolete member
183-
public override void CacheObjects(NetworkObject prefab, int count, bool asServer) => StorePrefabObjects(prefab, count, asServer);
184-
#pragma warning restore CS0672 // Member overrides obsolete member
185-
186-
/// <summary>
187-
/// Instantiates a number of objects and adds them to the pool.
188-
/// </summary>
189-
/// <param name="prefab">Prefab to cache.</param>
190-
/// <param name="count">Quantity to spawn.</param>
191-
/// <param name="asServer">True if storing prefabs for the server collection. This is only applicable when using DualPrefabObjects.</param>
192-
/// <returns>Prefabs instantiated and added to cache.</returns>
193-
public override List<NetworkObject> StorePrefabObjects(NetworkObject prefab, int count, bool asServer)
194-
{
195-
if (!_enabled)
196-
return null;
197-
if (count <= 0)
198-
return null;
199-
if (prefab == null)
200-
return null;
201-
if (prefab.PrefabId == NetworkObject.UNSET_PREFABID_VALUE)
202-
{
203-
NetworkManagerExtensions.LogError($"Pefab {prefab.name} has an invalid prefabId and cannot be cached.");
204-
return null;
205-
}
206-
207-
List<NetworkObject> added = new();
208-
Stack<NetworkObject> cache = GetCache(prefab.SpawnableCollectionId, prefab.PrefabId, createIfMissing: true);
209-
210-
for (int i = 0; i < count; i++)
211-
{
212-
NetworkObject nob = Instantiate(prefab);
213-
nob.gameObject.SetActive(false);
214-
cache.Push(nob);
215-
added.Add(nob);
216-
}
217-
218-
return added;
219-
}
220-
221-
/// <summary>
222-
/// Clears pooled objects for a specific NetworkObject.
223-
/// </summary>
224-
/// <param name="nob">Prefab or Instantiated NetworkObject to clear pool for.</param>
225-
/// <remarks>This will clear the entire pool for the specified object.</remarks>
226-
public void ClearPool(NetworkObject nob)
227-
{
228-
if (!_enabled)
229-
return;
230-
if (nob == null)
231-
return;
232-
233-
int spawnableCollectionId = nob.SpawnableCollectionId;
234-
Stack<NetworkObject> stack = GetCache(spawnableCollectionId, nob.PrefabId, createIfMissing: false);
235-
if (stack == null)
236-
return;
237-
238-
DestroyStackNetworkObjectsAndClear(stack);
239-
_cache[spawnableCollectionId].Clear();
240-
}
241-
242-
/// <summary>
243-
/// Clears all pooled objects.
244-
/// </summary>
245-
public void ClearPool()
246-
{
247-
int count = _cache.Count;
248-
for (int i = 0; i < count; i++)
249-
ClearPool(i);
250-
}
251-
252-
/// <summary>
253-
/// Clears a pool destroying objects for a SpawnableCollectionId.
254-
/// </summary>
255-
/// <param name="spawnableCollectionId">CollectionId to clear for.</param>
256-
public void ClearPool(int spawnableCollectionId)
257-
{
258-
if (spawnableCollectionId >= _cacheCount)
259-
return;
260-
261-
Dictionary<int, Stack<NetworkObject>> dict = _cache[spawnableCollectionId];
262-
263-
foreach (Stack<NetworkObject> item in dict.Values)
264-
DestroyStackNetworkObjectsAndClear(item);
265-
266-
dict.Clear();
267-
}
268-
269-
/// <summary>
270-
/// Gets a cache for an id or creates one if does not exist.
271-
/// </summary>
272-
/// <returns></returns>
273-
public Stack<NetworkObject> GetCache(int collectionId, int prefabId, bool createIfMissing)
274-
{
275-
if (collectionId >= _cacheCount)
276-
{
277-
//Do not create if missing.
278-
if (!createIfMissing)
279-
return null;
280-
281-
//Add more to the cache.
282-
while (_cache.Count <= collectionId)
283-
{
284-
Dictionary<int, Stack<NetworkObject>> dict = new();
285-
_cache.Add(dict);
286-
}
287-
_cacheCount = collectionId;
288-
}
289-
290-
Dictionary<int, Stack<NetworkObject>> dictionary = _cache[collectionId];
291-
//No cache for prefabId yet, make one.
292-
if (!dictionary.TryGetValueIL2CPP(prefabId, out Stack<NetworkObject> cache))
293-
{
294-
if (createIfMissing)
295-
{
296-
cache = new();
297-
dictionary[prefabId] = cache;
298-
}
299-
}
300-
301-
return cache;
302-
}
303-
304-
[Obsolete("Use GetCache(int, int, bool)")]
305-
public Stack<NetworkObject> GetOrCreateCache(int collectionId, int prefabId) => GetCache(collectionId, prefabId, createIfMissing: true);
306-
307-
/// <summary>
308-
/// Destroys all NetworkObjects within a stack and clears the stack.
309-
/// </summary>
310-
private void DestroyStackNetworkObjectsAndClear(Stack<NetworkObject> stack)
311-
{
312-
foreach (NetworkObject networkObject in stack)
313-
{
314-
if (networkObject != null)
315-
Destroy(networkObject.gameObject);
316-
}
317-
318-
stack.Clear();
319-
}
320-
}
321-
}
1+
//Clearing for merge.

0 commit comments

Comments
 (0)