電通総研 テックブログ

電通総研が運営する技術ブログ

UE5でコリジョン(衝突)判定機能を使って色々な機能を作成してみた

こんにちは、ISID 金融ソリューション事業部の岡崎です。
今回はUE5でコリジョン(衝突)判定機能を使って、自動で開閉するドアや、NPCとの簡単な会話システムを作成してみます。

はじめに

UE5ではフィールド上のさまざまなオブジェクトや、プレイヤーが操作するキャラクターにコリジョン判定機能を持たせることができます。
これにより、物体にキャラクターが当たった時や、前もって設定しておいた領域に他のオブジェクトが侵入した時などに、
任意の機能を作成できます。
今回はこのコリジョン判定機能を利用して下記2つの機能を実装します。

  • キャラクターが近づくと開き、遠ざかると閉じる自動ドアの機能
  • 対象キャラクター(NPC)にプレイヤーが近づき、任意のキーボードを押すと会話が行われる機能

検証環境/ツール

  • Unreal Engine5.2.0
  • AWS EC2
    • Windows_Server-2022-English-Full-Base-2023.01.19

実装手順

  1. 【自動ドア編】タイムラインを利用したドアのアニメーションの作成
  2. 【自動ドア編】コリジョンを利用した自動開閉システムの作成
  3. NPC会話編】会話UI用のウィジェットの作成
  4. NPC会話編】コリジョンを利用した会話UI用のウィジェットの表示
  5. NPC会話編】NPC毎のメッセージ内容切り替え

1. 【自動ドア編】タイムラインを利用したドアのアニメーションの作成

今回はThirdPersonテンプレートを利用したプロジェクトで進めていきます。
まず初めにドアに使用するアクターのBluePrintを作成します。
コンテンツドロワーより、BlueprintClassを選び、Actorを選択します。今回は「BP_Door」という名前にします。

「BP_Door」の編集画面に入ります。

コンポーネント追加ボタンより、「Static Mesh」を追加し、「Door」と命名します。
右側の詳細パネルより、Static Meshのセレクトボックスでスターターコンテンツの「SM_Door」を選びます。

次にドアの当たり判定用にコンポーネント追加ボタンより、「Box Collision」を追加し、ドアの大きさに合わせて変更します。

またキャラクターがドアをすり抜けてしまわないよう、今作った「Box Collision」のあたり判定を設定するコリジョンプリセットの値を「BlockAllDynamic」に変更します。

続いて、作成したドアにアニメーションをつけていきます。
本ステップでは、ドアにアニメーションをつけることが目的なので、わかりやすくするため、
ゲーム開始時に、ドアが開く仕組みを作成します。

「BP_Door」のイベントグラフを開きます。
「イベント BeginPlay」の後に、ドアに動きをつけるためにタイムラインを使用します。
以前のこちらの記事(UE5 x ZBrushでタイムラインを活用したアニメーションを作成する)で、タイムラインについて詳しく説明しているので、今回は割愛します。
「DoorOpenRate」という名前でタイムラインを作成し、さらに「Rate」というトラックを作成し、下記値を追加しました。

  • 秒数0:値0
  • 秒数0.5:値1

イベントグラフに戻ると、返却値として「Rate」を持つタイムラインができているので、「イベント BeginPlay」のピンとつなぎます。

次に「Make Rotator」ノードを作成しZ軸の値を「90」に設定します。これはドアが90度開くための値になります。
「乗算」ノードを追加し、下の写真のように作成したタイムラインとつなぎます。

最後に「Set Relative Rotation(Door)」を選択し、「New Rotation」にタイムラインから乗算した値をつなぎます。

コンパイルし、Map上に「BP_Door」を配置を行い、ゲームを開始することでドアが開くアニメーションを確認できます。

2. 【自動ドア編】コリジョンを利用した自動開閉システムの作成

ここでは、コリジョンを利用して、キャラクターが近づくと自動で開き、離れると自動で閉じるドアにします。
ちなみに先ほどドアに「Box Collision」を使いましたが、これはキャラクターがドアを通り抜けられなくするためのコリジョンのため、
これから作る自動ドアの範囲を示すコリジョンとは別のものになります。

「BP_Door」を開き、「Sphere Collision」を追加します。

次に、「Sphere Collision」をドアの中心へ移動し拡大を行い、キャラクターが入ると自動でドアが開く領域を設定します。

詳細パネルのイベント欄から「On Component Begin Overlap」と「On Component End Overlap」の右のプラスボタンを押します。

イベントグラフに下のようなノードができていることを確認します。

作成された「On Component Begin Overlap」を「イベント BeginPlay」と入れ替えることで、キャラクターがコリジョンで設定した領域に入ることでドアが開く挙動になります。
また、「On Component End Overlap」をタイムラインの「Reverse」ピンに接続することで、タイムラインで設定した値と逆の挙動が行われるので、キャラクターが領域からでた際にドアが閉まります。

以上がキャラクターが近づくと開き、遠ざかると閉じる自動のドアの機能の紹介になります。

3. 【NPC会話編】会話UI用のウィジェットの作成

続いて、対象キャラクター(NPC)にプレイヤーが近づき、任意のキーボードを押すと会話が行われる機能の作成手順を紹介します。
まずは会話UIに使用するウィジェットを作成するために、「Widget Blueprint」を「WBP_Talk」という名前で作成します。
ウィジェットの作成方法は以前のこちらの記事(UE5 PixelStreamingで、マウスカーソルを別の画像に変更してクリックイベントを作成する)で紹介しております。

まずはパレット内の一般から「Border」を「WBP_Talk」内にドラッグ&ドロップし、「Canvas Panel」でラップします。


詳細パネルからアンカーを選び、下に伸びているものを選びます。

「Brush」内の「Tint」の部分にカラーピッカーがあるので「A(アルファ)」の値を「0.5」まで下げて、先ほど作成した「Border」を半透明にします。サイズを下の写真のように大きくして簡易的な会話テキストを置く部分のUIとします。

次にパレット内から「Text」を選び、今作成した「Border」内にドラッグ&ドロップします。
詳細タブの「Padding」から上下左右中央そろえにします。また、「Font」から文字サイズも「36」に変更します。
これで会話UI用のウィジェットが出来ました。


実際に画面に表示させてみます。

スターターコンテンツで初期から入っているキャラクターを使用します。
ファイルは、コンテンツ>ThirdPerson>Blueprints>BP_ThirdPersonCharacter にあります。

まずはこのBlueprintからウィジェットにアクセスできるように設定します。
ウィジェットを作成」ノードを追加し、Class属性にWBP_Talkを設定します。また「Owning Player」には「Get Player Controller」をつなぎます。


次にウィジェットを作成ノードを「イベント BeginPlay」のピンとつなげます。
「WBP_Talk ウィジェットを作成」のノードの「Return Value」を変数としてセットし、「UI_Talk」と命名します。

次に「Q」を押した時にウィジェットを画面に表示させるようにします。
「Add to Viewport(UI_Talk)」を選び、「Q」のノードとつなぎます。

これで実際に画面に会話用のUIを表示することが出来ました。

ここまでで、会話用のUIに必要なウィジェットの準備が整いました。
続いてコリジョンを利用して、プレイヤーが操作しているキャラクターの前に、他のキャラクターがいる時のみ「Q」を押すことで、会話用のUIを出す機能を作成します。

4. 【NPC会話編】コリジョンを利用した会話UI用のウィジェットの表示

まずは「BP_ThirdPersonCharacter」のキャラクターに、先ほどドアを作成した時と同じように「Sphere Collision」を作成します。
キャラクターの前方に下の写真のように「Sphere Collision」を配置します。

イベントグラフに戻り、「Get Overlapping Actors(Sphere)」を作成します。これは先ほど作成した「Sphere Collision」に接触しているアクターの一覧を配列で返してくれるノードになります。
先ほど作成した「Q」を押した後の「ブランチ(IF文)」でfalseだった時に「For Each Loop With Break」ノードで「Sphere Collision」に接触しているアクターの配列を展開します。

本ステップではまだアクターごとに会話の文章の内容を分けず、コリジョン内にアクターがある場合のみ会話用のUIを出すだけの処理なので下の写真のように「Add to Viewport」につなぎ、配列がなくなるまでループさせます。
これで、コリジョン内にアクターが1つでもあれば、「Q」を押すことで会話用のUIを表示できます。

また、このままだと会話用UIが出たままになってしまうので、消去する処理も作成します。
「IsTalk」というBooleanの変数を作成し、会話中ではない時のみ画面に会話用UIが出るように設定します。
また会話中の場合は、画面から会話用UIを消すために「Remove From Parent」ノードを追加し、画面から会話用UIを消去し、「IsTalk」のフラグをfalseに変更します。

実際に試してみるために、マップにいくつかアクターを設置させます。
どんなアクターでも良いですが、今回はNPC風の人型アクターを作成して設置します。

Blueprint作成画面からCharacterを選択して「BP_NPC」を作成します。

コンポーネント一覧よりより、「Mesh」を選択し、詳細パネルよりメッシュを選びます。今回は「SK_Mannequin」を選択します。
マテリアルも任意のものを選び、マップに配置します。

ここまでの実装で、プレイヤーが操作するキャラクターの前にアクターがある時のみ、「Q」を押すことで、会話用のUIが出てくる処理が完成しました。

続いて、マップに配置したNPCごとに会話の内容を変更させる機能を作成し説明します。

5. 【NPC会話編】NPC毎のメッセージ内容切り替え

まずはアクター間を超えて共通の会話用の関数を使用できるようにブループリントインターフェースを作成します。
コンテンツドロワーからブループリントインターフェースを作成し、「BPI_Talk」と命名します。

編集画面で「CanTalk」というBooleanを返す関数と、「GetTalkMessage」というTextを返す関数を作成します。


「BP_NPC」で2つの関数を使用するために、「BP_NPC」を開き画面上部のクラス設定を押し、右側の実装インターフェースのセレクトボックスより「BPI_Talk」を選択します。

左側にインターフェース欄が追加され、先ほど作成した2つの関数があることを確認します。

左側のインターフェース欄から「CanTalk」をダブルクリックで開き、Booleanの返り値をtrueに設定します。

同様に「GetTalkMessage」を開き、リターンノードのTextの返り値を変数としてセットし、「TalkMessage」と命名します。
さらに、変数欄の右側の目のアイコンをクリックして、UEの全体の編集画面から直接変数の値を変更できるように設定しておきます。


最後のステップとして「BP_ThirdPersonCharacter」を開き、前にいるアクター(BP_NPC)が「CanTalk」でtrueを返しているかをチェックし、trueだった場合に「TalkMessage」でセットした文字列を会話用UIに埋め込んで表示させる処理を作成します。

先ほど配列で取得したコリジョン内のアクターをForEachで回している部分で、「CanTalk」がtrueかどうか確認するためにノードを追加します。

trueだった場合に、さらにそのアクターが設定してある会話の内容を「GetTalkMessage」から取得します。
(BP_NPCは全て「CanTalk」をtrueで返す設定をしています。)

「GetTalkMessage」のターゲットはアクターの配列が入っている「Array Element」です。

次に取得してきた会話の内容を「WBP_Talk」の中に埋め込みます。
「WBP_Talk」を開き、階層から「Text」を選択します。次に右上の「is Variable」にチェックを入れ、「Widget_TalkMessage」と命名します。


「WBP_Talk」をグラフ表示に変更して、関数を作成します。今回は「Widget_SetTextMessage」と命名します。
インプットにTextを設定します。

「SetText(Text)」ノードをつなぎ、ターゲットに「Widget_TalkMessage」を設定し、ターゲットに「UI_Talk」をつなぎます。

「BP_ThirdPersonCharacter」に戻り、「Widget_SetTextMessage」ノードを作成し、「GetTalkMessage」とつなぎます。
最後に「Add to Viewport」と繋ぐことでBlueprint側での処理は完了です。


全体の処理は下記のような流れになっています。

UEの編集画面からアクターを選択し、詳細タブの「Talk Massage」欄に任意の文言を追加することで、アクターごとに会話する内容を設定できます。


実際に会話を行ってみます。

以上がコリジョン機能を使って、自動で開閉するドアや、NPCとの簡単な会話システムの作成方法の紹介です。

所感

コリジョンを利用することで、オブジェクトを動かしたり、重なったアクターの情報を取得したりと、さまざまな使い方ができることがわかりました。
また、基本的な会話の作り方もわかったので、より複雑な会話方法や、ウィジェットの作成方法なども学習していきます。
特にウィジェットでできることはまだまだありそうなので、もう少し深ぼって調査していきたいと思います。

現在ISIDはweb3領域のグループ横断組織を立ち上げ、Web3およびメタバース領域のR&Dを行っております(カテゴリー「3DCG」の記事はこちら)。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください!
私たちと同じチームで働いてくれる仲間を、是非お待ちしております!
ISID採用ページ(Web3/メタバース/AI)

参考

執筆:@okazaki.wataru、レビュー:@wakamoto.ryosuke
Shodoで執筆されました