Meeting】(以下、GDM)。エンジニア向け勉強会:ゲーム産業におけるゲームAI研究・開発の最前線~会話AI、メタAI、ユーザ感情推定~」では、スクウェア・エニックスのテクノロジー推進部のメンバーをお招きして、GDC2019で発表した内容を中心に、最新の研究成果を紹介していただきました。ゴティエ)氏より発表された「キャラクターとのインタラクション」について、セッション内容をレポートします。目次キャラクターとのインタラクションエモーショナルについて感情モジュールムードモジュール性格モジュール▼関連レポート記事はこちらからキャラクターとのインタラクションゴティエ氏は以前、NPCが配置されたリアルなゲーム空間で、NPCの気配に似たものを感じたことに驚き、そのヴァーチャル空間の中には自分が存在したように感じたと話しました。ゲーム内でのNPCとのインタラクションについては、ボタンを押すなど比較的古典的な方法に限られており、(NPCと)視線が合ったり、自身がどんな行動をしてもNPCは何も反応してくれなかったことが悲しかったと明かしています。そこで今回のプロジェクトでは、音声や身振りなど自然なインタラクションを開発し、プレイヤーにとって適切な反応や表現ができるような、生き生きとしたNPCを実装したとのことです。ここからはデモ映像を使用しながら説明されました。デモではまず、KOBUNと名付けられたNPC(※以下、一部エージェントと表記)や宇宙船、多彩なオブジェクトが配置されている惑星を舞台にして、音声認識を中心に指示を出していきます。指示側は「あのドアを開けて」「オレンジのクリップを持って」「白いタンクに取り付けて」などKOBUNに音声で指示をしていきます。指示通りにうまく動けなかったり、感電してしまうと、KOBUNが悲しい感情を持つことがわかります。続いて、このシステムの実装の詳細について説明されました。音声認識エンジンが入力を受け取ると、言葉と品詞のリストに変換。ゲーム側の文法パサーが言語に基づいてDNAブロックに抽象化し、その後抽象ブロックが単語に対して、言語に依存していない表現に変換します。このプロジェクトの目的は、プレイヤーの使用できる語彙を制限せずに、複数の言語をサポートすることで、そのために言葉を言語に依存しない表現に抽象化することです。それを言葉のDNA(遺伝子)だと考えました。「リンゴを取る」「休憩を取る」という2つの表現の中にある「取る」という言葉の意味合いは違います。そこで「取る」という言葉が持つすべての意味を、まずタグ付けします。言語ごとに手動でタグ付けをするのは大変なので、どうすれば自動化できるかを考えました。そこでマルチに言語をサポートする同義語のデータベース「WordNet」を利用することを決めました。「大きいリンゴ」という言語を使いたい場合、ゲームの中に「大きい」という単語を組み込みます。WordNetで「大きい」を検索、たくさんの概念の中から、自分が必要としている意味と比較して近いものを2つ選択して、DNAブロックが完成しました。言葉の抽象化のステップが終わると、パサーに移行した部分は言語に依存しなくなりました。次の目的は抽象化された言葉を、ゲームに存在している概念につなぐことです。続いて、抽象化された言葉を各概念ごとにスコア計算する作業に移行します。「巨大」という単語のDNAを探して、ゲーム内のすべての形容詞の概念と比較しますが、「巨大」は存在しないので、他の形容詞の中からスコアが高いもの、DNAが似ているものが選ばれます。Managerがゴール(最終目的)を選択し、Plannerが選択されたゴールを実行するためのプランを立てます。今回は「プレイヤーの声を聞く」というゴールが選ばれたため、「聞く」というアクションが実行され、発言を記憶に追加しました。その後、AIが命令に従うかを決めていく流れです。次に「命令を実行する」ゴールが決められ、発言では「リンゴを取る」なので、Plannerは【リンゴを探す→リンゴの近くに移動→リンゴを取る】というプランを立てました。「リンゴを探す」という発言の実行について、目的はエージェントの記憶の中で発言に対して一番適切なオブジェクトを見つけること、になります。ターゲットのスコア計算方法は、発言によるオブジェクトにどれだけ似ているかを評価しています。タイプが同じなのか、サイズが合うかを判定して、すべてを組み合わせることでターゲットのスコアを合算します。オブジェクトタイプの比較は、WordNetでは同義語が階層構造で並んでいるので、それを利用します。リンゴは一番下にある「食べられる果物」のノードの下にあります。バナナも同じノードの下にありますが、テーブルとリンゴとの共通ノードは、全体を示しているので、なかなか一致するのは難しいです。表現にあるオブジェクトの「巨大なリンゴ」をヒエラルキーから探し、そのノードに位置を設定します。次にツリーのルートに0を設定、間にあるすべてのノードのスコアを保管します。ターゲットのスコアを探してみましょう。リンゴは発言にあるオブジェクトと同じなので、1になります。バナナとの共通ノードは「食べられる果物」なので、スコアはそのノードのスコア0.86になります。テーブルの全体ノードはスコアは0.14です。ここまで来れば、バナナとリンゴのスコアはかなり近くなります。テーブルは果物ではなく、食べられるものではないのでスコアは低くなります。この計算方法を使えば、エージェントはより柔軟な判断ができるようになります。次は、サイズの比較をします。発言による形容詞は「大きい」なので、エージェントの記憶にあるリンゴのサイズを比較します。リンゴAのサイズは平均なので、スコアは0.5になります。別の軸で計算すると、リンゴAのスコアを計算することができ、0.81になります。最終的にすべてのターゲットのスコアを計算すると、発言にあるオブジェクトと一番似ているものはリンゴBになることが分かります。そのおかげでリンゴを探すアクションでリンゴBを見つけることができました。するとエージェントはリンゴBの近くに移動して取るアクションをします。デモ映像では、「オレンジのクリップを取れますか」「赤いものに接続できますか」などの音声の指示に従ってKOBUNが適切に動き、成功すると表情にも変化が現れました。ゴティエ)」氏エモーショナルについて次に、エモーショナルコンポーネントについて、各モジュールの説明をしていきます。最初は感情モデルで、短期的な感情を表します。喜び、苦痛など時間の経過とともに急速に変化する特長を持っています。次はムードモジュールで、気分や長期的な感情を表します。時間とともにゆっくりスムーズな変化をするのが特長で、活力的、落ち込んでいる、不安な気分などを表します。感情モジュールとは相互関係にあります。性格モジュールは、エージェントの構成を定義するモジュールで、時間で変化することはありません。好奇心、恥ずかしい、怠惰などで、性格モジュールは感情、ムードと影響しています。感情モジュールまずは感情モジュールを説明します。Model」という感情モデルから着想を得て開発しています。最初に、エージェントにとって、そのイベントの「良し悪し」を判断し、種類によってブランチが分かれます。イベントがオブジェクトの見た目に関することであるとき、例えばリンゴを見たときなど、好き嫌いという感情が発生します。感電が起きるようなイベントのときには「苦痛」と「喜び」の感情が生まれます。イベントがエージェントのアクションであれば、さらに分岐していきます。アクションのときは「称賛・非難」などが生成されます。紹介されたデモ映像では、KOBUNがクリップを持って感電してしまいました。原因は指示側がボタンを押したせいで電気が流れてしまったからです。それを解析しましょう。感電するということは、KOBUNにとって悪い(イヤな)イベントであり、苦痛という感情が生成されました。原因がプレイヤーがボタンを押したことだと分かり、KOBUNはプレイヤーに対して怒りという感情が生成されました。実は、感情を生成するときにもうひとつの感情が流れています。先ほど感電したときに苦痛の感情が生成された後に、クリップが帯電しているという形容詞に対して、ネガティブなアフェクトを追加します。アフェクトは挙動と記憶に残る時間の値を持っています。悪いアフェクトをクリップと帯電の形容詞に与えたので、クリップと帯電しているオブジェクトに出会うと、KOBUNが嫌がって逃げると考えられます。その結果、KOBUNは電気が通っているクリップを嫌いになりました。その後、もう一度「そのクリップを取ってください」と頼むと、どう反応するのでしょうか?一旦はクリップを探すアクションはしますが、ビリビリしているクリップを見つけたKOBUNは提示されたプランを拒否して、その驚異をプレイヤーに表現します。キューブをイメージして開発されており、P(Pleasure=喜び)、A(Arousal=激情)、D(Dominance=怒り)を司り、これは自分の感情のコントロールがどれだけできるか、という値を表します。このキューブの中には、すべての感情が内包されており、8つのエリアに分かれ、中央にはデフォルトムードのポイントが存在します。各エリアにはそれぞれ違った感情が存在しています。感情が生成されると、ムードポイントが時間と共にスムーズに移動していきます。感情は強度と表現時間の値ともに生成され、強度の値が高ければ高いほど、ムードの変化速度が大きくなります。表現時間が経過したら、ムードポイントがゆっくりとデフォルトの位置に戻っていきます。喜びや怒りの感情に関連して、KOBUNが喜んだり、起こったり、表情も変化していきます。気分によってブレンド機能を使い、スムーズなアニメーションが実現できます。性格モジュール最後に性格モジュールになります。これはすごくシンプルなモデルで、怠惰・好奇心などUtilityの値だけとなります。怠惰10%に設定したKOBUNは、指示したクリップをきちんと取りにいきました。怠惰90%に設定すると、遠くにあるクリップまで行くのを面倒と判断し、近くにある指示とは違うクリップを取ってしまいました。横着者な性格になっていますね。そこで、どうやって怠惰の性格を実装したのか、説明しましょう。怠惰の性格は、オブジェクトを探すアクションに影響します。適切にオブジェクトを見つけるゴールでは、ターゲットのスコアを計算しており、その軸の一つに「近さ」があります。働き者のKOBUNの場合、近さの軸の値は0.1とすごく低くなっています。それはあまりスコアに影響しません。近さより大事なことだからです。怠け者のKOBUNの場合は、怠惰の値が高ければ高いほど、近さの軸の重みが変わります。オブジェクトが近ければ近いほど、優先させようとします。その結果、怠け者のKOBUNは色やサイズの軸を無視してしまいます。一般的に性格モジュールは簡単ですが、たくさんのバリエーションが実現でき、性格のパラメータはいろいろな部分に影響させることが可能です。ゴールのスコアに影響する、プランナーのアクションのセット、コスト、好き嫌いや感情の表現やデフォルトのムードにも影響が出ますし、その性格モジュールのおかげでNPCはひとりひとり違っていることを感じることができます。※この記事は2019年5月時点の情報です。GeNOM(ゲノム)とはDeNAのゲームクリエイターを様々な切り口で紹介するメディア(運営:株式会社ディー・エヌ・エー)です。ゲーム開発の現場で生まれる様々なエピソードや、クリエイター紹介、イベント紹介などを通して、DeNAで働くメンバーの”ありのまま”をお伝えしていきます。アカウントにて確認いただけます。RANKING宍倉さん、ぶっちゃけDeNAと組んでどうだった?──『メギド72』開発うら...【DeNAマーケティング部特集vol.1】ROIだけが判断軸ではない。