{"id":15160596,"url":"https://github.com/clpsplug/pooledobjects","last_synced_at":"2026-01-20T19:32:46.981Z","repository":{"id":226230913,"uuid":"768041656","full_name":"Clpsplug/PooledObjects","owner":"Clpsplug","description":"ClpsPLUG's Pooled Objects for Unity","archived":false,"fork":false,"pushed_at":"2024-04-07T08:08:06.000Z","size":93,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"base","last_synced_at":"2025-04-07T19:55:01.546Z","etag":null,"topics":["unity3d-plugin"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Clpsplug.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-03-06T11:09:50.000Z","updated_at":"2024-03-06T14:18:23.000Z","dependencies_parsed_at":"2024-03-06T15:21:59.332Z","dependency_job_id":"c5a66a9f-cb4a-47bb-8d32-30964fb456e3","html_url":"https://github.com/Clpsplug/PooledObjects","commit_stats":null,"previous_names":["clpsplug/pooledobjects"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Clpsplug%2FPooledObjects","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Clpsplug%2FPooledObjects/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Clpsplug%2FPooledObjects/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Clpsplug%2FPooledObjects/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Clpsplug","download_url":"https://codeload.github.com/Clpsplug/PooledObjects/tar.gz/refs/heads/base","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247721929,"owners_count":20985083,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["unity3d-plugin"],"created_at":"2024-09-26T23:03:14.193Z","updated_at":"2026-01-20T19:32:46.976Z","avatar_url":"https://github.com/Clpsplug.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ClpsPLUG's Pooled Objects for Unity\n\nYet another way to pool objects to reduce performance overhead in Unity.\n\n## Installation\n\nUse UPM - select \"Add package from Git URL\" and paste the following:\n\n```\nhttps://github.com/Clpsplug/PooledObjects.git\n```\n\n![add package](ManualImages~/upm.png)\n\n## Basic concept\n\nThis library enables you to create what's known as 'memory pool',\nbut in a form of a pool of (mainly) GameObjects.\n\nIn short, when you create a memory pool using this library,\nyou will do the following.\n\n1. You initialize a batch of instances of a prefab, but inactive.\n2. You call one of the instance for usage (spawn), and get the instance.\n3. You do anything you want with that instance. Run animation, change color, anything.\n4. After usage, you put away the instance (despawn). Or the instance itself can decide to put itself away.\n5. Rinse and repeat 2 ~ 4.\n\nIn this way, you will reduce the overhead of spawning instances of certain prefabs\n(especially in a large number), leading to better performance.\n\n## How to use\n\nYou will need the following:\n\n* Your custom MonoBehaviour script implementing `Clpsplug.PooledObjects.Runtime.IPoolable` interface\n* A prefab of GameObject that has the aforementioned script attached\n* An inherited class of `Clpsplug.PooledObjects.Runtime.PooledObjects\u003cT\u003e` (or the abstract class with different generic\n  typeparam count but the same name)\n* A prefan instantiation code.\n\n### The script to be pooled\n\nFirst, prepare your MonoBehaviour script for our PooledObjects system.\n\n```csharp\nusing UnityEngine;\nusing Clpsplug.PooledObjects.Runtime;\npublic class PooledMonoBehaviour: MonoBehaviour, IPoolable\n{\n    public bool isUsed {get; private set;}\n    \n    private void Awake()\n    {\n        isUsed = false;\n        gameObject.SetActive(false);\n    }\n    \n    public void OnSpawn()\n    {\n        /* Spawned! */\n        gameObject.SetActive(true);\n        isUsed = true;\n    }\n    \n    public void OnDespawn()\n    {\n        gameObject.SetActive(false);\n        isUsed = false;\n    }\n}\n```\n\nHere, we have three method - one of which is the unity event function, `Awake`.\nWe immediately set the GameObject inactive, hiding it from view - but it's still in the scene,\nso it doesn't get 'instantiated' in a traditional sense anymore;\nrather, it is 'spawned'.  \nLook at the `OnSpawn` method - it activates the GameObject, and sets the property `isUsed` to `true`;\nthis property is from the interface `IPoolable`.\nIt is required to signal which instance is currently used and which is not.  \nAnd in the `OnDespawn` method, we hide the GameObject again and set the `isUsed` property to `false`,\neffectively returning itself to whatever pool it's controlled in.\n\n### The Pool\n\nNow, we make the pool - we determine what GameObject a particular pool manages by its generic type parameter, like so:\n\n```csharp\nusing Clpsplug.PooledObjects.Runtime;\npublic class MonoBehaviourPool: PooledObjects\u003cPooledMonoBehaviour\u003e\n{\n    public override void OnSpawn(PooledMonoBehaviour item)\n    {\n        item.OnSpawn();\n    }\n    public override void OnDespawn(PooledMonoBehaviour item)\n    {\n        item.OnDespawn();\n    }    \n}\n```\n\nThe implementation of the pool itself is fairly simple - the overridable methods `OnSpawn` and `OnDespawn`\nis automatically called with the item being spawned/despawned, so you call whatever method you want on it.\n\n\u003e [!WARNING]  \n\u003e One thing you *don't* want to do is to call `Destroy(item.gameObject)` in `OnDespawn`; it's gonna break the pool!  \n\u003e When we say despawn, it means that the gameObject in question simply gets inactive, but still in the scene.\n\u003e Destroying it when we want to despawn it causes a null reference exceptions later down the line.\n\n### Use the pool\n\nTime to use the pool. Simply create an instance of a pool, and do this:\n\n```csharp\npublic GameObject pooledInstancePrefab;\nMonoBehaviourPool pool = new MonoBehaviourPool();\npool.Initialize(\n    () =\u003e Instantiate(pooledInstancePrefab).GetComponent\u003cPooledMonoBehaviour\u003e(),\n    100 // how many instances we want to pool?\n);\n```\n\nThis will initialize the pool. When this happens, 100 instances of `pooledInstancePrefab` is created,\nas dictated by the second parameter of the method `Initialize`.  \nAt this point, it appears that nothing is in the scene,\nbut if you see the inspector, you will notice inactive instances of the prefab.\n\nNow when we call `Spawn` on the pool...\n\n```csharp\nvar instance = pool.Spawn();\n```\n\nYou obtain an instance that was sitting in the pool. When this happens, the pool's `OnSpawn` is called,\ntherefore, `PooledMonoBehaviour.OnSpawn()` is called.\nNow you can do anything you want with this instance,\ne.g., set its position, set parameters...\n\nAfter you are done with the instance, you can call `Despawn()`, passing the instance as the parameter.\n\n```csharp\npool.Despawn(instance);\n```\n\nThis returns the instance to the pool. Similar to when we called `Spawn`,\nthe pool's `OnDespawn` is called, therefore, `PooledMonoBehaviour.OnDespawn()` gets called.\n\nYou can call `Spawn` as many times you want, until the pool is empty of ready-to-use instances,\nin which case several things can happen.\n\n## What happens when we exhaust the pool?\n\nShort answer: it depends. Long answer: it's been determined when you called `Initialize` of the pool.\n\n`Initialize` has an optional third argument that takes an enum `ExhaustionBehaviour`.\nThe member passed to this argument decides the behaviour when there are no instances to use.\n\n| ExhaustionBehaviour | Behaviour when `Spawn()` is called but no free instances                           |\n|:--------------------|:-----------------------------------------------------------------------------------|\n| Throw (Default)     | Throws `PooledObjectsExhaustedException`.                                          |\n| NullOrDefault       | Returns `null` or whatever default value.                                          |\n| AddOne              | Creates exactly one new instance and returns that. The size of the pool increases. |\n| Double              | Creates the same amount of the instance, effectively doubling the pool size.       |\n\nEach behaviour comes with its own pros and cons - which to use depends on the nature of the object you're dealing with.\n\n\u003e [!NOTE]  \n\u003e Some keen readers might have realized we call the behaviour where `null` is returned `NullOrDefault`,\n\u003e not simply `ReturnNull` or something.  \n\u003e This is because this pool can be used for non-MonoBehaviour stuff, including structs and plain-old classes,\n\u003e so long as they implement `IPoolable`!  \n\u003e In fact, the pool-related code is free of UnityEngine dependencies, so it's possible to yank the classes out\n\u003e and implement for other projects!\n\n\n## TODO\n\n* More documentation\n* Increase the type parameter variant of the pool base\n* Performance?\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclpsplug%2Fpooledobjects","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclpsplug%2Fpooledobjects","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclpsplug%2Fpooledobjects/lists"}