If I have a Player
class that has been created in the main game scene that creates a new gameobject Inventory
:
export class Player extends Phaser.GameObjects.Sprite {
inventory: Inventory | null;
constructor(params) {
this.currentScene = params.scene;
this.inventory = null;
}
update() : void {
if (this.currentScene.keys.i.isDown && !this.inventory) {
this.inventory = new Inventory(this.currentScene, 400, 300, this);
}
}
}
And I destroy the class like so:
export class Inventory extends Phaser.GameObjects.Container {
constructor(params) {
// ... some code ...
this.currentScene = scene;
this.inventoryBars = this.currentScene.add.group();
this.currentScene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.J).once('down', () => {
this.destroyInventory();
});
// ... more code ...
}
destroyInventory() {
this.currentScene.player.inventory = null;
this.inventoryBars.destroy(true);
this.destroy(true);
}
}
Why do I need to get a reference to the parent player.inventory
and set it to null
in order to completely remove it? Shouldn’t this.destroy(true)
take care of it?
Hi @joshuar500, welcome to the Phaser group.
When you call this.destroy(true)
what you are doing is telling that gameobject to remove itself from the displaylist, from the updatelist and from some Phaser’s internal systems like the input manager. It will also clear all its references to its parents (scene, container, etc).
BUT the property this.currentScene.player.inventory
in your Player
class still has a reference to that instance of Inventory
so the Javascript garbage collector cannot remove it from memory. Your Inventory
instance is effectively destroyed (Phaser cannot use it again) but it will remain in memory until you clear all references to it (setting them to null
).
@jackfreak Thanks for the quick response! Just to be sure: this.currentScene.player.inventory
inside of the Inventory
class has a context reference to the Player
class’s scene and this.currentScene
inside of the Player
class has a reference to the parent class of whatever instantiates that class (in this case the game scene). And because I instantiate new Inventory
with the Player’s this.currentScene
, I am actually keeping a reference to that instantiation, and destroy()
won’t have any affect to that reference – it only “destroys” in the sense of cleaning up Phaser system stuff?
I’m wondering then, if there is a better way to do this so that the destroy()
method (or maybe something else) also resets the variable in the Player
class to clean up unused references. I can imagine holding references in a lot of variables without resetting them somehow can build up memory usage. I have tried just using the scene
parameter for GameObject’s but have gotten errors in the past. Any ideas for GameObjects that are nested inside of classes like this?
To be honest you lost me there
All I can say is that destroy() only clears up Phaser system stuff like you said, you are still in charge to clear all the references to the instances of Inventory so the GC will pick them up.
Currently you are triggering the destruction of the Inventory instance from within the instance itself, so you -should- clear any references to it outside the instance (means doing this.currentScene.player.inventory = null
). Doing that is not mandatory but is a good practice to make sure your destroyed instance will become free for garbage collection.
A cleaner way could be to call destroyInventory() from the Player instance, something like this:
export class Player extends Phaser.GameObjects.Sprite {
inventory: Inventory | null;
constructor(params) {
this.currentScene = params.scene;
this.inventory = null;
}
clearInventory() : void {
if(this.inventory !== null) {
this.inventory.destroyInventory();
// And then mark the instance for GC
this.inventory = null;
}
}
}
Now there’s no need of accessing this.currentScene.player.inventory
from within the Inventory instance, if that’s whats bothering you .
Hah, sorry for being so convoluted, but you definitely helped me answer my question. Thanks again @jackfreak, really appreciate all your help!
1 Like