Last active
May 9, 2024 08:38
-
-
Save James-Frowen/c2ab4cdc96165298518bd2db0781bbe6 to your computer and use it in GitHub Desktop.
Prefab Pool for Unity and Mirror Networking, see simple example here https://gist.github.com/James-Frowen/46ca5e8fd76d62527be7b958ca8dbaf1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Mirror; | |
using UnityEngine; | |
namespace JamesFrowen.Spawning | |
{ | |
public class MirrorPrefabPool : PrefabPool | |
{ | |
private readonly NetworkIdentity _networkPrefab; | |
private bool _handlersRegistered; | |
public MirrorPrefabPool(GameObject prefab, int capacity = 100) : this(prefab.GetComponent<PrefabPoolBehaviour>(), prefab.GetComponent<NetworkIdentity>(), capacity) { } | |
public MirrorPrefabPool(PrefabPoolBehaviour prefab, int capacity = 100) : this(prefab, prefab.GetComponent<NetworkIdentity>(), capacity) { } | |
private MirrorPrefabPool(PrefabPoolBehaviour prefab, NetworkIdentity identity, int capacity = 100) : base(prefab, capacity) | |
{ | |
if (identity == null) | |
{ | |
throw new System.ArgumentNullException(nameof(identity), "Network prefab should have NetworkIdentity"); | |
} | |
_networkPrefab = identity; | |
if (NetworkClient.active) | |
{ | |
this.RegisterMirrorHandlers(); | |
} | |
} | |
#region Mirror Handlers | |
private GameObject networkSpawnHandler(SpawnMessage msg) | |
{ | |
var behaviour = this.Spawn(msg.position, msg.rotation); | |
return behaviour.gameObject; | |
} | |
private void networkUnSpawnHandler(GameObject gameObject) | |
{ | |
var behaviour = gameObject.GetComponent<PrefabPoolBehaviour>(); | |
this.Unspawn(behaviour); | |
} | |
public void RegisterMirrorHandlers() | |
{ | |
if (this._handlersRegistered) { return; } | |
ClientScene.RegisterPrefab(this._networkPrefab.gameObject, this.networkSpawnHandler, this.networkUnSpawnHandler); | |
this._handlersRegistered = true; | |
} | |
public void UnregisterMirrorHandlers() | |
{ | |
if (!this._handlersRegistered) { return; } | |
ClientScene.UnregisterPrefab(this._networkPrefab.gameObject); | |
this._handlersRegistered = false; | |
} | |
#endregion | |
#region IDisposable Support | |
protected override void Dispose(bool disposing) | |
{ | |
if (!this.disposedValue) | |
{ | |
this.UnregisterMirrorHandlers(); | |
} | |
base.Dispose(disposing); | |
} | |
#endregion | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
namespace JamesFrowen.Spawning | |
{ | |
public class PrefabPool : System.IDisposable | |
{ | |
/// <summary> | |
/// parent shared by all pools | |
/// </summary> | |
private static Transform _poolParent; | |
protected readonly PrefabPoolBehaviour _prefab; | |
private readonly PrefabPoolBehaviour[] _pool; | |
/// <summary> | |
/// parent for this pool, should be a child of _poolParent | |
/// </summary> | |
private readonly Transform _parent; | |
private int _next = -1; | |
public PrefabPool(GameObject prefab, int capacity = 100) : this(prefab.GetComponent<PrefabPoolBehaviour>(), capacity) { } | |
public PrefabPool(PrefabPoolBehaviour prefab, int capacity = 100) | |
{ | |
if (prefab == null) | |
{ | |
throw new System.ArgumentNullException(nameof(prefab)); | |
} | |
this._prefab = prefab; | |
this._pool = new PrefabPoolBehaviour[capacity]; | |
if (_poolParent == null) | |
{ | |
_poolParent = new GameObject("PrefabPools").transform; | |
} | |
this._parent = new GameObject(this._prefab.name).transform; | |
this._parent.SetParent(_poolParent); | |
} | |
public void ClearNullObject() | |
{ | |
var nextEmpty = 0; | |
for (var i = 0; i < this._pool.Length; i++) | |
{ | |
if (this._pool[i] != null) | |
{ | |
this._pool[nextEmpty] = this._pool[i]; | |
nextEmpty++; | |
} | |
else | |
{ | |
// clear c# object if Unity object is null | |
this._pool[i] = null; | |
} | |
} | |
this._next = nextEmpty - 1; | |
} | |
public void Warnup(int createCount) | |
{ | |
for (var i = this._next + 1; i < createCount; i++) | |
{ | |
var item = UnityEngine.Object.Instantiate(this._prefab); | |
item.OnInstantiate(this, this._parent); | |
this.putBack(item); | |
} | |
} | |
private PrefabPoolBehaviour getNext() | |
{ | |
PrefabPoolBehaviour item; | |
if (this._next == -1) | |
{ | |
item = UnityEngine.Object.Instantiate(this._prefab); | |
item.OnInstantiate(this, this._parent); | |
} | |
else | |
{ | |
item = this._pool[this._next]; | |
this._pool[this._next] = null; | |
this._next--; | |
} | |
item.BeforeSpawn(); | |
return item; | |
} | |
private void putBack(PrefabPoolBehaviour obj) | |
{ | |
if (this.disposedValue) | |
{ | |
UnityEngine.Object.Destroy(obj.gameObject); | |
return; | |
} | |
if (this._next < this._pool.Length - 1) | |
{ | |
this._next++; | |
this._pool[this._next] = obj; | |
obj.AfterUnspawn(); | |
} | |
else | |
{ | |
UnityEngine.Object.Destroy(obj.gameObject); | |
GameLog.LogWarning("NetworkWriterPool.Recycle, Pool was full leaving extra writer for GC"); | |
} | |
} | |
public PrefabPoolBehaviour Spawn() | |
{ | |
return this.getNext(); | |
} | |
public PrefabPoolBehaviour Spawn(Vector3 position, Quaternion rotation) | |
{ | |
var obj = this.getNext(); | |
obj.transform.position = position; | |
obj.transform.rotation = rotation; | |
return obj; | |
} | |
public PrefabPoolBehaviour Spawn(Transform parent) | |
{ | |
var obj = this.getNext(); | |
obj.transform.SetParent(parent); | |
return obj; | |
} | |
public PrefabPoolBehaviour Spawn(Vector3 position, Quaternion rotation, Transform parent) | |
{ | |
var obj = this.getNext(); | |
obj.transform.SetParent(parent); | |
obj.transform.position = position; | |
obj.transform.rotation = rotation; | |
return obj; | |
} | |
public void Unspawn(PrefabPoolBehaviour obj) | |
{ | |
this.putBack(obj); | |
} | |
#region IDisposable Support | |
private bool disposedValue = false; // To detect redundant calls | |
protected virtual void Dispose(bool disposing) | |
{ | |
if (!this.disposedValue) | |
{ | |
if (disposing) | |
{ | |
for (var i = 0; i < this._pool.Length; i++) | |
{ | |
if (this._pool[i] != null) | |
{ | |
UnityEngine.Object.Destroy(this._pool[i].gameObject); | |
this._pool[i] = null; | |
} | |
} | |
} | |
this.disposedValue = true; | |
} | |
} | |
public void Dispose() | |
{ | |
this.Dispose(true); | |
} | |
#endregion | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
namespace JamesFrowen.Spawning | |
{ | |
public class PrefabPoolBehaviour : MonoBehaviour | |
{ | |
private PrefabPool _pool; | |
private Transform _parent; | |
internal virtual void OnInstantiate(PrefabPool pool, Transform _parent) | |
{ | |
this._pool = pool; | |
this._parent = _parent; | |
this.transform.SetParent(this._parent); | |
} | |
internal virtual void BeforeSpawn() | |
{ | |
this.gameObject.SetActive(true); | |
} | |
internal void AfterUnspawn() | |
{ | |
this.gameObject.SetActive(false); | |
this.transform.SetParent(this._parent); | |
} | |
public void Unspawn() | |
{ | |
this._pool.Unspawn(this); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
namespace JamesFrowen.Spawning | |
{ | |
[RequireComponent(typeof(Rigidbody))] | |
public class PrefabRigidbodyPoolBehaviour : PrefabPoolBehaviour | |
{ | |
private Rigidbody _rigidBody; | |
internal override void OnInstantiate(PrefabPool pool, Transform _parent) | |
{ | |
base.OnInstantiate(pool, _parent); | |
this._rigidBody = this.GetComponent<Rigidbody>(); | |
} | |
internal override void BeforeSpawn() | |
{ | |
this._rigidBody.velocity = Vector3.zero; | |
this._rigidBody.angularVelocity = Vector3.zero; | |
base.BeforeSpawn(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
in here what is difference between c# object and Unity object?
it looks like just set as null when it is already null;