【Unreal Engine5】初めてのゲーム開発 <第9回> スイッチボタンをトリガーとした処理

前回まで、StackOBot(SOB) の開発の方によるレクチャー動画で3回にわたって勉強してきました。
おかげで少しずつUE5の理解が深まってきてると思います。

というわけで、今回は自由に色々触ってみようと思います。

今回やること

・StackOBotのアセット(部品)を利用
・プレッシャープレート型のON/OFF処理
・ボタン型インタラクトのON/OFF処理

今回の記事後の実行テスト

一応の目的はあって、ボール型のオブジェクトの挙動をいろいろいじってみようと思っています。


今回は今後いろいろ試しみたいボール型インスタンスのチェック、のためのテスト環境作りの一環。
簡単にボールを生成できるようするアセットの作成です。
いいかげんテストのためにボールを手作業でレベルに配置するのから脱却したい、との思いから作ってみました。

目次

StackOBotの素材を使わせてもらおう

使っていい素材なのか確認

StackOBotのサンプルページによると使用許諾に関する注意書があります。

原文

機械翻訳

とあるので、UEベースのプロジェクトなら素材利用可能だと思いますのでありがたく使わせてもらいましょう。

データ移行

StackBot起動したら、コンテンツブラウザでStackOBotを選択

右クリックメニューから「移行」

アセットレポートはそのままOK

あとは、コピー先に移行したいプロジェクトのContentフォルダを指定するだけです。

無事移行できたら、StackOBotフォルダが作成されて、中のBPやStaticMeshなどを利用できるようになります。
例えばBP_BotもワールドセッティングのDefault Pawn Classを変えるだけで使えるようになります。

MetaSoundで効果音(超初心者版)

超初心者とは筆者のこと(笑)
前回少しだけ触ったMetaSoundをもう少しだけ深掘り。
と言っても初心者がゲームを作るために最低限必要なSEを作れる程度を目指します。
正直適当なこと言ってると思います。

《例》※使ってるノードはごく一部の最低限

Input開始ノード(初期配置)
Output終了ノード(初期配置)
AD Envelope (Audio)音の長さや減衰(余韻)等を調整
Multiply (Audio)音を合成編集
Multiply (Audio by Float)音量調整
Wave Player 1.0wavファイルを取り込む ※今回未使用
1.0(モノラル)以外ノードもある
Sine正弦波の音をジェネレート
Wave Writer 1作成した音をwavファイル出力 ※今回未使用
1.0(モノラル)以外ノードもある
繋げてしまうと再生する度にファイルが出力されてしまう

Outputは左上のMetaSoundの設定キーで出てくる詳細パネルを変更すると自動で変更


大まかな処理の流れ

※原音として入力できるファイルはwavのみ

ジェネレータ種類
正弦波(Sine)
三角波(Triangle)
短形波(Square)
ノコギリ波(Saw)

SuperOscillator
ノイズ(Noise)

デフォルトで使う場合、上のものほどアクがなく、下のものほど耳障りに感じました。
周波数を変化させると音程が変わります。
SuperOscillatorは上4つのtypeのいずれか+α(?)。
ノイズは他とは明らかに異なる音を作り出すことができて、前回のように「物音」系の音を作成するのに使える。

Additive Synth、LFOに関しては一応ジェネレータ扱いですが、他のジェネレータと連携させて使う形?(よくわかりませんでした)。

全体的にNoise以外は電子音なので、例えばスイッチを押したときの「カチッ」とかいう物理系効果音を作るのは難しそう?
最近は効果音をAI作成してくれるようなサービスもあるので、基礎音源をそちらで作ってから、wav playerノードで取り込んでから編集するのが現実的かもしれません。

wavファイル出力

画像ではワイヤ―を繋げていませんが、実行すると作成した音源をwavファイルに出力します。
満足いく音源が出来たらwavファイル化してまとめておくと、他のプロジェクトに流用したりしやすい。

《出力先》
プロジェクト名/Saved/AudioCaptures

プレッシャープレートでON/OFF処理(色変化)

形作り

SMだけ流用させてもらって作りましょう。
初心者用動画でも似たようなことをやっていたのでできるはず。

フレームとボタンのSMを合成してスイッチボタンを作成。
ルート下だと拡大縮小しかできないこともあり、Sceneをルート下において親子付けすることに。

イベントグラフ

前回と比較して追加した処理
・ボタンを押したときに音を鳴らす
・ボタンが押されている時にボタンの色を変える

BP_SwitchBottun

前回の「プラットフォームの設置とON/OFFアニメーション」のコーディングを流用。
追加したノードのみピックアップ

GetActorLocation自身(プレッシャープレートのボタン)の位置
Play Sound at Locationサウンドエフェクトを発生
Greater
Branch
タイムラインが0.8/1以上であればTrue
上記以外はFalse
Set Materialプレッシャープレートのボタンの色を変更

実行結果 ※やや音大き目です、ごめんなさい

問題点
ボタンから離れる時にもOnComponentBeginOverlapが動く場合がある?
ジャンプした時にボタンの音が下がる(減衰が大きい?)

プレッシャープレートでON/OFF処理(ボール生成処理追加)

上で行ったことに、ボールの生成処理を連動させます。

横長になってしまったので2段に分けて(つながってます)
BP_SwitchBottun(前半)

関数に関しては上で記載しているのとほぼ被っているので省略。
音を出す処理を削除しています。

BP_SwitchBottun(後半)

Do Onceプレートの色が赤になった時に1度だけ処理。
白になったら処理可能状態に(Reset)。
GetActorLocation自身(プレッシャープレートのボタン)の位置
Play Sound at Locationサウンドエフェクトを発生
Get Actor Of Classスポーン場所(BP_SpawnPoint)のクラスインスタンスを取得。
複数ある場合はGet all Actors Of Classで配列取得する必要がある。
Get Actor Locationスポーン場所の位置を取得
Spawn Actor from Classボール(BP_Ball)を対象の位置にスポーン。

実行テスト

寸分たがわず同じポイントから落としてるはずなのに、数個で倒れるのは物理演算にも揺らぎがあるということでしょうか。

スイッチパネルでON/OFF処理(ボール生成)

今度はスイッチパネルを使ったボール生成です。
一見似ていますが、プレートと違って、パネルに対してインタラクトすることになるので複雑化します。

【プレッシャープレートのCollisionトリガー】→【ボール生成】
だったのが
【プレイヤーのインタラクトトリガー】→【スイッチパネル】→【ボール生成】
へと変化

簡易フロー

プレッシャーパネルではパネルの状態がトリガーで自己完結していましたが、今回はキー入力がトリガーになっているので、間にイベントディスパッチャーを噛ませてるイメージです。

なので今回は
・キー入力処理を行う BP_ThirdPersonCharacter
・イベントディスパッチャーを管理する BP_InteractionComponent
・ボール生成を行う BP_SwitchStructure

という3つのイベントグラフを編集していきます。

形作り(スイッチパネル)

StackOBot(SOB)のPropを流用して造形していきます。
StackOBotのフォルダからSM_Modules_Pillarを合成してスイッチ台っぽく。

SM_Button_FrameをX軸に90度回転させて大きさを半分(0.5)に。
位置を調整してSM_Modules_Pillarとくっつけます。

レベルに配置すると、これだけでも近づくとボタンを押すことができます

土台であるSM_Button_Frameの向きを変えたので、押されたボタンの凹み等もきちんと回転してくれてます。

ただし、前回は上に乗ることを前提とした挙動(低いBoxCollision)だったのでここまで近づかないと判定してくれません、

なお、BP_BotではCollisionの高さがたりなかったためテンプレートのBP_ThirdPersonCharacterに戻しました。

今回作りたいのは

サンプルゲーム 【Stack O Bot】より

やはりスイッチボタンと言ったらコレ

ボタン表示とEボタンによる起動をしていきます。

どのようになったかというと

Scene:ルート代理
SM_Button_Frame:SOBから流用
SM_Button_Pushable:SOBから流用
SM_Modules_Pillar:SOBから流用
Hint:ウィジェットコンポーネント(後述)
InteractionArea:Sphere Collision
BP_InteractionComponent:D&Dで作成

以下はきちんとした文献調査してないので間違ってる可能性あり
BP_InteractionComponentはコピーである点に注意が必要。
例えば、Aというクラスと、BというクラスでBP_InteractionComponentの内部変数を扱ったケース。
Aから呼び出した
BP_InteractionComponentの関数で内部変数を変更
Bから呼び出した
BP_InteractionComponentの関数で内部変数を表示してもデフォルト値のまま。

いろいろテストやってて思った動作にならない原因がおそらくコレでした…

Hint(ウィジェットコンポーネント)

ボタンに近づいたときに出る「PRESS 【E】」というアレ。

右クリックメニュー
ユーザーインタフェース > ウィジェットブループリント
から作成。

画像とか使って色々デザインに使ったりできるようですが、今回は単純に文字を出すだけ
見様見真似でとりあえず表示できればいい、という感じで作ったので説明は省略。

今回の対象外ということできちんと勉強はしてないので、デザイン面は目をつぶってください(笑)

BP_SwitchStructureのコンポーネントでHintを選択後、詳細パネルのVisibleはFalse(チェックなし)。
プレイヤーが近づいた(InteractionAreaに入った)時だけ表示します。

イベントグラフ(イベントディスパッチャー使用)

BP_InteractionComponent

イベントディスパッチャーが定義されているのはこのクラス

Add Custom EventEnableInteractability
DisableInteractability
StartInteraction
外部からイベントディスパッチャーの更新にコールされるイベント。
Call XXXOninteract
OnToggleInteractability
イベントディスパッチャーの更新
DelayOninteractの更新処理(Eキー)が連続で行われることを防止します。
いくら連打しても0.5秒置きにしかEキーは反応しないということ。
数値に関してはケースバイケースで調整。
これがないと、1回押しただけ何回も処理が走ったりすることもありましたので実は大事。

BP_ThirdPersonCharacter ※インタラクトキー(E)入力部分のみ

Enhanced Action Events IA_Interactインタラクトキー(E)が押された時に動作
Get Overlapping Actors自身がオーバーラップしているアクター(BP_SwitchStructure)を配列で返す。
Get (a copy)Get Overlapping Actorsで取得した配列の番号n(デフォルト0)を取得
Get Component by ClassBP_SwitchStructureのコンポーネント(BP_InteractionComponent)を取得
Start InteractionBP_InteractionComponentのカスタムイベントをコール

キー入力に関しては以前詳しく見たので省略します。

BP_SwitchStructure

少し複雑になっているので、区分けしてみていきます。

開始処理

イベントディスパッチャーのOninteractとOnToggleInteractabilityを監視(正式な表現ではありません)。
Oninteract/OnToggleInteractabilityに変更がある度にEventの処理が発生。

Assign OnInteractOninteractを監視し、更新があった時にOniteract(カスタムイベント)の処理に移る
Press Buttonカスタムイベント
インタラクトキーを押したときの処理(後述)
Assign OnToggleInteractability OnToggleInteractabilityを監視し、更新があった時にOnToggleInteractability (カスタムイベント)の処理に移る
Set VisibilityVisibility(可視性)のパラメータを更新する
更新値はOnToggleInteractabilityの返り値(True/False)
レベルに配置(インスタンス化)されたアクタの個々に別の処理を割り当てたい場合

同じBPで作られたアクタであっても、それぞれ別の動きを実装したい場合があります。
その場合は、今回BP_SwitchStructureで行ったことをレベルブループリントに記述することで実現できます。

ThirdPearsonMap

レベルブループリントから変化させたいインスタンスをD&Dして対象として明示すると

元は同じブループリントでも、特定のインスタンスのみ処理を行うことができる

Press Button(カスタムイベント)

BP_SwitchStructureの近くでEキーを押したときに、スイッチボタンの色を変えて、ボールを生成する処理。
横長なので前半と後半に分けます。
前半はBP_SwitchBottunと近い処理。

前半

関数に関してはBP_SwitchBottunとほぼ同様のため省略。
タイムラインのReverse処理条件を後半の処理(ボール生成)後に。

後半

Do Onceボタンが押される処理が始まったら、ボタンが元の状態に戻るまでは次のボール生成処理は行わない
Play Sound at Location   ボール生成に合わせて音を鳴らす
今のところ、場所はself(BP_SwitchStructure)となっている
Get Actor of Class対象のクラス(BP_SpawnPoint)に適合する最初のアクタを取得する
スポーンポイントの場所を示し、特に処理はなくレベルに配置のみしておきます
Spawn Actor From ClassBP_BallをBP_SpawnPointの位置にスポーンさせます。
BP_Ballは色のMaterialだけ変更した球コンポーネントです
処理は必要ないですが、Simulate Physicsのチェックだけ入れておきます
Delay処理後に少しだけ(0.2)ディレイして、タイムライン(Reverse)へ
これがないとボタンの色が一瞬で戻ってしまう

Hintの表示判定

判定だけであれば内部で行えるが、表示されてる時のみインタラクトキー(E)を受け付けるので、イベントディスパッチャーと連携する必要がある。

On Component Begin Overlap
On Component End Overlap
開始条件。
InteractionAreaの右クリックメニューから追加
Enable Interactability
Disable Interactability
BP_InteractionComponentのカスタムイベントをコール

Hintウィジェットをカメラ方向へ向ける

Get Player Camera Managerカメラ情報取得
Get Camera Locationカメラの座標取得
Get World LocationHintの座標を取得
Find Look at RotationHintからカメラの方向(Z軸のみ)取得
Set World RotationHintの向きをカメラの方向へ回転

Find Look at Rotationさえ知っていれば処理自体は単純。
Event Tickなので、余りに多くに同様の処理をいれると(可視性OFFにしてるとは言え)重くならないかは不安。

最後に

というわけで、今回はテストに使えそうな、アクタのスポーン用のトリガー(プレート型/ボタン型)を作ってみました。

イベントディスパッチャーの理解度は正直まだまだで、使い方は他にもいろいろあると思うので少しずつ慣れていきたい。

そろそろ、記事のストックも尽きましたので更新はゆっくりになります。
Unreal Engine5の初心者記事の需要なんてほとんどないのは分かっていますが、これからもネタがあったら回顧用に書いていきたいと思います。

しばらくゲーム攻略の記事を書いてないんですが、Unreal Engine5の勉強もやれることが増えていって楽しいんですよね。

どうしたものでしょうか。

コメント

コメントする

目次