Add StickGame Assets
This commit is contained in:
@@ -0,0 +1,255 @@
|
||||
using FishNet.Managing.Object;
|
||||
using FishNet.Object;
|
||||
using GameKit.Utilities;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Utility.Performance
|
||||
{
|
||||
|
||||
|
||||
public class DefaultObjectPool : ObjectPool
|
||||
{
|
||||
#region Public.
|
||||
/// <summary>
|
||||
/// Cache for pooled NetworkObjects.
|
||||
/// </summary> //Remove on 2024/01/01 Convert to IReadOnlyList.
|
||||
public IReadOnlyCollection<Dictionary<int, Stack<NetworkObject>>> Cache => _cache;
|
||||
private List<Dictionary<int, Stack<NetworkObject>>> _cache = new List<Dictionary<int, Stack<NetworkObject>>>();
|
||||
#endregion
|
||||
|
||||
#region Serialized.
|
||||
/// <summary>
|
||||
/// True if to use object pooling.
|
||||
/// </summary>
|
||||
[Tooltip("True if to use object pooling.")]
|
||||
[SerializeField]
|
||||
private bool _enabled = true;
|
||||
#endregion
|
||||
|
||||
#region Private.
|
||||
/// <summary>
|
||||
/// Current count of the cache collection.
|
||||
/// </summary>
|
||||
private int _cacheCount = 0;
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Returns an object that has been stored with a collectionId of 0. A new object will be created if no stored objects are available.
|
||||
/// </summary>
|
||||
/// <param name="prefabId">PrefabId of the object to return.</param>
|
||||
/// <param name="asServer">True if being called on the server side.</param>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] //Remove on 2024/01/01.
|
||||
#pragma warning disable CS0672 // Member overrides obsolete member
|
||||
public override NetworkObject RetrieveObject(int prefabId, bool asServer)
|
||||
#pragma warning restore CS0672 // Member overrides obsolete member
|
||||
{
|
||||
return RetrieveObject(prefabId, 0, asServer);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns an object that has been stored. A new object will be created if no stored objects are available.
|
||||
/// </summary>
|
||||
/// <param name="prefabId">PrefabId of the object to return.</param>
|
||||
/// <param name="collectionId">CollectionId of the prefab.</param>
|
||||
/// <param name="position">Position for object before enabling it.</param>
|
||||
/// <param name="rotation">Rotation for object before enabling it.</param>
|
||||
/// <param name="asServer">True if being called on the server side.</param>
|
||||
/// <returns></returns>
|
||||
public override NetworkObject RetrieveObject(int prefabId, ushort collectionId, Vector3 position, Quaternion rotation, bool asServer)
|
||||
{
|
||||
PrefabObjects po = base.NetworkManager.GetPrefabObjects<PrefabObjects>(collectionId, false);
|
||||
//Quick exit/normal retrieval when not using pooling.
|
||||
if (!_enabled)
|
||||
{
|
||||
NetworkObject prefab = po.GetObject(asServer, prefabId);
|
||||
return Instantiate(prefab, position, rotation);
|
||||
}
|
||||
|
||||
Stack<NetworkObject> cache = GetOrCreateCache(collectionId, prefabId);
|
||||
NetworkObject nob;
|
||||
//Iterate until nob is populated just in case cache entries have been destroyed.
|
||||
do
|
||||
{
|
||||
if (cache.Count == 0)
|
||||
{
|
||||
NetworkObject prefab = po.GetObject(asServer, prefabId);
|
||||
/* A null nob should never be returned from spawnables. This means something
|
||||
* else broke, likely unrelated to the object pool. */
|
||||
nob = Instantiate(prefab, position, rotation);
|
||||
//Can break instantly since we know nob is not null.
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
nob = cache.Pop();
|
||||
if (nob != null)
|
||||
nob.transform.SetPositionAndRotation(position, rotation);
|
||||
}
|
||||
|
||||
} while (nob == null);
|
||||
|
||||
nob.gameObject.SetActive(true);
|
||||
return nob;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns an object that has been stored. A new object will be created if no stored objects are available.
|
||||
/// </summary>
|
||||
/// <param name="prefabId">PrefabId of the object to return.</param>
|
||||
/// <param name="collectionId">CollectionId of the prefab.</param>
|
||||
/// <param name="asServer">True if being called on the server side.</param>
|
||||
/// <returns></returns>
|
||||
public override NetworkObject RetrieveObject(int prefabId, ushort collectionId, bool asServer)
|
||||
{
|
||||
PrefabObjects po = base.NetworkManager.GetPrefabObjects<PrefabObjects>(collectionId, false);
|
||||
//Quick exit/normal retrieval when not using pooling.
|
||||
if (!_enabled)
|
||||
{
|
||||
NetworkObject prefab = po.GetObject(asServer, prefabId);
|
||||
return Instantiate(prefab);
|
||||
}
|
||||
|
||||
Stack<NetworkObject> cache = GetOrCreateCache(collectionId, prefabId);
|
||||
NetworkObject nob;
|
||||
//Iterate until nob is populated just in case cache entries have been destroyed.
|
||||
do
|
||||
{
|
||||
if (cache.Count == 0)
|
||||
{
|
||||
NetworkObject prefab = po.GetObject(asServer, prefabId);
|
||||
/* A null nob should never be returned from spawnables. This means something
|
||||
* else broke, likely unrelated to the object pool. */
|
||||
nob = Instantiate(prefab);
|
||||
//Can break instantly since we know nob is not null.
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
nob = cache.Pop();
|
||||
}
|
||||
|
||||
} while (nob == null);
|
||||
|
||||
nob.gameObject.SetActive(true);
|
||||
return nob;
|
||||
}
|
||||
/// <summary>
|
||||
/// Stores an object into the pool.
|
||||
/// </summary>
|
||||
/// <param name="instantiated">Object to store.</param>
|
||||
/// <param name="asServer">True if being called on the server side.</param>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void StoreObject(NetworkObject instantiated, bool asServer)
|
||||
{
|
||||
//Pooling is not enabled.
|
||||
if (!_enabled)
|
||||
{
|
||||
Destroy(instantiated.gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
instantiated.gameObject.SetActive(false);
|
||||
instantiated.ResetState();
|
||||
Stack<NetworkObject> cache = GetOrCreateCache(instantiated.SpawnableCollectionId, instantiated.PrefabId);
|
||||
cache.Push(instantiated);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a number of objects and adds them to the pool.
|
||||
/// </summary>
|
||||
/// <param name="prefab">Prefab to cache.</param>
|
||||
/// <param name="count">Quantity to spawn.</param>
|
||||
/// <param name="asServer">True if storing prefabs for the server collection. This is only applicable when using DualPrefabObjects.</param>
|
||||
public override void CacheObjects(NetworkObject prefab, int count, bool asServer)
|
||||
{
|
||||
if (!_enabled)
|
||||
return;
|
||||
if (count <= 0)
|
||||
return;
|
||||
if (prefab == null)
|
||||
return;
|
||||
if (prefab.PrefabId == NetworkObject.UNSET_PREFABID_VALUE)
|
||||
{
|
||||
InstanceFinder.NetworkManager.LogError($"Pefab {prefab.name} has an invalid prefabId and cannot be cached.");
|
||||
return;
|
||||
}
|
||||
|
||||
Stack<NetworkObject> cache = GetOrCreateCache(prefab.SpawnableCollectionId, prefab.PrefabId);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
NetworkObject nob = Instantiate(prefab);
|
||||
nob.gameObject.SetActive(false);
|
||||
cache.Push(nob);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears pools destroying objects for all collectionIds
|
||||
/// </summary>
|
||||
public void ClearPool()
|
||||
{
|
||||
int count = _cache.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
ClearPool(i);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears a pool destroying objects for collectionId.
|
||||
/// </summary>
|
||||
/// <param name="collectionId">CollectionId to clear for.</param>
|
||||
public void ClearPool(int collectionId)
|
||||
{
|
||||
if (collectionId >= _cacheCount)
|
||||
return;
|
||||
|
||||
Dictionary<int, Stack<NetworkObject>> dict = _cache[collectionId];
|
||||
foreach (Stack<NetworkObject> item in dict.Values)
|
||||
{
|
||||
while (item.Count > 0)
|
||||
{
|
||||
NetworkObject nob = item.Pop();
|
||||
if (nob != null)
|
||||
Destroy(nob.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
dict.Clear();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a cache for an id or creates one if does not exist.
|
||||
/// </summary>
|
||||
/// <param name="prefabId"></param>
|
||||
/// <returns></returns>
|
||||
private Stack<NetworkObject> GetOrCreateCache(int collectionId, int prefabId)
|
||||
{
|
||||
if (collectionId >= _cacheCount)
|
||||
{
|
||||
//Add more to the cache.
|
||||
while (_cache.Count <= collectionId)
|
||||
{
|
||||
Dictionary<int, Stack<NetworkObject>> dict = new Dictionary<int, Stack<NetworkObject>>();
|
||||
_cache.Add(dict);
|
||||
}
|
||||
_cacheCount = collectionId;
|
||||
}
|
||||
|
||||
Dictionary<int, Stack<NetworkObject>> dictionary = _cache[collectionId];
|
||||
Stack<NetworkObject> cache;
|
||||
//No cache for prefabId yet, make one.
|
||||
if (!dictionary.TryGetValueIL2CPP(prefabId, out cache))
|
||||
{
|
||||
cache = new Stack<NetworkObject>();
|
||||
dictionary[prefabId] = cache;
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user