Reworked Object Pooling

This commit is contained in:
Albin Corén 2018-03-05 12:23:34 +01:00
parent 6a586f68b6
commit 0ee53e41f0
4 changed files with 69 additions and 70 deletions

View File

@ -4,37 +4,25 @@ namespace MLAPI.Data
{ {
internal class NetworkPool internal class NetworkPool
{ {
internal GameObject prefab; internal int spawnablePrefabIndex;
internal GameObject[] objects; internal GameObject[] objects;
internal string poolName; internal ushort poolId;
internal NetworkPool(GameObject prefab, uint size, string name) internal NetworkPool(int prefabIndex, uint size, ushort poolIndex)
{ {
objects = new GameObject[size]; objects = new GameObject[size];
poolName = name; poolId = poolIndex;
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)
{ {
GameObject go = UnityEngine.Object.Instantiate(prefab, Vector3.zero, Quaternion.identity); GameObject go = Object.Instantiate(NetworkingManager.singleton.SpawnablePrefabs[prefabIndex], Vector3.zero, Quaternion.identity);
go.name = "Pool " + poolName + " #" + i; go.GetComponent<NetworkedObject>().IsPooledObject = true;
go.GetComponent<NetworkedObject>().PoolId = poolId;
go.GetComponent<NetworkedObject>().Spawn();
go.name = "Pool Id: " + poolId + " #" + i;
go.SetActive(false); go.SetActive(false);
} }
} }
internal NetworkPool(GameObject[] prefabs, string name)
{
objects = prefabs;
poolName = name;
int size = prefabs.Length;
for (int i = 0; i < size; i++)
{
prefabs[i].name = "Pool " + poolName + " #" + i;
prefabs[i].SetActive(false);
}
}
internal GameObject SpawnObject(Vector3 position, Quaternion rotation) internal GameObject SpawnObject(Vector3 position, Quaternion rotation)
{ {
for (int i = 0; i < objects.Length; i++) for (int i = 0; i < objects.Length; i++)
@ -47,7 +35,7 @@ namespace MLAPI.Data
go.SetActive(true); go.SetActive(true);
} }
} }
Debug.LogWarning("MLAPI: The pool " + poolName + " has ran out of space"); Debug.LogWarning("MLAPI: The pool " + poolId + " has ran out of space");
return null; return null;
} }
} }

View File

@ -14,6 +14,10 @@ namespace MLAPI
[HideInInspector] [HideInInspector]
public bool isPlayerObject = false; public bool isPlayerObject = false;
public bool ServerOnly = false; public bool ServerOnly = false;
[HideInInspector]
public bool IsPooledObject = false;
[HideInInspector]
public ushort PoolId;
public bool isLocalPlayer public bool isLocalPlayer
{ {
get get

View File

@ -1,5 +1,4 @@
using MLAPI.MonoBehaviours.Core; using MLAPI.NetworkingManagerComponents;
using MLAPI.NetworkingManagerComponents;
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
@ -72,7 +71,8 @@ namespace MLAPI
MessageManager.reverseMessageTypes = new Dictionary<ushort, string>(); MessageManager.reverseMessageTypes = new Dictionary<ushort, string>();
SpawnManager.spawnedObjects = new Dictionary<uint, NetworkedObject>(); SpawnManager.spawnedObjects = new Dictionary<uint, NetworkedObject>();
SpawnManager.releasedNetworkObjectIds = new Stack<uint>(); SpawnManager.releasedNetworkObjectIds = new Stack<uint>();
NetworkPoolManager.Pools = new Dictionary<string, Data.NetworkPool>(); NetworkPoolManager.Pools = new Dictionary<ushort, Data.NetworkPool>();
NetworkPoolManager.PoolNamesToIndexes = new Dictionary<string, ushort>();
NetworkSceneManager.registeredSceneNames = new HashSet<string>(); NetworkSceneManager.registeredSceneNames = new HashSet<string>();
NetworkSceneManager.sceneIndexToString = new Dictionary<uint, string>(); NetworkSceneManager.sceneIndexToString = new Dictionary<uint, string>();
NetworkSceneManager.sceneNameToIndex = new Dictionary<string, uint>(); NetworkSceneManager.sceneNameToIndex = new Dictionary<string, uint>();
@ -100,6 +100,7 @@ namespace MLAPI
MessageManager.messageTypes.Add("MLAPI_DESTROY_OBJECT", 4); MessageManager.messageTypes.Add("MLAPI_DESTROY_OBJECT", 4);
MessageManager.messageTypes.Add("MLAPI_SWITCH_SCENE", 5); MessageManager.messageTypes.Add("MLAPI_SWITCH_SCENE", 5);
MessageManager.messageTypes.Add("MLAPI_SPAWN_POOL_OBJECT", 6); MessageManager.messageTypes.Add("MLAPI_SPAWN_POOL_OBJECT", 6);
MessageManager.messageTypes.Add("MLAPI_DESTROY_POOL_OBJECT", 7);
NetworkConfig.MessageTypes.Add("MLAPI_OnRecieveTransformFromClient"); NetworkConfig.MessageTypes.Add("MLAPI_OnRecieveTransformFromClient");
NetworkConfig.MessageTypes.Add("MLAPI_OnRecieveTransformFromServer"); NetworkConfig.MessageTypes.Add("MLAPI_OnRecieveTransformFromServer");
@ -587,15 +588,16 @@ namespace MLAPI
{ {
using (BinaryReader messageReader = new BinaryReader(messageReadStream)) using (BinaryReader messageReader = new BinaryReader(messageReadStream))
{ {
ushort poolIndex = messageReader.ReadUInt16(); uint netId = messageReader.ReadUInt32();
float xPos = messageReader.ReadSingle(); float xPos = messageReader.ReadSingle();
float yPos = messageReader.ReadSingle(); float yPos = messageReader.ReadSingle();
float zPos = messageReader.ReadSingle(); float zPos = messageReader.ReadSingle();
float xRot = messageReader.ReadSingle(); float xRot = messageReader.ReadSingle();
float yRot = messageReader.ReadSingle(); float yRot = messageReader.ReadSingle();
float zRot = messageReader.ReadSingle(); float zRot = messageReader.ReadSingle();
NetworkPoolManager.SpawnPoolObject(NetworkPoolManager.PoolIndexToPoolName[poolIndex], SpawnManager.spawnedObjects[netId].transform.position = new Vector3(xPos, yPos, zPos);
new Vector3(xPos, yPos, zPos), Quaternion.Euler(xRot, yRot, zRot)); SpawnManager.spawnedObjects[netId].transform.rotation = Quaternion.Euler(new Vector3(xRot, yRot, zRot));
SpawnManager.spawnedObjects[netId].gameObject.SetActive(true);
} }
} }
} }

View File

@ -7,73 +7,78 @@ namespace MLAPI.NetworkingManagerComponents
{ {
public static class NetworkPoolManager public static class NetworkPoolManager
{ {
internal static Dictionary<string, NetworkPool> Pools; internal static Dictionary<ushort, NetworkPool> Pools;
//We want to keep the pool indexes incrementing, this is to prevent new pools getting old names and the wrong objects being spawned.
private static ushort PoolIndex = 0; private static ushort PoolIndex = 0;
internal static Dictionary<string, ushort> PoolNamesToIndexes;
internal static Dictionary<ushort, string> PoolIndexToPoolName = new Dictionary<ushort, string>(); //Server only
internal static Dictionary<string, ushort> PoolNamesToIndexes = new Dictionary<string, ushort>(); public static void CreatePool(string poolName, int spawnablePrefabIndex, uint size = 16)
public static void CreatePool(string poolName, GameObject poolPrefab, uint size = 16)
{ {
if(Pools.ContainsKey(poolName)) if(!NetworkingManager.singleton.isServer)
{ {
Debug.LogWarning("MLAPI: A pool with the name " + poolName + " already exists"); Debug.LogWarning("MLAPI: Pools can only be created on the server");
return; return;
} }
else if(poolPrefab == null) NetworkPool pool = new NetworkPool(spawnablePrefabIndex, size, PoolIndex);
{
Debug.LogWarning("MLAPI: A pool prefab is required");
}
PoolIndexToPoolName.Add(PoolIndex, poolName);
PoolNamesToIndexes.Add(poolName, PoolIndex); PoolNamesToIndexes.Add(poolName, PoolIndex);
PoolIndex++; PoolIndex++;
Pools.Add(poolName, new NetworkPool(poolPrefab, size, poolName));
} }
public static void DestroyPool(string poolName)
public static void CreatePool(string poolName, GameObject[] poolPrefabs)
{ {
if (Pools.ContainsKey(poolName)) if (!NetworkingManager.singleton.isServer)
{ {
Debug.LogWarning("MLAPI: A pool with the name " + poolName + " already exists"); Debug.LogWarning("MLAPI: Pools can only be destroyed on the server");
return; return;
} }
else if (poolPrefabs == null) for (int i = 0; i < Pools[PoolNamesToIndexes[poolName]].objects.Length; i++)
{ {
Debug.LogWarning("MLAPI: A pool prefab array is required"); MonoBehaviour.Destroy(Pools[PoolNamesToIndexes[poolName]].objects[i]);
} }
PoolIndexToPoolName.Add(PoolIndex, poolName); Pools.Remove(PoolNamesToIndexes[poolName]);
PoolNamesToIndexes.Add(poolName, PoolIndex);
PoolIndex++;
Pools.Add(poolName, new NetworkPool(poolPrefabs, poolName));
} }
public static GameObject SpawnPoolObject(string poolName, Vector3 position, Quaternion rotation) public static GameObject SpawnPoolObject(string poolName, Vector3 position, Quaternion rotation)
{ {
if(NetworkingManager.singleton.isServer) if (!NetworkingManager.singleton.isServer)
{ {
using(MemoryStream stream = new MemoryStream(26)) Debug.LogWarning("MLAPI: Object spawning can only occur on server");
{ return null;
using(BinaryWriter writer = new BinaryWriter(stream))
{
writer.Write(PoolNamesToIndexes[poolName]);
writer.Write(position.x);
writer.Write(position.y);
writer.Write(position.z);
writer.Write(rotation.eulerAngles.x);
writer.Write(rotation.eulerAngles.y);
writer.Write(rotation.eulerAngles.z);
}
NetworkingManager.singleton.Send("MLAPI_SPAWN_POOL_OBJECT", "MLAPI_RELIABLE_FRAGMENTED_SEQUENCED", stream.GetBuffer());
}
} }
return Pools[poolName].SpawnObject(position, rotation); GameObject go = Pools[PoolNamesToIndexes[poolName]].SpawnObject(position, rotation);
using (MemoryStream stream = new MemoryStream(28))
{
using (BinaryWriter writer = new BinaryWriter(stream))
{
writer.Write(go.GetComponent<NetworkedObject>().NetworkId);
writer.Write(position.x);
writer.Write(position.y);
writer.Write(position.z);
writer.Write(rotation.eulerAngles.x);
writer.Write(rotation.eulerAngles.y);
writer.Write(rotation.eulerAngles.z);
}
NetworkingManager.singleton.Send("MLAPI_SPAWN_POOL_OBJECT", "MLAPI_RELIABLE_FRAGMENTED_SEQUENCED", stream.GetBuffer());
}
return go;
} }
public static void DestroyPoolObject(GameObject gameObject) public static void DestroyPoolObject(NetworkedObject netObject)
{ {
gameObject.SetActive(false); if (!NetworkingManager.singleton.isServer)
{
Debug.LogWarning("MLAPI: Objects can only be destroyed on the server");
return;
}
netObject.gameObject.SetActive(false);
using (MemoryStream stream = new MemoryStream(4))
{
using (BinaryWriter writer = new BinaryWriter(stream))
{
writer.Write(netObject.NetworkId);
}
NetworkingManager.singleton.Send("MLAPI_DESTROY_POOL_OBJECT", "MLAPI_RELIABLE_FRAGMENTED_SEQUENCED", stream.GetBuffer());
}
} }
} }
} }