Do I need to manually dispose of event listeners?

Hi,

I have a keyboard input object which takes care of setting up event listeners for keypresses and emitting them from the InputBus (full code below). If I go from one part of the game to another I might destroy this set of key press listeners and create a different set.

My question is to do with tidying up my event listeners when I destroy the InputKeyboard object. These three lines of code seem messy - is there a better way of doing this?

const onUpdate = (): void => this.update()

scene.events.on('update', onUpdate)
this.once('destroy', () => scene.events.off('update', onUpdate))

Basically because you have to send the exact method to scene.events.off it needs to be saved in a const. But the const is not in the scope of the destroy method of this object, so I would either need to make the const a property of the object or do this self listening thing for destroy. Either way seems messy.

Can anyone make a better suggestion or is there some way that this InputKeyboard would get garbage collected?

Thoughts appreciated!

Thanks, Gordon

import DestroyableObject from ‘…/…/Utils/DestroyableObject’
import InputBus from ‘…/InputBus’
import { InputKey } from ‘…/InputTypes’

export default class InputKeyboard extends DestroyableObject {
keys: Record<InputKey, Phaser.Input.Keyboard.Key>

constructor(scene: Phaser.Scene) {
super()
console.log(‘InputKeyboard created’)

const keyboard = scene.input.keyboard

this.keys = keyboard.addKeys({
  left: Phaser.Input.Keyboard.KeyCodes.A,
  right: Phaser.Input.Keyboard.KeyCodes.D,
  fire1: Phaser.Input.Keyboard.KeyCodes.H,
  fire2: Phaser.Input.Keyboard.KeyCodes.K,
  nextPayload2: Phaser.Input.Keyboard.KeyCodes.U
}) as Record<InputKey, Phaser.Input.Keyboard.Key>

// LISTENERS

this.keys.nextPayload2.on('down', () => InputBus.emit('nextPayload', 2))

const onUpdate = (): void => this.update()

scene.events.on('update', onUpdate)
this.once('destroy', () => scene.events.off('update', onUpdate))

}

update(): void {
if (this.keys.left.isDown) {
InputBus.emit(‘moveX’, -1)
} else if (this.keys.right.isDown) {
InputBus.emit(‘moveX’, 1)
} else {
InputBus.emit(‘moveX’, -0)
}

if (this.keys.fire1.isDown) InputBus.emit('firePrimary')
if (this.keys.fire2.isDown) InputBus.emit('fireSecondary')

}

destroy(): void {
this.keys.nextPayload2.removeAllListeners()
this.emit(‘destroy’)
}
}

scene.events.on('update', this.onUpdate, this)
// Destroy:
scene.events.off('update', this.onUpdate, this)

That’s great! I knew there would be something like that :slight_smile: