Unreal Engine 5を使ってみる その6(ロボットアーム、ブループリント)
はじめに
今回はUnreal Engine 5(UE5)でロボットアームのようなものを作ってみました。まだ試作段階で、これから厳密なモデルにしていきたいなと考えています。
まだまだUE5について知らないことが大量にあるので、手探り状態です。とりあえずキーボードで操作できるようにはしてみました。
なお今回はWindows環境、UE5.4、ブランクプロジェクトで試しています。
▼新しいプロジェクトとして作成しました。

▼以前の記事はこちら
ActorとPawnの違い
クラスについて
UE5にはブループリントクラスがいろいろあります。全然把握していないので少し調べてみました。
▼このくらいあります。

▼こちらでクラスについて紹介されていました。
https://note.com/ryodist/n/nb694f36e0703
今回はActorとPawnについて検証してみました。今後頻繁に使っていくことになりそうです。
▼Actorのドキュメントはこちら
▼Pawnのドキュメントはこちら
簡単にまとめると以下のようになります。
- Actorは任意のオブジェクト(カメラ、スタティックメッシュ、プレイヤースタート位置など)
- PawnはプレイヤーやAIで操作可能、コントローラとは1対1の関係
実際にブループリントで動かして、違いを見てみます。
ブループリントクラスを作成する
今回はPawnクラスのtestと、Actorクラスのtest_actorを作成しました。
▼コンテンツドロワーを右クリックし、ブループリントクラスを選択します。

▼Pawnとアクタのクラスを作成します。

▼それぞれコンポーネントの追加ボタンから、キューブだけ追加しました。

キューブがActorなのかPawnなのか分かりやすいように、テキストを追加してみました。
▼テキストレンダリングコンポーネントを追加し、テキストと色を設定しました。

▼文字が一緒に回転するように、親子付けしています。


▼Pawnにはカメラも追加しました。


所有(Possess)について
Pawnは操作可能とのことでしたが、所有することでコントローラの入力を受け付けるようになります。
▼PawnはPossessノードが実行されることで所有できます。

▼Actorを所有しようとすると、そもそも互換性がないとして表示されます。

公式ドキュメントに所有に関するサンプルがあったので、試してみました。
▼ThirdPersonCharacterの所有に関するサンプルです。
▼コンテンツフォルダにThirdPersonが無い場合、コンテンツドロワーの「追加」→「機能またはコンテンツパックを追加」から、プロジェクトにコンテンツを追加することができます。


▼ワールドに配置しました。

このThirdPersonCharacterを所有できるように、レベルブループリントでプログラムしました。
▼「レベルブループリントを開く」から編集できます。

▼キーボードの2を押すと、所有できるようにしました。

▼キーボードの入力は、Any Keyノードを追加後、詳細タブでキーを選択できます。

ThirdPersonCharacterのノードは、アウトライナーからドラッグ&ドロップで配置できます。
▼右クリックしても表示されました。

公式ドキュメント通りならこれで動くはずですが、動きませんでした。画面のバージョンが違っていたからかもしれません。
▼所有はできてカメラは移動したのですが、動かせません。

ThirdPersonCharacterのブループリントを見てみました。
▼Event BeginPlayから始まっています。

以前の記事でも同様の状態だったのですが、Event BeginPlayはゲームが始まった時にしか実行されません。そのため、ポーンを所有したときに実行されなかったのだと思われます。
そこで、所有した時点で開始するようにしてみました。
▼ちょうどEvent Possessedがあったので、追加しました。

▼操作できるようになりました!

プレイヤーの入力を受け付ける
ブループリントでActorとPawnを回転させてみます。
ActorはキーボードのYを押したとき、PawnはTを押したときに回転するようにしました。ちなみに、キーが被っている場合、Actorだけ回転してPawnは回転しなかったです。
注意点として、ActorはEnable Inputが無いと回転しません。
▼Enable Inputについては、こちらで紹介されていました。
https://zenn.dev/posita33/books/ue5_starter_cpp_and_bp_001/viewer/chap_02_bp-input_event
回転にはAdd Relative Rotationノードを使いました。
▼Actorのブループリントはこちら。ゲーム開始時にEnable Inputが呼び出されるようになっています。

▼Pawnのブループリントはこちら。Enable Inputが無くても、所有した時点で操作できるようになります。ただし所有するまでは回転しません。

▼実際に回転させたときの様子。
カメラやテキストレンダリングコンポーネントを親子付けしていたので、一緒に回転しています。回転の中心は、キューブの中心になっていますね。
ロボットアームのようなものを作ってみる
コンポーネントの配置
これまでの検証を踏まえて、Pawnクラスでロボットアームのようなものを作ってみました。まずは2軸です。
▼ロボットアームというよりは遮断機みたいですね。

土台部分はシリンダー、アーム部分はキューブを配置しただけの、単純なモデルです。
親子付けを行うことで、土台に近いアームが回転すると、それに付随してもう一つのアームも動きます。
▼親子関係はこのようになっています。

キューブを回転させたときは、その中心が回転中心になっていました。ロボットアームとして制御するうえで、回転軸をどのように設定するのか?が悩みどころでした。
そこで、キューブのような物体はない、回転軸にするためのスタティックメッシュを配置しました。親子関係に含まれていたRotate1とRotate2がそうです。
▼arm2の中心となる位置は、直方体の中心になっています。

▼それに対し、Rotate2は回転軸になるあたりに配置しています。

Rotate2の子としてarm2を配置することで、Rotate2が回転したときにarm2も一緒に回転するようにしています。
また、Rotate1とRotate2は物体がなくて透明なので、分かりやすいようにスタティックメッシュとしてSM_FieldArrowを割り当てています。
▼水色の半透明になっている矢印がそうです。回転したときはこの矢印も回転します。


ブループリントの編集
ブループリントでは、キーボードの入力に合わせて正転、逆転、停止するようにしています。
▼4つのInteger型の変数を用意しました。

arm1Rotate、arm2Rotateはアームの回転状態を保存します。RotateとInverseはそれぞれ1とー1が代入された定数扱いです。値に応じた状態は以下のようになっています。
- 1:正転
- 0:停止
- ー1:逆転
▼マイコンでのモータードライバーの制御を思い出します。2つのピンのHIGHとLOWで制御していたのですが、同じように制御することもできそうですね。
これらの値を、キーボードの入力に合わせて代入します。
▼キーボードを押したときに1やー1、離したときに0を代入するようになっています。

代入した値をもとに判定を行い、回転軸に相対的な回転を与えます。
Branchで分岐して、Rotate/Inverseとarm1Rotate/arm2Rotateの値が一致すると、Add Relative Rotationノードが実行されます。そして、どちらに分岐したとしても次のBranchに繋がるようになっています。
▼フローはこちら。

また、このロボットアームを所有できるように、レベルブループリントにノードを追加しました。
▼キーボードの1を入力すると、Arm1を所有するようになっています。

実際に動かしてみました。
▼キーボードを長押ししている間は回転します。こう見ると砲台っぽいですね。
謎の球体が出てきてしまっているのが気になります...
6軸にしてみる
先程のモデルは2軸でしたが、あと4つ増やして6軸にしてみました。
▼6軸ロボットの構成については、調べるといろいろ出てきました。
https://www.keyence.co.jp/ss/products/vision/fa-robot/industrial_robot/mechanism.jsp
▼キューブだけですが、先程よりもロボットアームっぽくなったような気がします。

ブループリントは2軸のときのものを4つ追加しただけです。回転軸などは変わっています。
▼配列とかで書きたくなりますね。





▼全体像はこちら

▼実際に動かしたときの様子がこちら。ボタンが多いので、操作が難しいです。
▼せめて掴むためのツメが欲しい...

最後に
腕同士が干渉しているので、次はコリジョンを設定したいところですね。
ロボットアームの制御については勉強中なのですが、手先ではなく土台の部分から位置が決まっていくので、順運動学的な制御になっているのかな?と思っています。
今回は親子付けしていたので一緒に動いていましたが、手先だけ任意の位置に動かし、それに合わせて他の間接を動かすというようなことはできなさそうです。親子関係を変更するか、すべてのアームの位置を計算して配置する必要がありそうです。またいろいろ試してみます。
CADのデータを取り込んだときはスタティックメッシュとして取り込まれていました。キューブを置き換えれば、リアルなモデルになるのではないかと考えています。
▼CADデータの取り込みは以前試しました。キーボードの入力を置き換えて、PS4のコントローラで操作できるようにもできそうですね。