Entity Factories and Object Pooling
Summary
Use a ksEntityFactory to implement object pooling.
Description
Entity factories can be used to override the behaviour for spawning and destroying game objects for entities. ksEntityFactory has two methods that can be overriden:
GameObject GetGameObject(ksEntity entity, GameObject prefab)
Gets the game object for an entity. The returned game object must have a ksEntityComponent and must not be assigned to another non-destroyed entity.void ReleaseGameObject(ksEntityComponent entity)
Called when an entity whose game object was retrieved from this factory is destroyed andksEntity.DestroyWithServer
is true, or when you callksEntityComponent.CleanUp()
on a destroyed entity. Override this to implement your own destruction logic.
Entity Factories are registered on the room with a regex pattern that determines which entity types use the entity factory.
For example, calling room.AddEntityFactory("Bullet", new MyEntityFactory());
will register the factory for entities of type
'Bullet'. room.AddEntityFactory(".*Bullet", new MyEntityFactory());
will register it for all entity types the end with 'Bullet',
and room.AddEntityFactory(".*", new MyEntityFactory());
will register it for all entity types. If multiple factories are
registered with a regex pattern that matches the same entity type, the first one registered will be used for that type. Factories
must be registered before connecting to the room or from an on connect handler.
The following example shows how to implement object pooling for entity game objects using an entity factory. You should see one disabled game object in the hierarchy for each entity type you register the factory for. As entities are deleted, their game objects will be added as children to their respective pool objects, and as new entities spawn, they will be removed from their pool.
Connect Script
***
// Before connecting, register the entity pool factory for all entities.
// Change the regex pattern ".*" if you only want to pool certain entity types.
room.AddEntityFactory(".*", new EntityPool());
***
EntityPool
using System.Collections.Generic;
using UnityEngine;
using KS.Reactor.Client.Unity;
public class EntityPool : ksEntityFactory
{
// Maps asset ids to object pools.
private Dictionary<uint, Transform> m_pools = new Dictionary<uint, Transform>();
public override GameObject GetGameObject(ksEntity entity, GameObject prefab)
{
// Get the object from its pool if there is one.
Transform pool;
if (m_pools.TryGetValue(entity.AssetId, out pool) && pool != null && pool.childCount > 0)
{
GameObject gameObject = pool.transform.GetChild(pool.childCount - 1).gameObject;
gameObject.transform.SetParent(null);
return gameObject;
}
// Create a new object from the prefab.
return base.GetGameObject(entity, prefab);
}
public override void ReleaseGameObject(ksEntityComponent entity)
{
// Return the object to its pool.
Transform pool;
if (!m_pools.TryGetValue(entity.AssetId, out pool) || pool == null)
{
pool = new GameObject(entity.Type + " Factory").transform;
pool.gameObject.SetActive(false);
m_pools[entity.AssetId] = pool;
}
entity.transform.SetParent(pool);
}
}