Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
Unity 1week でつくったゲームに AIを実装してみる 2021/1/13 とりすーぷ
Slide 2
Slide 2 text
自己紹介 •とりすーぷ • @toRisouP • VR系の開発してる • Microsoft MVP • (Developer Technologies) • 最近はVRChatしてます illustrations by kota(@kt_kkz)さん
Slide 3
Slide 3 text
あけろ!爆裂駐車場! https://unityroom.com/games/bakuretsu
Slide 4
Slide 4 text
Unity 1Weekでつくったゲーム •「あけろ!爆裂駐車場!」 • 次から次へと車が押し寄せる駐車場を空けるゲーム
Slide 5
Slide 5 text
駐車場をあけろ! •次々にやってくる車を駐車場から排除しろ! • 車はぶっ壊してもOK • 外野にふっとばしてもOK!
Slide 6
Slide 6 text
武器 •武器アイテムを拾って装備を変えよう!
Slide 7
Slide 7 text
ワンミスで終了だ! •やられたら終了! • 爆発に巻き込まれたり、フィールドから落ちたら終わり
Slide 8
Slide 8 text
こだわりポイント •VRM読み込みに対応 • 好きなアバターであそべる!
Slide 9
Slide 9 text
AIを実装してみる
Slide 10
Slide 10 text
このゲームにAIを実装してみよう •目標 • AIが自動的にプレイヤを操作する • 状況を判断して適切な行動を取り続ける
Slide 11
Slide 11 text
できたもの 公開してます:https://unityroom.com/games/akebaku_ai
Slide 12
Slide 12 text
手法 •「Behavior Tree」 • 階層構造をもったステートマシンみたいなもの • “状態”ではなく“行動”について評価をする
Slide 13
Slide 13 text
Behavior Tree Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する • 階層構造をもったグラフで AIの行動パターンを定義する • 深さ優先、左端優先
Slide 14
Slide 14 text
Node Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する ノード → ノード → ノード → ノード → • 各要素を「ノード」と呼ぶ
Slide 15
Slide 15 text
• 各ノードは状態を持つ • 成功 • 失敗 • (実行中) • (待機中) 状態 Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する
Slide 16
Slide 16 text
ノードの種類 Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する • ノードは大きく2種類に分類される • Control Flow ノード • Task ノード
Slide 17
Slide 17 text
Behavior Tree Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する • Task • 実際にAIがとる「行動」を表す これらがTask→
Slide 18
Slide 18 text
Control Flow Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する • Control Flow • 全体の”流れ”を司るノード • 種類がいくつかある • SelectorとSequence の2つがメインに使われる Control Flow
Slide 19
Slide 19 text
Sequence Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する • Sequence • 子のノードを左から実行 • 子がすべて成功したら「成功」 • 子が1つでも失敗したら「失敗」 になり即終了 • 要するにAND
Slide 20
Slide 20 text
Selector Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する • Selector • 子のノードを左から実行 • 子が成功した時点で「成功」 • 子がすべて失敗したら「失敗」 • 要するにOR
Slide 21
Slide 21 text
Repeat Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する • Repeat • 子の処理をずっと繰り返す
Slide 22
Slide 22 text
このグラフの挙動 Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する
Slide 23
Slide 23 text
このグラフの挙動 Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する 1. 敵が近くにいるか判定する 2. 見つけた敵に向かって移動する 3. 攻撃する
Slide 24
Slide 24 text
このグラフの挙動 Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する 1. 敵が近くにいるか判定する 2. 見つけた敵に向かって移動する 3. 攻撃する ↑が失敗したら↓を実行する 1. フィールド中央に移動する 2. 待機する
Slide 25
Slide 25 text
Case1: 敵が近くにいた場合 Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する 実行中 待機中 実行中
Slide 26
Slide 26 text
Case1: 敵が近くにいた場合 Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する 「1.敵が近くにいるか?」を実行する 実行中 待機中 待機中 実行中 実行中 待機中
Slide 27
Slide 27 text
Case1: 敵が近くにいた場合 Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する 「1.敵が近くにいるか?」が成功する → 次に処理が移る 実行中 待機中 待機中 実行中 実行中
Slide 28
Slide 28 text
Case1: 敵が近くにいた場合 Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する 「2.対象に移動する」が成功する → 次に処理が移る 実行中 待機中 実行中 実行中
Slide 29
Slide 29 text
Case1: 敵が近くにいた場合 Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する 「3.攻撃する」が成功する → Sequence自体が「成功」する 待機中 実行中
Slide 30
Slide 30 text
Case1: 敵が近くにいた場合 Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する Selectorも「成功する」 → Repeatによって最初に戻る 待機中
Slide 31
Slide 31 text
Case2: 敵が近くにいなかった Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する 実行中 待機中 実行中 「1.敵が近くにいるか?」を実行する 待機中 実行中 待機中
Slide 32
Slide 32 text
Case2: 敵が近くにいなかった Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する 実行中 待機中 実行中 「1.敵が近くにいるか?」を実行する → 失敗する 待機中 待機中
Slide 33
Slide 33 text
Case2: 敵が近くにいなかった Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する 待機中 実行中 「1.敵が近くにいるか?」を実行する → 失敗する → 続きは実行されずSequence自体が 失敗となる 待機中 待機中
Slide 34
Slide 34 text
Case2: 敵が近くにいなかった Selector Sequence 敵が近くに いるか? Sequence 対象に 移動する 攻撃する フィールド 中央に 移動する 待機する 実行中 実行中 Selectorにより次のブロックに処理が移る 待機中 待機中 実行中
Slide 35
Slide 35 text
アセットを使うと楽 •Behavior Designer
Slide 36
Slide 36 text
昔に解説してるので参考になれば •【Unity】 Behavior TreeでAIを作る • https://www.slideshare.net/torisoup/unity-behavior-treeai
Slide 37
Slide 37 text
UnityでAIをつくっていく
Slide 38
Slide 38 text
AIを実装していく •今回は「Behavior Designer」を使って、 「あけろ!爆裂駐車場!」にAIを実装する
Slide 39
Slide 39 text
方針 「Playerのコンポーネントには手を加えない」 • プレイヤーの移動、攻撃、アイテム装備…、 すべて同じコンポーネントをそのまま使いまわす
Slide 40
Slide 40 text
差し替える部分はどこか? •「入力イベント」のみを差し替える
Slide 41
Slide 41 text
人間が遊ぶ場合 人間 入力イベント プレイヤキャラクタ
Slide 42
Slide 42 text
AIの場合 AI 入力イベント プレイヤキャラクタ
Slide 43
Slide 43 text
イベントを使い回せば ここの処理は全く同じにできる! 入力イベントの発行者が 異なるだけで
Slide 44
Slide 44 text
入力の抽象化レイヤを挟む 人間やAIから入力されたイベント をいい感じに変換するレイヤ
Slide 45
Slide 45 text
抽象化 •入力イベント発行機構を抽象化しておく
Slide 46
Slide 46 text
人間が操作するとき •キーボードからの入力をイベントに変換する
Slide 47
Slide 47 text
AIが操作するとき •AIからの入力をイベントに変換する • AIに「ゲームパッド」を持たせるイメージ
Slide 48
Slide 48 text
プレイヤ初期化時に差し替える •差し替えるのは基本これだけ • これでAIがプレイヤを操作する口ができた
Slide 49
Slide 49 text
これで入力イベントが共通化できた IInputEventProvider
Slide 50
Slide 50 text
他の下準備 •AI用にいくつか下準備をしておく
Slide 51
Slide 51 text
Playerにコンポーネントを追加 •「Behavior Designer」と「NavMeshAgent」
Slide 52
Slide 52 text
AI用の情報提供クラス •AIがゲームの状態を知るための仲介クラス
Slide 53
Slide 53 text
AIの実装
Slide 54
Slide 54 text
ロジック 1. 燃えている車があったら、逃げる 2. アイテムが近くにあったら、拾う 3. 車があったら、近づいて攻撃する 4. ステージ中央に向かう
Slide 55
Slide 55 text
ロジック 1. 燃えている車があったら、逃げる 2. アイテムが近くにあったら、拾う 3. 車があったら、近づいて攻撃する 4. ステージ中央に向かう 優先度が高い処理から試行していく 条件を満たさない場合は次の処理を試す
Slide 56
Slide 56 text
AIの実装手順 1. Taskノードを自作する 2. ノードグラフを構築する 3. 動作確認して調整する
Slide 57
Slide 57 text
Taskノードの自作 •Behavior Designerは“行動”を自作可能 • C#のスクリプトを書けば簡単に作れる • 必要なタスクを自分で作ってしまえばOK
Slide 58
Slide 58 text
車を探すTask
Slide 59
Slide 59 text
車を探すTask 毎フレーム実行される Runningを返すと継続 Success / Failureを返すと終了
Slide 60
Slide 60 text
例:「移動する」Taskの実装 InputEventProviderに渡してPlayerの移動に反映する NavMeshAgentから得た経路の情報を
Slide 61
Slide 61 text
結果
Slide 62
Slide 62 text
No content
Slide 63
Slide 63 text
4つのブロックにわかれている
Slide 64
Slide 64 text
1.燃えている車が近くにあったら逃げる 燃えている車が 近くにあるか? 逃げる先を決定 移動する ちょっと待機
Slide 65
Slide 65 text
2.アイテムが近くにあったら拾う アイテムが 近くにあるか? 移動する
Slide 66
Slide 66 text
3.車があったら攻撃しにいく 車を探す 移動する 攻撃する
Slide 67
Slide 67 text
4.ステージ中央に向かう
Slide 68
Slide 68 text
動作させながら微調整 •パラメータを調整する •挙動を細かく調整する
Slide 69
Slide 69 text
例:調整箇所 •「攻撃するために移動する」 • 武器ごとにリーチに差がある • ロケランは自爆の可能性がある → 装備武器ごとに対象にどれだけ近づくか変える
Slide 70
Slide 70 text
調整 •武器ごとにどれだけ車に近づくか変える • 近接武器はより近づく、ロケランは遠くで止まる
Slide 71
Slide 71 text
他にも調整したい箇所は山程ある •移動中に障害物でスタックしたときどうする •攻撃が届かないシチュエーションを減らす •場外に飛んでいった車に反応しないようにする •戦車から逃げる •爆風に自分から突っ込まないようにする
Slide 72
Slide 72 text
まとめ •Behavior Treeはいいぞ • 比較的かんたんにAIを実装できる! • それっぽく動くところまでの実装時間は約3時間 • ただしそこから微調整で+6時間くらい… • あらかじめAIの実装を許容する設計にしておく必要はあり • 適切に処理を抽象化しておこう
Slide 73
Slide 73 text
以下おまけ
Slide 74
Slide 74 text
AIを移動させる •Unityには「NavMesh」という機能がある • 経路探索を用いてオブジェクトを移動させる機能 • これを使えば障害物を避けていい感じに移動してくれる
Slide 75
Slide 75 text
NavMeshAgentの利用方法 •NavMeshAgent • NavMeshに沿ってオブジェクトを動かすコンポーネント • デフォルトだとこのコンポーネントで勝手に移動していく → NavMeshAgentによる自動移動を今回はOFFにする
Slide 76
Slide 76 text
NavMeshを使ったAI操作
Slide 77
Slide 77 text
NavMeshを使ったAI操作 NavMeshAgentの認識する「現在地」を 自分のtransform位置に補正する
Slide 78
Slide 78 text
NavMeshを使ったAI操作 NavMeshAgent.desiredVelocity で 経路探索の結果から移動するべき方向が取得できる
Slide 79
Slide 79 text
NavMeshを使ったAI操作 移動するべき方向をInputEventProviderに渡して Playerの移動入力とする