Skip to content

Commit

Permalink
feat: Pool Spawner for Room example
Browse files Browse the repository at this point in the history
  • Loading branch information
MrGadget1024 committed Dec 8, 2024
1 parent 7766ed2 commit ea2af34
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ GameObject:
serializedVersion: 6
m_Component:
- component: {fileID: 4362442735993418}
- component: {fileID: 114251241889735402}
- component: {fileID: 114048121767222990}
- component: {fileID: 5119366209337690377}
- component: {fileID: 135606878775227198}
- component: {fileID: 1765969535664783447}
- component: {fileID: 114251241889735402}
- component: {fileID: 5119366209337690377}
- component: {fileID: 114048121767222990}
m_Layer: 0
m_Name: Prize
m_Name: Reward
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
Expand All @@ -36,6 +36,35 @@ Transform:
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!135 &135606878775227198
SphereCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1139254171913846}
m_Material: {fileID: 0}
m_IsTrigger: 1
m_Enabled: 1
serializedVersion: 2
m_Radius: 0.3
m_Center: {x: 0, y: 0, z: 0}
--- !u!54 &1765969535664783447
Rigidbody:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1139254171913846}
serializedVersion: 2
m_Mass: 1
m_Drag: 0
m_AngularDrag: 0.05
m_UseGravity: 0
m_IsKinematic: 1
m_Interpolate: 0
m_Constraints: 0
m_CollisionDetection: 0
--- !u!114 &114251241889735402
MonoBehaviour:
m_ObjectHideFlags: 0
Expand All @@ -53,23 +82,6 @@ MonoBehaviour:
serverOnly: 0
visibility: 0
hasSpawned: 0
--- !u!114 &114048121767222990
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1139254171913846}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a22f9eb8ebad79e47babf4c051a714ee, type: 3}
m_Name:
m_EditorClassIdentifier:
syncDirection: 0
syncMode: 0
syncInterval: 0.1
randomColor: {fileID: 5119366209337690377}
available: 1
--- !u!114 &5119366209337690377
MonoBehaviour:
m_ObjectHideFlags: 0
Expand All @@ -88,35 +100,23 @@ MonoBehaviour:
color:
serializedVersion: 2
rgba: 4278190080
--- !u!135 &135606878775227198
SphereCollider:
--- !u!114 &114048121767222990
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1139254171913846}
m_Material: {fileID: 0}
m_IsTrigger: 1
m_Enabled: 1
serializedVersion: 2
m_Radius: 0.3
m_Center: {x: 0, y: 0, z: 0}
--- !u!54 &1765969535664783447
Rigidbody:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1139254171913846}
serializedVersion: 2
m_Mass: 1
m_Drag: 0
m_AngularDrag: 0.05
m_UseGravity: 0
m_IsKinematic: 1
m_Interpolate: 0
m_Constraints: 0
m_CollisionDetection: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a22f9eb8ebad79e47babf4c051a714ee, type: 3}
m_Name:
m_EditorClassIdentifier:
syncDirection: 0
syncMode: 0
syncInterval: 0.1
randomColor: {fileID: 5119366209337690377}
available: 1
--- !u!1 &5133204039361288107
GameObject:
m_ObjectHideFlags: 0
Expand Down
5 changes: 1 addition & 4 deletions Assets/Mirror/Examples/Room/Scenes/MirrorRoomOffline.unity
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,6 @@ MonoBehaviour:
headlessStartMode: 1
editorAutoStart: 0
sendRate: 30
autoStartServerBuild: 0
autoConnectClientBuild: 0
offlineScene: Assets/Mirror/Examples/Room/Scenes/MirrorRoomOffline.unity
onlineScene: Assets/Mirror/Examples/Room/Scenes/MirrorRoomOnline.unity
offlineSceneLoadDelay: 0
Expand All @@ -276,8 +274,7 @@ MonoBehaviour:
type: 3}
autoCreatePlayer: 1
playerSpawnMethod: 1
spawnPrefabs:
- {fileID: 1139254171913846, guid: 52f1c9ea06cfd154cb68ff9d1b66fc13, type: 3}
spawnPrefabs: []
exceptionsDisconnect: 1
snapshotSettings:
bufferTimeMultiplier: 2
Expand Down
14 changes: 14 additions & 0 deletions Assets/Mirror/Examples/Room/Scripts/NetworkRoomManagerExt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class NetworkRoomManagerExt : NetworkRoomManager
[Header("Spawner Setup")]
[Tooltip("Reward Prefab for the Spawner")]
public GameObject rewardPrefab;
public byte poolSize = 10;

public static new NetworkRoomManagerExt singleton => NetworkManager.singleton as NetworkRoomManagerExt;

Expand All @@ -24,7 +25,20 @@ public override void OnRoomServerSceneChanged(string sceneName)
{
// spawn the initial batch of Rewards
if (sceneName == GameplayScene)
{
Spawner.InitializePool(rewardPrefab, poolSize);
Spawner.InitialSpawn();
}
else
Spawner.ClearPool();
}

public override void OnRoomClientSceneChanged()
{
// Don't initialize the pool for host client because it's
// already initialized in OnRoomServerSceneChanged
if (!NetworkServer.active && networkSceneName == GameplayScene)
Spawner.InitializePool(rewardPrefab, 10);
}

/// <summary>
Expand Down
19 changes: 10 additions & 9 deletions Assets/Mirror/Examples/Room/Scripts/Reward.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class Reward : NetworkBehaviour

[Header("Diagnostics")]
[ReadOnly, SerializeField]
bool available = true;
bool available;

protected override void OnValidate()
{
Expand All @@ -21,19 +21,24 @@ protected override void OnValidate()
randomColor = GetComponent<Common.RandomColor>();
}

public override void OnStartServer()
{
available = true;
}

[ServerCallback]
void OnTriggerEnter(Collider other)
{
// Set up physics layers to prevent this from being called by non-players
// and eliminate the need for a tag check here.
if (!other.CompareTag("Player")) return;

// This is a fast switch to prevent two players claiming the prize in a bang-bang close contest for it.
// This is a fast switch to prevent two players claiming the reward in a bang-bang close contest for it.
// First to trigger turns it off, pending the object being destroyed a few frames later.
if (!available)
return;
else
available = false;

available = false;

// Calculate the points from the color...lighter scores higher as the average approaches 255
// UnityEngine.Color RGB values are byte 0 to 255
Expand All @@ -42,11 +47,7 @@ void OnTriggerEnter(Collider other)
// award the points via SyncVar on Player's PlayerScore
other.GetComponent<PlayerScore>().score += points;

// spawn a replacement
Spawner.SpawnReward();

// destroy this one
NetworkServer.Destroy(gameObject);
Spawner.RecycleReward(gameObject);
}
}
}
86 changes: 84 additions & 2 deletions Assets/Mirror/Examples/Room/Scripts/Spawner.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,103 @@
using System.Threading.Tasks;
using UnityEngine;

namespace Mirror.Examples.NetworkRoom
{
internal class Spawner
{
static GameObject prefab;
static byte poolSize = 10;
static Pool<GameObject> pool;
static ushort counter;

internal static void InitializePool(GameObject poolPrefab, byte count)
{
prefab = poolPrefab;
poolSize = count;

NetworkClient.RegisterPrefab(prefab, SpawnHandler, UnspawnHandler);
pool = new Pool<GameObject>(CreateNew, poolSize);
}

internal static void ClearPool()
{
if (prefab == null) return;

NetworkClient.UnregisterPrefab(prefab);

if (pool == null) return;

// destroy all objects in pool
while (pool.Count > 0)
Object.Destroy(pool.Get());

counter = 0;
pool = null;
}

static GameObject SpawnHandler(SpawnMessage msg) => Get(msg.position, msg.rotation);

static void UnspawnHandler(GameObject spawned) => Return(spawned);

static GameObject CreateNew()
{
// use this object as parent so that objects dont crowd hierarchy
GameObject next = Object.Instantiate(prefab);
counter++;
next.name = $"{prefab.name}_pooled_{counter:00}";
next.SetActive(false);
return next;
}

public static GameObject Get(Vector3 position, Quaternion rotation)
{
GameObject next = pool.Get();

// set position/rotation and set active
next.transform.position = position;
next.transform.rotation = rotation;
next.SetActive(true);
return next;
}

// Used to put object back into pool so they can b
// Should be used on server after unspawning an object
// Used on client by NetworkClient to unspawn objects
public static void Return(GameObject spawned)
{
// disable object
spawned.SetActive(false);

// add back to pool
pool.Return(spawned);
}

[ServerCallback]
internal static void InitialSpawn()
{
for (int i = 0; i < 10; i++)
for (byte i = 0; i < poolSize; i++)
SpawnReward();
}

[ServerCallback]
internal static void SpawnReward()
{
Vector3 spawnPosition = new Vector3(Random.Range(-19, 20), 1, Random.Range(-19, 20));
NetworkServer.Spawn(Object.Instantiate(NetworkRoomManagerExt.singleton.rewardPrefab, spawnPosition, Quaternion.identity));
NetworkServer.Spawn(Get(spawnPosition, Quaternion.identity));
}

[ServerCallback]
internal static async void RecycleReward(GameObject reward)
{
NetworkServer.UnSpawn(reward);
Return(reward);
await DelayedSpawn();
}

static async Task DelayedSpawn()
{
await Task.Delay(new System.TimeSpan(0, 0, 1));
SpawnReward();
}
}
}

0 comments on commit ea2af34

Please sign in to comment.