ai-behavior-trees-utility-ai について
行動木、Utility AI、または両者を組み合わせたNPC意思決定システムを実装するためのガイドです。ランタイム構成とスコアリング手法を、実装資料とともに解説します。
主な機能
- 01行動木ランタイムの設計
- 02Blackboardとノードの構成
- 03Utilityスコアリングと応答曲線
- 04アクション選択方式
- 05BTとUtility AIのハイブリッドパターン
- 06Tick、状態、パフォーマンスの指針
活用シーン
- 01再利用可能なNPC行動木ランタイムの構築
- 02現在の条件に基づくターゲットや行動の評価
- 03構造化された行動と段階的な選択の組み合わせ
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ gamedev-skills/ awesome-gamedev-agent-skills --skill ai-behavior-trees-utility-aiインストール後、Claude Code で/ai-behavior-trees-utility-aiを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/behavior-tree-core.mdbest-practices-and-pitfalls.mdpractical-examples.mdutility-ai-system.md詳細
ビヘイビアツリーとユーティリティ AI
NPC の意思決定を構成する、互いに補完し合う 2 つの方法と、それらの組み合わせ方を紹介します。 ビヘイビアツリー(BT) は、ツリーとして表現した「構造化され、優先順位が付けられた、リアクティブな」ロジックを各ステップで「ティック」します。ユーティリティ AI は、正規化された曲線でアクションを採点し、最良のものを選ぶことで、「今、各選択肢をどれだけ望んでいるか?」に答えます。構造には BT を、段階的なトレードオフが重要な場面にはユーティリティ AI を使うことで、信頼感のあるエージェントを実装できます。
このスキルは game-ai(FSM/BT/ステアリング/経路探索のどれを選ぶかを支援します)を補完する実装向けの資料です。モデルを選ぶには game-ai を、ランタイムを構築するにはこちらを参照してください。
使用する場面
- 再利用可能な BT ランタイム(
Blackboard、Node基底クラス、アクション/条件リーフ、Sequence/Selector/Parallelコンポジット、デコレーター(Inverter、Cooldown、Repeat))を構築する場合に使用します。 - ユーティリティ AI の判定器(レスポンス曲線、考慮要素、アクションを採点して選択する評価器(多様性を持たせるための max、softmax、または weighted-random))を構築する場合に使用します。
- リーフからユーティリティ評価器に「どの攻撃/ターゲットにするか」の選択を委ねる BT など、ハイブリッド AI を構築する場合に使用します。
使用しない場面: FSM、BT、ステアリング、経路探索のどれを選ぶかを決める場合や、A*/ナビメッシュによる経路探索には game-ai を使用してください。Unreal のアセットベースの BehaviorTree/Blackboard、BTTask/BTService、AIController には unreal-behavior-trees を使用してください。NPC を移動させるナビメッシュエージェントには unity-navmesh またはエンジンのナビゲーションノードを使用してください。
基本的なワークフロー
- モデルを選びます。 構造化され、優先順位が付けられ、中断可能な動作 → BT。継続的に「すべての選択肢を採点する」意思決定(ターゲット選定、欲求、アイテム選択) → ユーティリティ AI。両方 → ハイブリッド。
- まず Blackboard を設計します。 エージェントごとに 1 つ用意する型付きキー/値ストアが、ノード間を疎結合にする共有メモリになります。リーフはこれを読み書きし、互いへの参照は保持しません。
- リーフを作成します。 条件 は即座に
Success/Failureを返し、アクション は完了するまでフレームをまたいでRunningを返します。リーフは小さく保ち、副作用を明示します。 - 組み合わせます。
Selector= OR/フォールバック(最初に Failure 以外を返したものが勝ちます)。Sequence= AND(最初に Success 以外が返された時点で停止します)。Parallelは並行分岐に使用します。デコレーターでラップし、ポリシー(反転、クールダウン、繰り返し、強制的な Success)を適用します。 - ユーティリティ AI の場合: 考慮要素を列挙し、生の事実を正規化された 0..1 の曲線に通して値を変換し、組み合わせます(補正付きの加重積、または加重和)。その後、最大値を選択します。同点でエージェントが頻繁に選択を切り替えないよう、ヒステリシスを加えます。
- 意図的にティックします。 ツリー/評価器は意思決定ステップごとに 1 回ティックします(多くの場合、レンダリングより低頻度です)。ティック間で
Runningの状態を保持します。調整中にアクティブなパスとアクションごとのスコアを画面に表示して検証してください。
アーキテクチャの概要
ビヘイビアツリーは上から下、左から右に評価され、各ノードはステータスを親に返します。
flowchart TD
Root["Selector (root)"] --> Combat["Sequence: Combat"]
Root --> Patrol["Action: Patrol"]
Combat --> See["Condition: CanSeePlayer?"]
Combat --> InRange{"Selector: Reach"}
Combat --> Attack["Action: Attack (Running)"]
InRange --> Close["Condition: InAttackRange?"]
InRange --> MoveTo["Action: MoveToPlayer (Running)"]
ユーティリティ AI は採点パイプラインです。候補となるすべてのアクションを採点し、その後 1 つを選択します。
facts (distance, health, ammo…)
│ each fact → a normalized 0..1 response curve (consideration)
▼
score(action) = weight · combine(consideration_1 … consideration_n) # product+compensation or sum
▼
select: argmax · or softmax / weighted-random for variety · + hysteresis to avoid jitter
ステータスは、すべてのノードで共有される 3 値の enum です。これがツリーの合成を可能にする契約です。
public enum Status { Success, Failure, Running }
public abstract class Node
{
public abstract Status Tick(Blackboard bb, float dt);
public virtual void Reset() { } // called when a parent abandons this subtree
}
// Selector = fallback/OR: return the first child that is not Failure.
public sealed class Selector : Composite
{
public override Status Tick(Blackboard bb, float dt)
{
for (; _current < Children.Count; _current++)
{
var s = Children[_current].Tick(bb, dt);
if (s != Status.Failure) return s; // Success or Running stops the scan
}
_current = 0;
return Status.Failure; // every child failed
}
}
相互に補完する Sequence(AND — 最初に Success 以外が返された時点で停止)、Parallel、Blackboard、リーフの基底クラス、すべてのデコレーターについては、references/behavior-tree-core.md を参照してください。
ユーティリティの採点を 1 つのスニペットで
// A consideration maps one raw fact to 0..1 through a response curve.
float Score(Blackboard bb)
{
float distance01 = Curves.InverseLerp01(bb.Get<float>("distToPlayer"), 20f, 2f); // near = 1
float health01 = Curves.Sigmoid(bb.Get<float>("health01"), k: 8f, mid: 0.4f); // hurt = low
// Product + compensation keeps a single 0 from vetoing while low values still dampen.
return Curves.CompensatedProduct(new[] { distance01, health01 });
}
曲線ライブラリ(線形、二次、指数、ロジスティック/シグモイド、smoothstep)、Consideration/UtilityAction 型、UtilityEvaluator の選択戦略については、references/utility-ai-system.md を参照してください。
落とし穴
- 毎フレーム、ルートから
Running状態のアクションを再度ティックすると、再起動されます。Runningを返して前回の続きから再開し、親が実際にサブツリーを放棄した場合にのみReset()します。 - 深いツリー全体を毎ティック再評価すると、時間がかかり、処理の無駄な繰り返しが発生します。 ツリーは浅くし、条件付き中断(優先度の高い条件が低いブランチを中断できる仕組み)を利用してください。
- 考慮事項が正規化されていません。 あるカーブが0~100、別のカーブが0~1を出力すると、値の大きいほうが支配的になります。すべての考慮事項は0~1を返す必要があります。
- 僅差の場合、ユーティリティ選択が揺らぎます。 ヒステリシスを加え、現在実行中のアクションに少しボーナスを与えることで、エージェントが選択を維持し、頻繁に切り替わるのを防ぎます。
- 毎ティック、ノード、クロージャー、配列を割り当てると、GCのスパイクが発生します。 スポーン時にツリーを一度だけ構築し、毎ティックの処理でメモリを割り当てないようにしてください。
参考資料
references/behavior-tree-core.md— Blackboard、Node/リーフの基底クラス、アクションおよび条件リーフ、Sequence/Selector/Parallel、デコレーターライブラリ(C#完全版)。references/utility-ai-system.md— 反応カーブライブラリ、Consideration、UtilityAction、UtilityEvaluator(argmax、softmax、重み付きランダム、ヒステリシス)。references/practical-examples.md— ガードのPatrol→Combat BT、村人のニーズに基づくUtility AI、ハイブリッドエージェントのすぐに使えるテンプレート。references/best-practices-and-pitfalls.md— メモリ管理、プロファイリング、深いツリーの回避、イベント駆動の中断、Utility AIとBTの組み合わせ(ハイブリッドアーキテクチャ)。
関連スキル
game-ai— FSM/BT/ステアリングの選択、A*およびナビメッシュによる経路探索。unreal-behavior-trees— UnrealのアセットベースのBT/Blackboard、タスク、デコレーター、サービス。unity-navmesh— 「移動」インテントを実行するNavMeshAgent。physics-tuning— モーションレイヤーのエージェントの半径、移動、衝突応答。tower-defense、fps-shooter、rpg— この意思決定レイヤーを組み込むジャンル。