メインコンテンツへスキップ

イベント

はじめに

イベントは、柔軟なリスナーとディスパッチシステムを通じて、エンティティが互いに通信する方法です。

イベント・リスナー

リスナー
PropertyType商品説明
ターゲットイードイベントがディスパッチされたエンティティ。
カレントターゲットイードイベントがリッスンされたエンティティ。
nameストリングイベント名
データいずれもイベント・カスタム・データ

イベント・リスナーの作成

追加リスナー

world.events.addListener(target, name, listener)
パラメータ一覧
tip

world.events.globalId`をターゲットとして、グローバル・イベント・リスナーを作成することができる。

PropertyType商品説明
ターゲットイードターゲット・エンティティへの参照。
nameストリングリッスンするイベント名。
リスナーリスナーイベントがトリガーされたときのコールバック関数

イベントハンドラの作成

エンティティにイベントリスナーを追加する場合、特にコンポーネントが複数のエンティティに追加される場合は、意図したとおりに機能するようにハンドラを正しく設定することが重要です。 ハンドラーの不適切な作成は、陳腐な参照や予期せぬ動作につながる可能性がある。

例えば、NPCエンティティのハンドラを作成し、破損イベントをリッスンするとします。 ハンドラは、イベントが発生したときに、いくつかのスキーマとデータ値を更新しなければならない。

誤った例

import * as ecs from '@8thwall/ecs'
import { addCleanup, doCleanup } from './cleanup'

ecs.registerComponent({
name: 'npc',
schema: {
isInjured: ecs.boolean,
}
data: {
bpm: ecs.f32,
}
add: (world, component) => {
// ハンドラの作成が正しくない
const damagedHandler = (e) => {
component.schema.isInjured = true
component.data.bpm += 30
}
world.events.addListener(component.eid, 'damaged', damagedHandler)

const cleanup = () => {
world.events.removeListener(component.eid, 'damaged', damagedHandler)
}
addCleanup(component, cleanup)
},
remove: (world, component) => {
doCleanup(component)
},
})

この例では

  • ハンドラ damagedHandler は component.schemacomponent.data を直接参照する。
  • コンポーネントが複数のエンティティに追加されると、ハンドラ内のコンポーネント参照は古くなります。
  • これは、ハンドラーが不正確なデータを操作する原因となり、バグを引き起こす可能性がある。

正しい例

ハンドラが正しいエンティティデータを操作するようにするには、コンポーネントの dataAttributeschemaAttribute をハンドラに渡し、ハンドラ内でカーソルをフェッチするためにそれらを使用する。

import * as ecs from '@8thwall/ecs'
import { addCleanup, doCleanup } from './cleanup'

// ダメージハンドラを作成する関数
const createDamagedHandler = (dataAttribute, schemaAttribute) => (e) => {
const dataCursor = dataAttribute.cursor(e.target)
const schemaCursor = schemaAttribute.cursor(e.target)
schemaCursor.isInjured = true
dataCursor.bpm += 30
}

ecs.registerComponent({
name: 'npc',
schema: {
isInjured: ecs.boolean,
},
data: {
bpm: ecs.f32,
},
add: (world, component) => {
// 正しいハンドラ作成
const damagedHandler = createDamagedHandler(component.dataAttribute, component.schemaAttribute)
world.events.addListener(component.eid, 'damaged', damagedHandler)

const cleanup = () => {
world.events.removeListener(component.eid, 'damaged', damagedHandler)
}
addCleanup(component, cleanup)
},
remove: (world, component) => {
doCleanup(component)
},
})

イベントリスナーの削除

removeListener

world.events.removeListener(target, name, listener)
パラメータ一覧
PropertyType商品説明
ターゲットイードターゲット・エンティティへの参照。
nameストリングリッスンするイベント名。
リスナーリスナーイベントがトリガーされたときのコールバック関数

イベント・ディスパッチャー

カスタムイベントのディスパッチ

派遣

インフォメーション

あるエンティティにイベントが発生すると、まずそのエンティティのハンドラが実行され、次にその親のハンドラが実行され、さらに他の祖先のハンドラが実行される。

world.events.dispatch(eidOfEnemy, "attack", {damage: 10})

リスナーの掃除

危険

メモリリークを避けるため、常にリスナーが適切に削除されていることを確認する。

コンポーネントが削除されると、そのイベントリスナーは自動的にクリーンアップされないので、手動で削除する必要があります。