メインコンテンツまでスキップ

CommandGraph:ノードベースのイベントスクリプティング

CommandGraph は、NPC の行動、カットシーン、クエスト、インタラクティブなイベントを作成するための MCE のビジュアルスクリプティングシステムです。コマンドを接続してイベントの流れを定義するノードベースのエディターを提供し、C# コードは不要です。

これは、すべてのエディションで MCE を扱うゲームデザイナーにとっての主要なツールであり、ソースコードが含まれないコンパイル版のエディションも含まれます。

グラフが生み出すもの

そのボックスは、2 ノードのグラフの出力です。プレイヤーが調べた看板と、1 つの ShowSignDialog コマンド。C# は一切書かれていません。分岐するカットシーンにも同じ形でスケールし、ランタイムは違いを区別しません。

CommandGraph とは?​

CommandGraph(ActorCommandGraph)は、Actor(ワールド内の操作可能なエンティティ)に保存されるノードグラフです。アクターが起動されると、グラフはコルーチンとして、ノードを 1 つずつ順に実行します。

すべてのアクターには複数のグラフスロットがあり、反応したいタイミングごとに 1 つずつ用意されています。

スロット実行されるタイミング
On Enable Command Graphアクターが有効化されたとき。
Loop Command Graphアクターの他のグラフが実行されていない間、繰り返し。
Interact Command Graphプレイヤーがアクターに触れたとき。
On Demand Command Graph 0 to 3他のグラフが要求したときのみ(RunOnDemand、RunMultipleOnDemand)。

特化したアクターは独自のスロットを追加します。TriggerActor には「プレイヤーが入る直前/入った/テレポートされる直前/テレポートされた」と「アクターが内部で押された」グラフがあり、ActorCharacter には「プレイヤー発見」グラフ、PushableActor には「押す」グラフがあります。

グラフは、各ノードがゲームのアクションであるビジュアルスクリプトだと考えてください。

[Root] → [ShowDialog] → [IfPlayerHasBadge]
├─ True → [GivePlayerItem] → ...
└─ False → [ShowDialog: "Come back later"]

最初のイベントを作る​

ステップ 1:アクターを作成する​

最も手早い方法は Hierarchy のメニューです。右クリックして GameObject > MCE > から既製のアクターを選びます。

メニュー作成されるもの
Blank/Character、Blank/EmptyTrigger、Blank/Invisible自分で埋めるための、空のキャラクター、トリガー、不可視アクター
NPCs/Simple dialog、NPCs/Give item、NPCs/Give monsterダイアログ、アイテムのギフト、モンスターのギフトのグラフが用意された NPC
Trainers/Static、Circle、Look around、Random look around、Random walk一般的な行動をするトレーナー
Other/Sign、Pick up item、切れる木、壊せる岩、岩、渦定番のオーバーワールドの小道具

コンポーネントを自分で追加することもできます。具体的なアクタータイプは次のとおりです。

アクタータイプトリガー用途
SimpleActorプレイヤーが調べる(グラフィックや追加ロジックなし)不可視のインタラクションポイント
ActorCharacterプレイヤーが調べる。歩く、見回す、プレイヤーを発見することができるNPC、トレーナー
TriggerActorプレイヤーが上に乗る(移動を妨げない)自動トリガー、ワープ、隠しイベント
ActorItemプレイヤーが調べると、アイテムを渡して消える地面に落ちているアイテム
PushableActorプレイヤーが押す(ActorCharacter)岩、パズルのブロック

Actor と GridSubscribingActor は抽象基底クラスです。直接追加することはありません。

ステップ 2:CommandGraph エディターを開く​

  1. アクターの GameObject を選択します。
  2. Inspector で、目的のグラフスロット(たとえば Interact Command Graph)を見つけます。
  3. Edit graph をクリックして、ノードエディターのウィンドウを開きます。Delete graph はグラフを空にします。

ステップ 3:ノードを追加する​

  1. グラフエディターで右クリックします。
  2. Create Command / <カテゴリ> / <ノード> を選びます。カテゴリはノードのフォルダーです(後述)。
  3. あるノードの出力ポートから別のノードの入力ポートへドラッグして、ノードを接続します。

ステップ 4:ノードを設定する​

ノードをクリックすると、Inspector パネルでそのフィールドを編集できます。ダイアログのテキスト、ギフトのアイテムと数量、テレポートのタイル、条件の変数などです。

ノードのカテゴリ​

これらは Create Command メニューに表示されるカテゴリです。以下のリストは各カテゴリで最も有用なノードを挙げたもので、完全なセットはメニューにあります。

Dialogs​

ノード説明
ShowDialog通常のダイアログを表示
ShowChoiceDialogプレイヤーが選択するダイアログを表示(選択肢ごとに 1 つの出力ポート)
ShowSignDialog看板のダイアログを表示
ShowNoSkippableDialogプレイヤーがスキップできないダイアログを表示
NextDialog次のダイアログへスキップ
ShowUsedMoveDialogモンスターが技を使ったことを知らせるダイアログ
ShowMonsterPictureモンスターの正面画像を枠付きウィンドウに表示、または取り下げ

Variables​

条件と変数の変更。すべての If... ノードには、True と False の 2 つの出力ポートがあります。

ノード説明
SetBoolVariable、SetIntVariableゲーム変数を設定
IfBool、IfIntEquals、IfIntComparebool、または値と比較した int(小さい、大きい、等しい…)で分岐
IfIntVariablesCompareint 変数を別の int 変数と比較
SwitchIntVariableint 変数の値ごとに 1 つの出力ポート
WhileBool、WhileCondition条件が成り立つ間ループ
IfPlayerCharacterIs、IfPlayerDirectionIs選択されたプレイヤーキャラクター、またはその向きで分岐
SetTemporalBoolVariable、SetTemporalIntVariable、IfTemporalBool実行中のアクターの変数で、ゲームとともに保存されないもの

ゲーム変数は、変数参照(グローバルストレージ、またはシーンのストレージ)を通じて選択します。セーブデータに保存され、任意のグラフやスクリプトから読み取れます。

Items​

ノード説明
GivePlayerItem、TakePlayerItemプレイヤーのバッグにアイテムを追加/削除
GivePlayerMoneyプレイヤーにお金を渡す
IfPlayerHasItemプレイヤーがアイテムを持っているかで分岐
ChooseItemDialogプレイヤーにアイテムを選ばせ、それに応じてコマンドを実行

Monsters​

ノード説明
GiveMonstersプレイヤーにモンスターを渡す(固定の種またはランダム)。オンラインレイヤーでは grant id が必要です:モンスターギフト を参照
HealPlayerRosterパーティ全体を回復
ChooseMonsterDialog、ChooseTwoMonstersDialogプレイヤーに 1 体または 2 体のモンスターを選ばせる
ChangeMonsterNickname、RemoveMonsterNicknameモンスターの名前を変更
MoveTutor、RemindPreviouslyLearntMoves技を教える、または過去に覚えた技を思い出させる
IfMonsterCanLearnMove、IfRosterHasMove技で分岐
OpenStorageモンスターストレージを開く

Battles​

ノード説明
SingleTrainerFight1 人のトレーナーと戦う
SingleWildFight、DoubleWildFight野生モンスターとの戦いを開始
FightFromTemplateバトルテンプレートから戦いを開始
RandomFightAgainstRandomRosters1 つまたは 2 つのランダムなロースターとのランダムな戦い
StartTowerRunバトルタワーのランを開始
IfCanHaveDoubleBattleダブルバトルが可能かどうかで分岐

Badges, Dex, Quests​

ノード説明
GiveBadge、IfPlayerHasBadgeバッジを渡す/持っているか確認
GiveDex、IfPlayerHasDex、IfDexIsComplete、RegisterMonsterAsSeen図鑑の処理
StartQuest、UpdateQuestObjective、ProgressQuestObjective、CompleteQuest、FailQuestクエストの進行(クエストシステム を参照)
IfPlayerHasQuest、IfCompletedQuest、IfQuestFailed、IfCurrentQuestObjectiveクエストの状態で分岐

Animations​

キャラクター、プレイヤー、画面。

ノード説明
Move、MovePlayer、WalkToPlayerキャラクター、プレイヤー、またはプレイヤーの方へ歩かせる
Look、LookAtPlayer、ForcePlayerToLookキャラクターの向きを変える
JumpCharacter、WanderWithinRangeジャンプ、開始タイルの周りを歩き回る
HideCharacter、ShowCharacter、HidePlayer、ShowPlayerグラフィックの表示/非表示
MoveFollower、LookFollowerプレイヤーに付いてくるモンスターを歩かせる/向きを変える
FadeScreenToBlack、OpenDoor画面を暗転、アクターのタイルのドアを開く
PlayExclamation、PlayEmotionキャラクターの上にバルーンを表示:感情バルーンとエモート を参照

Sounds​

ノード説明
PlayMusic、StopMusic、SaveMusic、RestoreSceneMusicマップ自身の音楽の上にワールド音楽を重ねる
PlaySound、PlayMonsterCry、WaitForAudio効果音と鳴き声

Shops, Trade, Saves, Breeding​

ノード説明
BuyInShop、SellInShop購入または売却のショップロジックを実行
TradeSelectedMonsterプレイヤーが選んだモンスターを交換
AutoSaveIfEnabled設定で有効になっていればオートセーブ
StoreTwoSelectedMonstersInNursery、IfEggIsReady、BreedEggInNurseryAndGiveToPlayer育て屋

Utils​

ノード説明
TeleportPlayerプレイヤーを別の場所へテレポート(オンライン時はサーバーが検証)
TeleportActorInsideScene、PlaceActor現在のシーン内でアクターを移動
WaitTime、LoopXTimes、RunInParallelタイミングとフロー
LockPlayerInputカットシーン中にプレイヤーの移動をロック/解除
SetActorActive、AutoDestroy別のオブジェクトをオフにする、またはアクターを破棄
SwitchOnDayMoment、SwitchTimeOfDay時間帯で分岐、または時間帯を設定
SetLastHealLocation、SetLastHealLocationToCurrent敗北後にプレイヤーが復活する場所
LogMessageコンソールにメッセージを記録

ノードの接続​

CommandGraph はフローベースの接続モデルを使います。

  • 各グラフは Root ノードから始まります。
  • 各ノードには 入力ポートと、1 つ以上の出力ポートがあります。
  • ほとんどのノードの出力ポートはちょうど 1 つ(次のコマンド)です。If... ノードには True と False があり、ShowChoiceDialog には選択肢ごとに 1 つのポート、SwitchOnDayMoment には時間帯ごとに 1 つのポートがあります。
  • 出力ポートが接続されていないノードは、グラフのその経路を終了します。

例:ショップの NPC​

[Root]
→ [ShowDialog: "Welcome! Would you like to browse my wares?"]
→ [ShowChoiceDialog: "Buy" / "Sell" / "No thanks"]
├─ "Buy" → [BuyInShop]
├─ "Sell" → [SellInShop]
└─ "No thanks" → [ShowDialog: "Come back anytime!"]

例:クエストの依頼人​

[Root]
→ [IfBool: rescued_lost_monster]
├─ True → [IfBool: quest_reward_given]
│ ├─ True → [ShowDialog: "Thanks again!"]
│ └─ False → [GivePlayerItem: TM, 1]
│ → [SetBoolVariable: quest_reward_given = true]
│ → [ShowDialog: "Take this as thanks!"]
└─ False → [ShowDialog: "Please help me find my lost monster!"]
→ [SetBoolVariable: quest_find_monster = true]

例:ジムリーダー​

[Root]
→ [IfPlayerHasBadge: Boulder Badge]
├─ True → [ShowDialog: "You've already proven yourself!"]
└─ False
→ [ShowDialog: "I am the Gym Leader! Prepare for battle!"]
→ [SingleTrainerFight]
├─ On Player Won → [ShowDialog: "Impressive! You've earned this."]
│ → [GiveBadge: Boulder Badge]
└─ On Player Lost → [ShowDialog: "Train harder and come back!"]

SingleTrainerFight には 3 つの出力ポートがあります。通常の次のコマンドのポート、On Player Won、On Player Lost です。「負けた」経路は、ノードが敗北後にプレイヤーをリスポーンさせない設定のときだけ実行されます。

イベントのテスト​

  1. エディターで Play Mode に入ります。
  2. キャラクターをアクターの所まで歩かせます。
  3. インタラクトボタンを押します。
  4. グラフが実行され、フローを確認できます。
グラフのデバッグ

グラフが期待どおりに動作しない場合:

  1. コンソールのエラーを確認します。
  2. 参照しているゲーム変数、アイテム、モンスターが存在することを確認します。
  3. すべての出力ポートが接続されていることを確認します -- 接続されていないポートは、その経路を黙って終了させます。
  4. LogMessage ノードを追加して、実行中の値を出力します。

ベストプラクティス​

  1. アクターにわかりやすい名前を付ける。"Actor (3)" よりも "NPC_Professor_Lab" のほうが良いです。
  2. 状態にはゲーム変数を使う。アクターの有効/無効だけに頼らないでください。
  3. 両方の分岐をテストする。すべての If... ノードは True と False の両方で動作する必要があります。
  4. グラフを読みやすく保つ。空間的な配置で流れを明確にし、関連するノードをまとめます。
  5. パターンを再利用する。動作するショップ NPC ができたら、複製して他のショップ用に変更します。
  6. テストの前に保存する。CommandGraph の変更はシーンレベルの変更なので、Unity がクラッシュすると失われる可能性があります。

C# 側 -- コードからグラフを実行する、または独自のノードを書く -- については、CommandGraph API を参照してください。