You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
RizzeProjectile/Assets/Scripts/Utilities/NetworkObjectPool.cs

116 lines
2.9 KiB
C#

using System.Collections.Generic;
using UnityEngine;
using Fusion;
namespace Projectiles
{
public class NetworkObjectPool : Fusion.Behaviour, INetworkObjectProvider
{
public SceneContext Context { get; set; }
private Dictionary<NetworkPrefabId, Stack<NetworkObject>> _cached = new(32);
private Dictionary<NetworkObject, NetworkPrefabId> _borrowed = new();
NetworkObjectAcquireResult INetworkObjectProvider.AcquirePrefabInstance(NetworkRunner runner, in NetworkPrefabAcquireContext context, out NetworkObject result)
{
if (_cached.TryGetValue(context.PrefabId, out var objects) == false)
{
objects = _cached[context.PrefabId] = new Stack<NetworkObject>();
}
if (objects.Count > 0)
{
var oldInstance = objects.Pop();
_borrowed[oldInstance] = context.PrefabId;
#if UNITY_EDITOR
var originalPrefab = runner.Config.PrefabTable.Load(context.PrefabId, true);
oldInstance.name = originalPrefab.name;
#endif
oldInstance.SetActive(true);
result = oldInstance;
return NetworkObjectAcquireResult.Success;
}
var original = runner.Config.PrefabTable.Load(context.PrefabId, true);
if (original == null)
{
result = default;
return NetworkObjectAcquireResult.Failed;
}
var instance = Instantiate(original);
runner.MoveToRunnerScene(instance.gameObject);
#if UNITY_EDITOR
instance.name = original.name;
#endif
_borrowed[instance] = context.PrefabId;
AssignContext(instance);
for (int i = 0; i < instance.NestedObjects.Length; i++)
{
AssignContext(instance.NestedObjects[i]);
}
result = instance;
return NetworkObjectAcquireResult.Success;
}
void INetworkObjectProvider.ReleaseInstance(NetworkRunner runner, in NetworkObjectReleaseContext context)
{
if (context.IsNestedObject == true)
return;
NetworkObject instance = context.Object;
if (instance == null)
return;
if (instance.NetworkTypeId.IsSceneObject == false && runner.IsShutdown == false)
{
if (_borrowed.TryGetValue(instance, out var prefabID) == true)
{
_borrowed.Remove(instance);
_cached[prefabID].Push(instance);
instance.SetActive(false);
instance.transform.parent = null;
instance.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
#if UNITY_EDITOR
instance.name = $"(Cached) {instance.name}";
#endif
}
else
{
Destroy(instance.gameObject);
}
}
else
{
Destroy(instance.gameObject);
}
}
NetworkPrefabId INetworkObjectProvider.GetPrefabId(NetworkRunner runner, NetworkObjectGuid prefabGuid)
{
return runner.Prefabs.GetId(prefabGuid);
}
private void AssignContext(NetworkObject instance)
{
for (int i = 0, count = instance.NetworkedBehaviours.Length; i < count; i++)
{
if (instance.NetworkedBehaviours[i] is IContextBehaviour cachedBehaviour)
{
cachedBehaviour.Context = Context;
}
}
}
}
}