A faithful port of QFSW's Master Object Pooler 2 (originally a Unity asset used by the XRUIOS) to the Aether Engine's Godot 4.7 + C# stack. The public API mirrors the original so existing usage patterns carry over with minimal changes.
Ported for the XRUIOS, Echoes Online and Masuki Quest.
Original: https://github.com/QFSW/MasterObjectPooler2
Verified to compile clean (0 warnings / 0 errors) against Godot.NET.Sdk/4.7.0, net8.0.
![]() |
![]() |
|---|---|
| Code by WalkerDev “Loving coding is the same as hating yourself” Discord |
Art by Kennaness “When will I get my isekai?” Bluesky • ArtStation |
Aether Engine • View The Original
MasterObjectPooler2/
addons/mop2/
ObjectPool.cs # Resource — a pool of instances of one PackedScene
MasterObjectPooler.cs # Node — manages named pools
PoolableNode.cs # Node3D base that can self-release to its pool
AutoPool.cs # Releases an object after a timer
IPoolable.cs # Interface for receiving the parent pool
PopulateMethod.cs # Set / Add enum
NodeActivation.cs # internal SetActive(node,bool) helper
demo/
ReleaseOnCollision.cs # RigidBody3D that releases on collision (+ death FX)
TriggerSpawner.cs # Spawns pooled rigidbodies at a fixed rate
Copy addons/mop2/ into your project (it needs no plugin.cfg or EditorPlugin — the classes are
exposed to the editor via [GlobalClass]). Build the project's C# solution once; afterwards:
- Object Pool appears in the Create Resource dialog (mirrors Unity's
CreateAssetMenu). - MasterObjectPooler, AutoPool, etc. appear in the Add Node dialog.
using QFSW.MOP2;
// Create + initialize a pool at runtime
var pool = ObjectPool.CreateAndInitialize(myPackedScene, defaultSize: 20);
Node bullet = pool.GetObject(spawnPosition, spawnRotation);
RigidBody3D rb = pool.GetObjectComponent<RigidBody3D>(spawnPosition); // node-typed lookup, cached
pool.Release(bullet);
// Or via a MasterObjectPooler node, addressing pools by name
mop.GetObject("Bullet", spawnPosition);
mop.ReleaseAll("Bullet");| Unity (MOP2) | Godot port |
|---|---|
GameObject template (prefab) |
PackedScene template |
ObjectPool : ScriptableObject |
ObjectPool : Resource ([GlobalClass]) |
MasterObjectPooler : MonoBehaviour |
MasterObjectPooler : Node |
Instantiate(template) |
PackedScene.Instantiate() |
Object.Destroy(obj) |
Node.QueueFree() |
GameObject.SetActive(bool) |
NodeActivation.SetActive (visibility + ProcessMode) |
transform.SetParent(...) |
Node.AddChild / Node.Reparent |
GetComponent<T>() |
node is T, else first descendant of type T |
GetInstanceID() (int) |
GetInstanceId() (ulong) |
[SerializeField] / [Tooltip] |
[Export] + XML doc comments |
ObjectParent (new GameObject) |
lazily-created holder Node3D under the current scene |
These stem from real engine differences, not omissions:
-
Component model. Godot has no components; nodes are the type.
GetObjectComponent<T>()returns the instance itself when it is aT, otherwise the first descendant node of that type (cached by instance id + type, exactly like the original). -
Activation. Unity toggles the whole GameObject with
SetActive. Here a pooled (inactive) node is hidden (if it is aNode3D/CanvasItem) and has itsProcessModeset toDisabledso_Process/_PhysicsProcess/input stop firing — the closest equivalent. -
Template transform. A
PackedScenecannot be queried without instancing, so the template's local position/rotation/scale are captured from the first instance created and used as the defaults for the parameterlessGetObject()/Populate(). -
Scene-change handling. MOP2 subscribed to
SceneManager.sceneUnloadedto cleanse and optionally repopulate. A GodotResourcehas no scene-lifecycle callbacks, so this is exposed as a publicObjectPool.Cleanse()you call manually (e.g. before/afterSceneTree.ChangeSceneToFile).Purge()remains available to destroy everything. -
Singleton mode.
MasterObjectPoolerwith_singletonModereparents itself under the scene tree root (Godot's equivalent ofDontDestroyOnLoad) and enforces a singleInstance. -
PoolableNodebase type. The originalPoolableMonoBehaviourwas a component attachable to any object. The port derives fromNode3D(attachable to any 3D node, including physics bodies). For 2D orControl-based pooled scenes, implementIPoolabledirectly instead.
Code: NON-AI MPL 2.0 Artwork: — NO AI training. NO reproduction. NO exceptions.
Unauthorized use of the artwork — including but not limited to copying, distribution, modification, or inclusion in any machine-learning training dataset — is strictly prohibited and will be prosecuted to the fullest extent of the law.



