ステートマシン
はじめに
ステート・マシンは、状態管理を単純化するために設計されている。
ステートマシンは3つの主要コンポーネントから構成される:
- 州
- 州グループ
- トリガー
ステートマシンは常に正確に1つの状態にあり、(トリガーによって定義された)特定の条件が満たされたときに状態間を遷移する。 ステート・グループは、複数のステート間で共有されるロジックを束ねる便利な方法だが、グループそのものはステートではない。
例
ecs.registerComponent({
name: 'Jump On Touch',
stateMachine: ({world, entity, defineState}) => {
const idle = defineState('idle').initial().onEnter(() => {
console.log('アイドル状態に入る')
}).onEvent(ecs.input.SCREEN_TOUCH_START, 'jumping')
const jumping = defineState('jumping').onEnter(() => { console.log('ジャンプ状態に入る') ecs.physics.applyImpulse(world eid 0 5 0) }.onEnter(() => {
console.log('Entering jumping state')
ecs.physics.applyImpulse(world, entity.eid, 0, 5, 0)
}).onTick(() => {
console.log('In jumping state')
}).wait(2000, 'idle')
},
}).
ステートマシンの定義
コンポーネント内にステートマシンを作成する場合、関数は次のように呼び出される:
プロパティ
| プロパティ | タイプ | 説明 |
|---|---|---|
| 世界 | 世界 | 世界への言及。 |
| イード | イード | 現在のコンポーネントのエンティティID。 |
| エンティティ | エンティティ | 現在のコンポーネントのエンティティインスタンス |
| 定義状態 | function | ステートマシンの状態を定義する関数 |
| defineStateGroup | function | ステートマシンのグループを定義する関数 |
| スキーマ属性 | ワールド属性 | ワールドスコープにおける現在のコンポーネントのスキーマへの参照。 |
| データ属性 | ワールド属性 | ワールドスコープにおける現在のコンポーネントのデータへの参照。 |
次のコードは、空のステートマシンを定義する方法の例である:
ecs.registerComponent({
...
stateMachine: ({world, entity, defineState}) => {
// ここで状態を定義する
},
})
州
ステートとは、ステートマシンの基本的な原子単位である。 ステートマシンの可能な状態を定義した後、トリガを定義することで状態間を移動でき る。
州の定義
次のコードは、コンポーネント内のステートマシン内で新しいステートを定義する方法の例です。
ecs.registerComponent({
...
stateMachine: ({world, entity, defineState}) => {
const foo = defineState('foo')
...
}
})
State関数は "フルエント "であり、Stateの同じインスタンスを返すので、1つのステートメントで複数の関数呼び出しを連鎖させることができる。
.initial()
ステートマシンの作成時に、この状態を最初のアクティブ状態としてマークする。
defineState('myCustomState').initial()
.onEnter()
この状態になったときに実行するコールバックを設定する。
defineState('myCustomState').onEnter(() => {
// 何かをする
})
.onTick()
この状態がアクティブな間、毎フレーム実行するコールバックを設定する。
defineState('myCustomState').onTick(() => {
// 何かをする
})
.onExit()
この状態を終了するときに実行するコールバックを設定します。
defineState('myCustomState').onExit(() => {
// 何かをする
})
.onEvent()
特定のイベントを受信すると、新しい状態に遷移する。
| パラメータ | タイプ | 説明 |
|---|---|---|
| イベント (必須) | ストリング | リッスンするイベント名 |
| nextState (必須) | 文字列または州 | イベント発生時に遷移する状態 |
| オプション(オプション) | オブジェクト | 追加オプション |
オプション
| パラメータ | タイプ | 説明 |
|---|---|---|
| ターゲット | イード | イベントを受信すると予想されるエンティティ(デフォ ルトは現在のエンティティ) |
| どこ | (event) => boolean | トランジションする前にチェックするオプションの条件。 |
defineState('myCustomState').onEvent(
ecs.input.SCREEN_TOUCH_START,
'other',
{
target: world.events.globalId,
where:(event) => event.data.position.y > 0.5
}.
)
.wait()
一定時間後に新しい状態に移行する。
| パラメータ | タイプ | 説明 |
|---|---|---|
| タイムアウト | 番号 | 遷移するまでの時間(ミリ秒単位 |
| 次の状態 | 文字列または州 | 次に遷移する状態 |
defineState('myCustomState').wait(1000, 'myOtherCustomState')
.onTrigger()
TriggerHandle(ecs.defineTrigger()で定義)がトリガーされた時に新しい状態に遷移する。
| パラメータ | タイプ | 説明 |
|---|---|---|
| ハンドル | トリガーハンドル | 手動で作動させたときにトランジションを起こすハンドル |
| 次の状態 | 文字列または州 | 次に遷移する状態 |
const toOther = ecs.defineTrigger()
defineState('example').onTrigger(toOther, 'other')
...
toOther.trigger()
.listen()
ステートに入ると自動的に追加され、ステートが終了すると削除されるイベントリスナーを登録します。
| パラメータ | タイプ | 説明 |
|---|---|---|
| ターゲット | eidまたは() => eid | イベントを受信すると予想されるエンティティ |
| 名称 | ストリング | 注目のイベント |
| リスナー | (イベント) => void | イベントがディスパッチされたときに呼び出される関数 |
const handleCollision = (event) => {
console.log('Collided with', event.data.other)
}
defineState('example').listen(eid, ecs.physics.COLLISION_START_EVENT, handleCollision)
州グループ
ステートグループは、ステートのリストに適用される動作とトリガーを定義する方法です。 国家グループは国家そのものではないので、直接移行することはできない。 その代わり、グループ内のいずれかのステートがアクティブになると、グループのビヘイビアとトリガーもアクティブになる。
ステート・グループの定義
| パラメータ | タイプ | 説明 |
|---|---|---|
| サブステート(オプション) | 文字列または状態の配列 | このグループを構成する州のリスト。このパラメータを除外すると、すべての州をリストアップすることになる。 |
const fizz = defineState('fizz')
const buzz = defineState('buzz')
const fizzBuzz = defineStateGroup([fizz, 'buzz'])
ステート・グループ関数は "フルエント "であり、ステート・グループの同じインスタンスを返すので、1つのステートメントで複数の関数呼び出しを連鎖させることができる。
.onEnter()
このグループに入るときに実行するコールバックを設定します。
defineStateGroup(['a', 'b']).onEnter(() => {
// 何かをする
})