ゲームにダイアログツリーシステムを実装する最良の方法は何ですか?NPCに、プレーヤーにさまざまな応答セットを提供します。応答の一部は、プレーヤーにアイテムがあるか、前のイベントが発生したときにのみ表示されます。
ゲームにダイアログツリーシステムを実装する最良の方法は何ですか?NPCに、プレーヤーにさまざまな応答セットを提供します。応答の一部は、プレーヤーにアイテムがあるか、前のイベントが発生したときにのみ表示されます。
回答:
ダイアログツリーはXMLを使用して実行する必要があります。より複雑な操作を行う必要がある場合は、スクリプトファイルへの参照を使用して、応答の条件と応答をネストされたツリーに保存します。
特に数トンの会話に値するRPGをまとめる場合は、スクリプトとダイアログを分離しておく必要があります。その後、simpleXMLなどのライブラリを使用して、XMLファイルを読み取ることができます。
SOについても同様の質問があります。例:https : //stackoverflow.com/questions/372915/game-logic-in-xml-files
私は、luaやrubyのようなスクリプト言語を埋め込み、ダイアログ対話をコーディングすることを検討します。
したがって、ダイアログスクリプトは次のようになります。
switch showDialog "Why don't you just leave me along!", "Okay", "But I found your dog!"
case 1:
showDialog "And stay gone!"
case 2:
if playerHasObject "dog"
showDialog "Thank you!"
else
showDialog "Liar!"
これは、AIのコーディングや、実行時に微調整するのに役立つその他の単純なものにも適しています。デバッグで(またはイースターエッグとして)実行中に起動できるエディターをアプリケーションに追加することもできます。
ゲームStendhalでは、有限状態マシンを使用してNPCを実装します。
次の図は、クエストチュートリアルの書き方の小さな例を示しています。
最初は、NPCはアイドル状態にあり、歩き回っている可能性があります。プレイヤーは「こんにちは」と言って会話を始めることができ、NPCは参加中の状態になります。この状態では、彼の「ジョブ」に関する質問に答え、ゲームの「ヘルプ」を提供します。プレイヤーがクエストを要求すると、NPCはプレイヤーがクエストを受け入れる(「はい」)または拒否する(「いいえ」)のを待つ状態QUEST_OFFEREDになります。
遷移に付加できる一連の条件を定義しました。たとえば、クエストを完了することは、PlayerHasItemWithHimConditionが満たされた場合にのみ可能です。
トランジションが実行された後、NPCはテキストを言ったり、アクションを実行したりできます。条件と同様に、プレイヤーにクエスト報酬を与えるために使用されるEquipItemActionのような再利用可能なアクションのセットを定義しました。
AndCondition、OrCondition、およびNotConditionを使用して、複数の条件を組み合わせることができます。通常、クエストの完了時に実行されるアクションが多数あるため、MultipleActionsクラスもあります。
Stendhalでの実際の実装は、他の(人間の)言語で簡単に翻訳できないことに苦しんでいますが、一般的な概念は良いと思います。
翻訳を追加する場合、上記のロジックに引き続きXMLを使用できます。そのような複雑さを経験する場合、独自の対話ツールを作成する必要があります。対話テキストは、表示する言語に応じて交換できるデータベースのキーとして保存されます。
たとえば、次のことができます。
<dialogue id="101" condition="!npc.carsFixed">
<message>Localize.FixMyCar</message>
<choices>
<choice condition="hero.carFixingSkill > 5" priority="7" id="Localize.Sure">
<command>hero.carFixingSkills += 1</command>
<command>npc.carFixed = true</command>
<command>hero.playSmokeAnimation()</command>
<command>nextDialogue = 104</command>
</choice>
<choice condition="hero.carFixingSkill <= 5" id="Localize.CantFix">
<command>nextDialogue = 105</command>
</choice>
<choice id="Localize.FixYourself">
<command>npc.likesHero -= 1</command>
</choice>
</choices>
</dialogue>
次に、クエストテキストレンダラーで「Localize.FixMyCar」を適切に翻訳されたテキストに置き換えます。
ツールは、プレーヤーが編集可能な生のXMLとともに選択可能な言語で表示するものを表示します。
npc.add(ConversationStates.ATTENDING,
ConversationPhrases.QUEST_MESSAGES,
null,
ConversationStates.QUEST_OFFERED,
Localization[ "BringMeABeer" ],
null);
キーが十分に説明的である場合、完全なテキストを持たなくても問題になりません。
このようなものも同様に便利です:
Localization[ "<Location>.<NPC_name>.<Dialogue_text_key>" ];
かなり深いダイアログツリーのセットがある場合は、ChatMapperを使用します。完全に機能する無料バージョンがあり、このツールを使用すると、ダイアログツリーをXMLにエクスポートできます。私はこれを使用してきましたが、複雑なダイアログツリーを視覚化して整理するための優れた方法です。
ダイアログが複雑な場合、ダイアログの実装に必要な最も重要なことは、対話の複雑さを理解する方法です。これを視覚化するために、何らかの種類のノードエディタをお勧めしますが、推奨する優れたオープンシステムはありません。
単純なオートマトンは次のことを行います。
(dialogueline_id, condition) -> (next_id, response)
次のようになります。
(1, troll is hungry?) -> (2, say "troll be hungry")
(2, player has bananas?) -> (3, say "hey, you have bananas!")
(3, ) -> (-1, (say "i like bananas, i take them and eat, you may pass, bye", remove bananas, feed the troll))
(2, player does not have bananas?) -> (-1, say "go away!!!")
ゲームでは、IDを見つけ、IDと条件を一致させようとします。
条件とアクションをモデル化する必要があります。オブジェクト、関数ポインター、XML ...
優れたダイアログエディターも便利です。