[Add] FishNet
This commit is contained in:
@@ -0,0 +1,230 @@
|
||||
// using System; // Remove on V5
|
||||
|
||||
// namespace FishNet.Utility.Performance
|
||||
// {
|
||||
|
||||
// /// <summary>
|
||||
// /// Unity 2022 has a bug where codegen will not compile when referencing a Queue type,
|
||||
// /// while also targeting .Net as the framework API.
|
||||
// /// As a work around this class is used for queues instead.
|
||||
// /// </summary>
|
||||
// public class BasicQueue<T>
|
||||
// {
|
||||
// /// <summary>
|
||||
// /// Maximum size of the collection.
|
||||
// /// </summary>
|
||||
// public int Capacity => Collection.Length;
|
||||
// /// <summary>
|
||||
// /// Number of elements in the queue.
|
||||
// /// </summary>
|
||||
// public int Count => _written;
|
||||
// /// <summary>
|
||||
// /// Collection containing data.
|
||||
// /// </summary>
|
||||
// private T[] Collection = new T[4];
|
||||
// /// <summary>
|
||||
// /// Current write index of the collection.
|
||||
// /// </summary>
|
||||
// public int WriteIndex { get; private set; }
|
||||
// /// <summary>
|
||||
// /// Buffer for resizing.
|
||||
// /// </summary>
|
||||
// private T[] _resizeBuffer = new T[0];
|
||||
// /// <summary>
|
||||
// /// Read position of the next Dequeue.
|
||||
// /// </summary>
|
||||
// private int _read;
|
||||
|
||||
// /// <summary>
|
||||
// /// Length of the queue.
|
||||
// /// </summary>
|
||||
// private int _written;
|
||||
|
||||
// /// <summary>
|
||||
// /// Enqueues an entry.
|
||||
// /// </summary>
|
||||
// /// <param name="data"></param>
|
||||
// public void Enqueue(T data)
|
||||
// {
|
||||
// if (_written == Collection.Length)
|
||||
// Resize();
|
||||
|
||||
// if (WriteIndex >= Collection.Length)
|
||||
// WriteIndex = 0;
|
||||
// Collection[WriteIndex] = data;
|
||||
|
||||
// WriteIndex++;
|
||||
// _written++;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Tries to dequeue the next entry.
|
||||
// /// </summary>
|
||||
// /// <param name="result">Dequeued entry.</param>
|
||||
// /// <returns>True if an entry existed to dequeue.</returns>
|
||||
// public bool TryDequeue(out T result)
|
||||
// {
|
||||
// if (_written == 0)
|
||||
// {
|
||||
// result = default;
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// result = Dequeue();
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Dequeues the next entry.
|
||||
// /// </summary>
|
||||
// /// <returns></returns>
|
||||
// public T Dequeue()
|
||||
// {
|
||||
// if (_written == 0)
|
||||
// throw new Exception($"Queue of type {typeof(T).Name} is empty.");
|
||||
|
||||
// T result = Collection[_read];
|
||||
|
||||
// _written--;
|
||||
// _read++;
|
||||
// if (_read >= Collection.Length)
|
||||
// _read = 0;
|
||||
|
||||
// return result;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Tries to peek the next entry.
|
||||
// /// </summary>
|
||||
// /// <param name="result">Peeked entry.</param>
|
||||
// /// <returns>True if an entry existed to peek.</returns>
|
||||
// public bool TryPeek(out T result)
|
||||
// {
|
||||
// if (_written == 0)
|
||||
// {
|
||||
// result = default;
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// result = Peek();
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Peeks the next queue entry.
|
||||
// /// </summary>
|
||||
// /// <returns></returns>
|
||||
// public T Peek()
|
||||
// {
|
||||
// if (_written == 0)
|
||||
// throw new Exception($"Queue of type {typeof(T).Name} is empty.");
|
||||
|
||||
// return Collection[_read];
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Clears the queue.
|
||||
// /// </summary>
|
||||
// public void Clear()
|
||||
// {
|
||||
// _read = 0;
|
||||
// WriteIndex = 0;
|
||||
// _written = 0;
|
||||
|
||||
// DefaultCollection(Collection);
|
||||
// DefaultCollection(_resizeBuffer);
|
||||
|
||||
// void DefaultCollection(T[] array)
|
||||
// {
|
||||
// int count = array.Length;
|
||||
// for (int i = 0; i < count; i++)
|
||||
// array[i] = default;
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Doubles the queue size.
|
||||
// /// </summary>
|
||||
// private void Resize()
|
||||
// {
|
||||
// int length = _written;
|
||||
// int doubleLength = (length * 2);
|
||||
// int read = _read;
|
||||
|
||||
// /* Make sure copy array is the same size as current
|
||||
// * and copy contents into it. */
|
||||
// // Ensure large enough to fit contents.
|
||||
// T[] resizeBuffer = _resizeBuffer;
|
||||
// if (resizeBuffer.Length < doubleLength)
|
||||
// Array.Resize(ref resizeBuffer, doubleLength);
|
||||
// // Copy from the read of queue first.
|
||||
// int copyLength = (length - read);
|
||||
// Array.Copy(Collection, read, resizeBuffer, 0, copyLength);
|
||||
// /* If read index was higher than 0
|
||||
// * then copy remaining data as well from 0. */
|
||||
// if (read > 0)
|
||||
// Array.Copy(Collection, 0, resizeBuffer, copyLength, read);
|
||||
|
||||
// // Set _array to resize.
|
||||
// Collection = resizeBuffer;
|
||||
// // Reset positions.
|
||||
// _read = 0;
|
||||
// WriteIndex = length;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Returns value in actual index as it relates to simulated index.
|
||||
// /// </summary>
|
||||
// /// <param name="simulatedIndex">Simulated index to return. A value of 0 would return the first simulated index in the collection.</param>
|
||||
// /// <returns></returns>
|
||||
// public T this[int simulatedIndex]
|
||||
// {
|
||||
// get
|
||||
// {
|
||||
// int offset = GetRealIndex(simulatedIndex);
|
||||
// return Collection[offset];
|
||||
// }
|
||||
// set
|
||||
// {
|
||||
// int offset = GetRealIndex(simulatedIndex);
|
||||
// Collection[offset] = value;
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Returns the real index of the collection using a simulated index.
|
||||
// /// </summary>
|
||||
// /// <param name="allowUnusedBuffer">True to allow an index be returned from an unused portion of the buffer so long as it is within bounds.</param>
|
||||
// private int GetRealIndex(int simulatedIndex, bool allowUnusedBuffer = false)
|
||||
// {
|
||||
// if (simulatedIndex >= Capacity)
|
||||
// {
|
||||
// return ReturnError();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// int written = _written;
|
||||
// // May be out of bounds if allowUnusedBuffer is false.
|
||||
// if (simulatedIndex >= written)
|
||||
// {
|
||||
// if (!allowUnusedBuffer)
|
||||
// return ReturnError();
|
||||
// }
|
||||
// int offset = (Capacity - written) + simulatedIndex + WriteIndex;
|
||||
// if (offset >= Capacity)
|
||||
// offset -= Capacity;
|
||||
|
||||
// return offset;
|
||||
// }
|
||||
|
||||
// int ReturnError()
|
||||
// {
|
||||
// UnityEngine.Debug.LogError($"Index {simulatedIndex} is out of range. Collection count is {_written}, Capacity is {Capacity}");
|
||||
// return -1;
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7c0a46ad871780b45bfe317c8f904322
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Utility/Performance/BasicQueue.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FishNet.Utility.Performance
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves and stores byte arrays using a pooling system.
|
||||
/// </summary>
|
||||
public static class ByteArrayPool
|
||||
{
|
||||
/// <summary>
|
||||
/// Stored byte arrays.
|
||||
/// </summary>
|
||||
private static Queue<byte[]> _byteArrays = new();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a byte array which will be of at lesat minimum length. The returned array must manually be stored.
|
||||
/// </summary>
|
||||
public static byte[] Retrieve(int minimumLength)
|
||||
{
|
||||
byte[] result = null;
|
||||
|
||||
if (_byteArrays.Count > 0)
|
||||
result = _byteArrays.Dequeue();
|
||||
|
||||
int doubleMinimumLength = minimumLength * 2;
|
||||
if (result == null)
|
||||
result = new byte[doubleMinimumLength];
|
||||
else if (result.Length < minimumLength)
|
||||
Array.Resize(ref result, doubleMinimumLength);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a byte array for re-use.
|
||||
/// </summary>
|
||||
public static void Store(byte[] buffer)
|
||||
{
|
||||
/* Holy cow that's a lot of buffered
|
||||
* buffers. This wouldn't happen under normal
|
||||
* circumstances but if the user is stress
|
||||
* testing connections in one executable perhaps. */
|
||||
if (_byteArrays.Count > 300)
|
||||
return;
|
||||
_byteArrays.Enqueue(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c7620a5e6fedc18408f8f04821b35bbd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Utility/Performance/ByteArrayPool.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,326 @@
|
||||
using FishNet.Managing;
|
||||
using FishNet.Managing.Object;
|
||||
using FishNet.Object;
|
||||
using FishNet.Utility.Extension;
|
||||
using GameKit.Dependencies.Utilities;
|
||||
using System;
|
||||
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.
|
||||
/// Key: CollectionId.
|
||||
/// </summary>
|
||||
public IReadOnlyList<Dictionary<int, Stack<NetworkObject>>> Cache => _cache;
|
||||
private List<Dictionary<int, Stack<NetworkObject>>> _cache = new();
|
||||
#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
|
||||
|
||||
#pragma warning disable CS0672 // Member overrides obsolete member
|
||||
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)
|
||||
#pragma warning restore CS0672 // Member overrides obsolete member
|
||||
{
|
||||
ObjectPoolRetrieveOption options = ObjectPoolRetrieveOption.Unset;
|
||||
if (makeActive)
|
||||
options |= ObjectPoolRetrieveOption.MakeActive;
|
||||
|
||||
return RetrieveObject(prefabId, collectionId, options, parent, nullablePosition, nullableRotation, nullableScale, 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 object to return.</param>
|
||||
/// <param name = "asServer">True if being called on the server side.</param>
|
||||
/// <returns></returns>
|
||||
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)
|
||||
{
|
||||
bool makeActive = options.FastContains(ObjectPoolRetrieveOption.MakeActive);
|
||||
bool localSpace = options.FastContains(ObjectPoolRetrieveOption.LocalSpace);
|
||||
|
||||
if (!_enabled)
|
||||
return GetFromInstantiate();
|
||||
|
||||
Stack<NetworkObject> cache = GetCache(collectionId, prefabId, createIfMissing: true);
|
||||
NetworkObject nob = null;
|
||||
|
||||
// Iterate until nob is populated just in case cache entries have been destroyed.
|
||||
while (nob == null)
|
||||
{
|
||||
if (cache.TryPop(out nob))
|
||||
{
|
||||
if (nob != null)
|
||||
{
|
||||
nob.transform.SetParent(parent);
|
||||
if (localSpace)
|
||||
nob.transform.SetLocalPositionRotationAndScale(nullablePosition, nullableRotation, nullableScale);
|
||||
else
|
||||
nob.transform.SetWorldPositionRotationAndScale(nullablePosition, nullableRotation, nullableScale);
|
||||
|
||||
if (makeActive)
|
||||
nob.gameObject.SetActive(true);
|
||||
|
||||
return nob;
|
||||
}
|
||||
}
|
||||
// Nothing left in cache.
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Fall through, nothing in cache.
|
||||
return GetFromInstantiate();
|
||||
|
||||
// Returns a network object via instantation.
|
||||
NetworkObject GetFromInstantiate()
|
||||
{
|
||||
NetworkObject prefab = GetPrefab(prefabId, collectionId, asServer);
|
||||
if (prefab == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
NetworkObject result;
|
||||
Vector3 scale;
|
||||
|
||||
if (localSpace)
|
||||
{
|
||||
prefab.transform.OutLocalPropertyValues(nullablePosition, nullableRotation, nullableScale, out Vector3 pos, out Quaternion rot, out scale);
|
||||
if (parent != null)
|
||||
{
|
||||
// Convert pos and rot to world values for the instantiate.
|
||||
pos = parent.TransformPoint(pos);
|
||||
rot = parent.rotation * rot;
|
||||
}
|
||||
result = Instantiate(prefab, pos, rot, parent);
|
||||
}
|
||||
else
|
||||
{
|
||||
prefab.transform.OutWorldPropertyValues(nullablePosition, nullableRotation, nullableScale, out Vector3 pos, out Quaternion rot, out scale);
|
||||
result = Instantiate(prefab, pos, rot, parent);
|
||||
}
|
||||
|
||||
result.transform.localScale = scale;
|
||||
|
||||
if (makeActive)
|
||||
result.gameObject.SetActive(true);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a prefab for prefab and collectionId.
|
||||
/// </summary>
|
||||
public override NetworkObject GetPrefab(int prefabId, ushort collectionId, bool asServer)
|
||||
{
|
||||
PrefabObjects po = NetworkManager.GetPrefabObjects<PrefabObjects>(collectionId, false);
|
||||
return po.GetObject(asServer, prefabId);
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public override void StoreObject(NetworkObject instantiated, bool asServer)
|
||||
{
|
||||
// Pooling is not enabled.
|
||||
if (!_enabled)
|
||||
{
|
||||
Destroy(instantiated.gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
/* This call occurs here rather than in the object pool
|
||||
* to protect the user should they be using a
|
||||
* custom pool. */
|
||||
SetTransformToSerializedValues(instantiated);
|
||||
|
||||
// Get all children as well and reset state on them.
|
||||
List<NetworkObject> nestedNobs = instantiated.GetNetworkObjects(GetNetworkObjectOption.All);
|
||||
|
||||
foreach (NetworkObject nob in nestedNobs)
|
||||
nob.ResetState(asServer);
|
||||
|
||||
CollectionCaches<NetworkObject>.Store(nestedNobs);
|
||||
|
||||
// Set root inactive.
|
||||
instantiated.gameObject.SetActive(false);
|
||||
|
||||
Stack<NetworkObject> cache = GetCache(instantiated.SpawnableCollectionId, instantiated.PrefabId, createIfMissing: true);
|
||||
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>
|
||||
#pragma warning disable CS0672 // Member overrides obsolete member
|
||||
public override void CacheObjects(NetworkObject prefab, int count, bool asServer) => StorePrefabObjects(prefab, count, asServer);
|
||||
#pragma warning restore CS0672 // Member overrides obsolete member
|
||||
|
||||
/// <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>
|
||||
/// <returns>Prefabs instantiated and added to cache.</returns>
|
||||
public override List<NetworkObject> StorePrefabObjects(NetworkObject prefab, int count, bool asServer)
|
||||
{
|
||||
if (!_enabled)
|
||||
return null;
|
||||
if (count <= 0)
|
||||
return null;
|
||||
if (prefab == null)
|
||||
return null;
|
||||
if (prefab.PrefabId == NetworkObject.UNSET_PREFABID_VALUE)
|
||||
{
|
||||
NetworkManager.LogError($"Pefab {prefab.name} has an invalid prefabId and cannot be cached.");
|
||||
return null;
|
||||
}
|
||||
|
||||
List<NetworkObject> added = new();
|
||||
Stack<NetworkObject> cache = GetCache(prefab.SpawnableCollectionId, prefab.PrefabId, createIfMissing: true);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
NetworkObject nob = Instantiate(prefab);
|
||||
nob.gameObject.SetActive(false);
|
||||
cache.Push(nob);
|
||||
added.Add(nob);
|
||||
}
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears pooled objects for a specific NetworkObject.
|
||||
/// </summary>
|
||||
/// <param name = "nob">Prefab or Instantiated NetworkObject to clear pool for.</param>
|
||||
/// <remarks>This will clear the entire pool for the specified object.</remarks>
|
||||
public void ClearPool(NetworkObject nob)
|
||||
{
|
||||
if (!_enabled)
|
||||
return;
|
||||
if (nob == null)
|
||||
return;
|
||||
|
||||
int spawnableCollectionId = nob.SpawnableCollectionId;
|
||||
Stack<NetworkObject> stack = GetCache(spawnableCollectionId, nob.PrefabId, createIfMissing: false);
|
||||
if (stack == null)
|
||||
return;
|
||||
|
||||
DestroyStackNetworkObjectsAndClear(stack);
|
||||
_cache[spawnableCollectionId].Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all pooled objects.
|
||||
/// </summary>
|
||||
public void ClearPool()
|
||||
{
|
||||
int count = _cache.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
ClearPool(i);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears a pool destroying objects for a SpawnableCollectionId.
|
||||
/// </summary>
|
||||
/// <param name = "spawnableCollectionId">CollectionId to clear for.</param>
|
||||
public void ClearPool(int spawnableCollectionId)
|
||||
{
|
||||
if (spawnableCollectionId >= _cacheCount)
|
||||
return;
|
||||
|
||||
Dictionary<int, Stack<NetworkObject>> dict = _cache[spawnableCollectionId];
|
||||
|
||||
foreach (Stack<NetworkObject> item in dict.Values)
|
||||
DestroyStackNetworkObjectsAndClear(item);
|
||||
|
||||
dict.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a cache for an id or creates one if does not exist.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Stack<NetworkObject> GetCache(int collectionId, int prefabId, bool createIfMissing)
|
||||
{
|
||||
if (collectionId >= _cacheCount)
|
||||
{
|
||||
// Do not create if missing.
|
||||
if (!createIfMissing)
|
||||
return null;
|
||||
|
||||
// Add more to the cache.
|
||||
while (_cache.Count <= collectionId)
|
||||
{
|
||||
Dictionary<int, Stack<NetworkObject>> dict = new();
|
||||
_cache.Add(dict);
|
||||
}
|
||||
_cacheCount = _cache.Count;
|
||||
}
|
||||
|
||||
Dictionary<int, Stack<NetworkObject>> dictionary = _cache[collectionId];
|
||||
// No cache for prefabId yet, make one.
|
||||
if (!dictionary.TryGetValueIL2CPP(prefabId, out Stack<NetworkObject> cache))
|
||||
{
|
||||
if (createIfMissing)
|
||||
{
|
||||
cache = new();
|
||||
dictionary[prefabId] = cache;
|
||||
}
|
||||
}
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
[Obsolete("Use GetCache(int, int, bool)")]
|
||||
public Stack<NetworkObject> GetOrCreateCache(int collectionId, int prefabId) => GetCache(collectionId, prefabId, createIfMissing: true);
|
||||
|
||||
/// <summary>
|
||||
/// Destroys all NetworkObjects within a stack and clears the stack.
|
||||
/// </summary>
|
||||
private void DestroyStackNetworkObjectsAndClear(Stack<NetworkObject> stack)
|
||||
{
|
||||
foreach (NetworkObject networkObject in stack)
|
||||
{
|
||||
if (networkObject != null)
|
||||
Destroy(networkObject.gameObject);
|
||||
}
|
||||
|
||||
stack.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb13d174096685549b1d6a94d726ff7d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Utility/Performance/DefaultObjectPool.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,96 @@
|
||||
using FishNet.Managing;
|
||||
using FishNet.Managing.Object;
|
||||
using FishNet.Object;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FishNet.Utility.Extension;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Utility.Performance
|
||||
{
|
||||
public abstract class ObjectPool : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// NetworkManager this ObjectPool belongs to.
|
||||
/// </summary>
|
||||
protected NetworkManager NetworkManager { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called at the end of every frame. This can be used to perform routine tasks.
|
||||
/// </summary>
|
||||
public virtual void LateUpdate() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this script for use.
|
||||
/// </summary>
|
||||
public virtual void InitializeOnce(NetworkManager nm)
|
||||
{
|
||||
NetworkManager = nm;
|
||||
}
|
||||
|
||||
/// <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 object to return.</param>
|
||||
/// <param name = "asServer">True if being called on the server side.</param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use RetrieveObject(int, ushort, RetrieveOption, parent, Vector3?, Quaternion? Vector3?, bool) instead.")] // Remove in V5
|
||||
public virtual NetworkObject RetrieveObject(int prefabId, ushort collectionId, Transform parent = null, Vector3? position = null, Quaternion? rotation = null, Vector3? scale = null, bool makeActive = true, bool asServer = true) => null;
|
||||
|
||||
/// <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 object to return.</param>
|
||||
/// <param name = "asServer">True if being called on the server side.</param>
|
||||
/// <returns></returns>
|
||||
public virtual NetworkObject RetrieveObject(int prefabId, ushort collectionId, ObjectPoolRetrieveOption options, Transform parent = null, Vector3? position = null, Quaternion? rotation = null, Vector3? scale = null, bool asServer = true) => null;
|
||||
|
||||
/// <summary>
|
||||
/// Returns a prefab using specified values.
|
||||
/// </summary>
|
||||
/// <param name = "prefabId">PrefabId of the object to return.</param>
|
||||
/// <param name = "collectionId">CollectionId of the object to return.</param>
|
||||
/// <param name = "asServer">True if being called on the server side.</param>
|
||||
/// <returns></returns>
|
||||
public virtual NetworkObject GetPrefab(int prefabId, ushort collectionId, bool asServer)
|
||||
{
|
||||
PrefabObjects po = NetworkManager.GetPrefabObjects<PrefabObjects>(collectionId, false);
|
||||
return po.GetObject(asServer, prefabId);
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public abstract void StoreObject(NetworkObject instantiated, bool asServer);
|
||||
|
||||
/// <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 virtual void CacheObjects(NetworkObject prefab, int count, bool asServer) { }
|
||||
|
||||
/// <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>
|
||||
/// <returns>Prefabs instantiated and added to cache.</returns>
|
||||
public virtual List<NetworkObject> StorePrefabObjects(NetworkObject prefab, int count, bool asServer) => default;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the transform of a NetworkObject to it's values during serialization.
|
||||
/// </summary>
|
||||
public static void SetTransformToSerializedValues(NetworkObject nob)
|
||||
{
|
||||
nob.transform.SetLocalPositionRotationAndScale(nob.SerializedTransformProperties.Position, nob.SerializedTransformProperties.Rotation, nob.SerializedTransformProperties.Scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6ec7d855ffa7afc45b619b84ddbda27c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Utility/Performance/ObjectPool.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace FishNet.Utility.Performance
|
||||
{
|
||||
public static class RetrieveOptionExtensions
|
||||
{
|
||||
public static bool FastContains(this ObjectPoolRetrieveOption whole, ObjectPoolRetrieveOption part) => (whole & part) == part;
|
||||
}
|
||||
|
||||
[System.Flags]
|
||||
public enum ObjectPoolRetrieveOption
|
||||
{
|
||||
Unset = 0,
|
||||
/// <summary>
|
||||
/// True to make the object active before returning.
|
||||
/// </summary>
|
||||
MakeActive = 1,
|
||||
/// <summary>
|
||||
/// True to treat supplied transform properties as local space.
|
||||
/// False will treat the properties as world space.
|
||||
/// </summary>
|
||||
LocalSpace = 2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 30dbc4b626ddb7844aac0189cc4c7487
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Utility/Performance/ObjectPoolRetrieveOption.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,25 @@
|
||||
using FishNet.Object;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Utility.Performance
|
||||
{
|
||||
public static class GetNonAlloc
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets all NetworkBehaviours on a transform.
|
||||
/// </summary>
|
||||
public static void GetNetworkBehavioursNonAlloc(this Transform t, ref List<NetworkBehaviour> results)
|
||||
{
|
||||
t.GetComponents(results);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all transforms on transform and it's children.
|
||||
/// </summary>
|
||||
public static void GetTransformsInChildrenNonAlloc(this Transform t, ref List<Transform> results, bool includeInactive = false)
|
||||
{
|
||||
t.GetComponentsInChildren(includeInactive, results);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d0740f919077254c8ffb131b9587407
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Utility/Performance/Transforms.cs
|
||||
uploadId: 866910
|
||||
Reference in New Issue
Block a user