とあるゲームプログラマの挑戦と敗北の歴史

UE4とプログラミングとmayaとpythonとhtmlとマラソンを中心に情報を発信する元「技術ブログを目指すブログ」から再始動した毎日の日々を発信するブログです。

Udemy Spine の使い方。インポートからアニメーションまで一貫したワークフローの解説 を受講しました

Udemy
Spine の使い方。インポートからアニメーションまで一貫したワークフローの解説
を受講した際のおぼえ書きです。
https://www.udemy.com/course/spine-in-jp/



まずこちらのコースは
Professional版のSpineが必要です、
Essential版では色々機能がつかえず、実際にできることが少ないです。

メッシュ、パス、クリッピング機能等多数の機能が利用できません。
ひざの曲げる方向を逆に指定することもできないです。
そんな、Essential版で学んだことを記述しています。


ボーンの分割)
ボーンを選択→分割ボタンをクリック
で一本のボーンを分割することができます。
f:id:toncrimentan_w:20210808231248p:plain

フィボナッチにチェックをいれるとこのとおり
f:id:toncrimentan_w:20210808231344p:plain


IKコンストレイン
ボーンを二つ選択→IKコンストレインとを選択
作成したい場所をクリックすることで
IKコンストレインを作成することができます。

ポーズを選択することでIKコンストレインを移動することができ、
この通り腕が曲がります。
f:id:toncrimentan_w:20210808231719p:plain


キーフレームの打ち方)
1フレーム目はすべてのボーンを選択して
回転とトランスレートのキーを打つことがオススメです。
(スケール、シアはなくてもよいです。)
f:id:toncrimentan_w:20210808232027p:plain


クリーンアップ機能)
アニメーション選択⇔クリーンアップをクリックすることで
不要なアニメーションを削除することができます。
f:id:toncrimentan_w:20210808232115p:plain


スキン機能)
スキン機能を利用し、色違いキャラをつくることができます。

ツリーからスキンを選択→スキンを作成
で色違いキャラの種類を増やすことができます。
ここでは素材フォルダがcolor2フォルダなので
color2という名前で作っておく必要があります。
f:id:toncrimentan_w:20210808232211p:plain

差し替えたい素材を選択→スキンプレースホルダーを選択
各スキン用にアタッチメントを複製、アタッチメントの名前を変更にチェックをし実行することで
f:id:toncrimentan_w:20210808232533p:plain

無事このように、素材違いのキャラを作ることができました。
f:id:toncrimentan_w:20210808232626p:plain


実際にできたもの。
f:id:toncrimentan_w:20210808232807g:plain


以上、Spine の使い方。インポートからアニメーションまで一貫したワークフローの解説
について学んだ際のおぼえがきになります。
f:id:toncrimentan_w:20210808233140j:plain

UE4:アンリアルクエスト初級編サンプル解析

5月17日から22日の間、
UE4を利用した学習コンテスト、アンリアルクエストが行われました。

https://www.unrealengine.com/ja/blog/unrealquest-01-archives?sessionInvalidated=true


初級編サンプルが公開されたのでそちらを解析したのをまとめました。

https://epicgames.ent.box.com/s/a6usckg3g8h4mh4nkl811nt78wpdf423



いきなりブート画面がこれです。
テンションあがります!
f:id:toncrimentan_w:20210701095647p:plain



ダメージ床)
BP_Spike

f:id:toncrimentan_w:20210701095721p:plain

床のとげのモデルは、おそらくジオメトリで製作したものと思われ、
9つのとげモデルを1メッシュとしていました。

f:id:toncrimentan_w:20210701095747p:plain

ダメージ部分はボックスコリジョンコンポーネントですね、
オーバーラップイベントとしてGetPlayerCharacterでプレイヤーかどうかを判別し
ApplyDamageノードを利用しダメージをあたえている。
ただそれだけの処理のようです。

f:id:toncrimentan_w:20210701095830p:plain


落下床)
BP_FallingFloor

f:id:toncrimentan_w:20210701095956p:plain

コリジョンのワイアーフレームの太さはこちらのLineThicknessで変更できます。
(これはとても利用価値のある有益な情報です!!)

f:id:toncrimentan_w:20210701100024p:plain

ボックスにオーバーラップすると
SetTimerByEventノードを利用し一定時間後、物理を有効にすることで落下させています。

f:id:toncrimentan_w:20210701100110p:plain

落下後レベルをリスタートすることなく、
一定時間後落下床を元の場所にもどし再開する。非常に丁寧な作りになっています。
(しっかりしています)

f:id:toncrimentan_w:20210701100144p:plain



アニメーション付 落下床)
BP_FallingFloor_WithAnim

f:id:toncrimentan_w:20210701100244p:plain


落下床のアニメーションは、
タイムラインか?と思いきやSetTimerByEventを利用した、
一定時間ごとにメッシュの向きをランダムで変化させることにより作成しています。
(なんかアニメーションがカワイイです!)

f:id:toncrimentan_w:20210701100350p:plain



移動床(2点間))
2点の間を補完する移動床です。

f:id:toncrimentan_w:20210703183449p:plain


コンストラクションスクリプト
TimeLineComponentに対して、PlayRateを利用しタイムラインの再生速度を指定しています。
(タイムラインの再生速度指定方法は実は知りませんでした。あるだろうけども)

f:id:toncrimentan_w:20210703184329p:plain


StartPos GoalPos変数に
インスタンス編集可能
・3Dヴィジェットを表示
の指定を行うことで、ビューポート内でマウスで編集可能にしています!
(こんな方法知らなかった!!)

f:id:toncrimentan_w:20210703184555p:plain



移動床(スプライン))
スプラインの上を補完する移動床です。

スプラインコンポーネントをいじることで、
移動ルートを変更することができます。
f:id:toncrimentan_w:20210703184740p:plain

スプラインはGetLocationAtDistanceAlongSplineノードを利用して
スプラインの指定した距離上の座標を取得することができます。
(個人的には、実は2点間移動床の方が新しい発見がありました)

f:id:toncrimentan_w:20210703184931p:plain



ジップライン)
BP_Zipline

f:id:toncrimentan_w:20210703193339p:plain

コンストラクションスクリプトでは
スプラインコンポーネントと開始位置と終了位置に
自動的に接触ボリュームが配置されているようにしています。

f:id:toncrimentan_w:20210703193318p:plain

このように接触ボリュームがアタッチされます

f:id:toncrimentan_w:20210703193626p:plain


さらにコンストラクションスクリプトでは
スプラインコンポーネント上にスプラインメッシュコンポーネントを追加しています。
これは最終的な挙動には変わらないのですが、
ジップライン上にケーブルが貼っているように見た目上指定しています。

f:id:toncrimentan_w:20210705023709p:plain

こんどはこっちの方です。
見た目上のケーブルを作っています。
キングダムハーツスノーボードステージの空中を張ってるやつとかこれなのかなぁ)

f:id:toncrimentan_w:20210704094056p:plain



ターザンロープ)
BP_SwingRope

f:id:toncrimentan_w:20210705010007p:plain

ロープをつかんだ判定。
ロープの持てる部分にボリュームがあるようにはしていません。
※エリア内に入ったら、ロープのつかめる部分が遠かろうがつかめるようになっています
f:id:toncrimentan_w:20210705010216p:plain

そして、Tickでは
ボリュームにオーバーラップしてから、エンドオーバーラップするまでの間
プレイヤーのCharacterMovementに対しAddForceで移動させるようにしています。
f:id:toncrimentan_w:20210705010323p:plain
向きもその移動の方向に合わせています。
f:id:toncrimentan_w:20210705010347p:plain

ではこのケーブルは何なのか?
ターザンロープとはケーブルに捕まるものではないのだろうか?
そう思う人もいるかと思います。
しかしながら、このケーブルはただの飾りです。見た目です。
※ケーブルなしでも透明なターザンロープにつかまりゲームが実現できる。
 そのうえで、見た目としてプレイヤーにつなげているだけのものになります。
f:id:toncrimentan_w:20210705010433p:plain

ボリューム内に入った時にケーブルをプレイヤーに対してアタッチしています。
f:id:toncrimentan_w:20210705010628p:plain

f:id:toncrimentan_w:20210705010653p:plain

そのほかBP_SwingRopeでは、
話した瞬間ふわっと飛ばすとか、こだわりの処理が含まれています。
つまり、無くても動く処理も含まれています。
(なかなかの大作ギミックだ)



ヴィジェットBPの生成)
WBP_InGameHUD
f:id:toncrimentan_w:20210705013012p:plain

スコアなどのヴィジェットBPはどこで生成するべきか?
ゲームモードで生成しても動くし、プレイヤーのBPで生成しても動く、
多くの参考書ではレベルBPで生成しているものも多くあります。

サンプルでは、
「ゲームモードで生成しています」

スコア表示は、ゲームのルールに関数ものなので
ゲームモードのBPで生成する作りにあるのは適切と思います。

f:id:toncrimentan_w:20210705013051p:plain



エネミー)
BP_Enemy
f:id:toncrimentan_w:20210705020410p:plain

まずビヘイビアツリーは使用していません。
ビヘイビアツリーは難しいと思うし、必要なゲームでもないです。
(サンプルが使用していないのだから、今後製作するゲームにおいて、
 ビヘイビアツリーは利用しない。というのも重要な選択肢とおもいました。)

敵の視覚に入った判定、
サンプルではボリュームを利用して、敵に見つかったかどうかを判別しています。
(一般的にはレイトレースを利用する場合もあります)
f:id:toncrimentan_w:20210705020506p:plain

見つかったら、
ルート移動と弾を発射を実行しています。

ルート移動はAIMoveToノードを利用しています。
f:id:toncrimentan_w:20210705020543p:plain

発射した弾に当たったPCは、BP_Playerで
SetAllBodiesSimulatePhysics、SetCollisionEabledノードを利用しラグドール化しています。
また入力の無効化はPlayerControllerのDisableInputノードを利用しています。
f:id:toncrimentan_w:20210705020600p:plain

またエネミーからプレイヤーへの攻撃は
当たったらダメージというもの製作しています。

敵死亡時の処理、
StopMovementを利用し移動を停止
f:id:toncrimentan_w:20210705022016p:plain

死亡演出は少々カワイイ死亡処理を採用しているようで、
頭とボディにわからたエネミーを
物理に任せてバラバラになるようにしてあります。カワイイ
f:id:toncrimentan_w:20210705022704p:plain




ゴール)
BP_Goal

ゴールBPに接触すると、
SetGlobalTimeDilationノードを利用しスロー演出をいれています。カッコイイ
f:id:toncrimentan_w:20210705022342p:plain



ヴィジェット
WBP_Result

BackgroundBlueを利用して
背景をぼかすような処理をしています。
f:id:toncrimentan_w:20210719224429p:plain
実際こんな感じに表示されます。
f:id:toncrimentan_w:20210719224459p:plain



Spacer
7月14日に放送されたアンリアルクエスト解説編中級・上級によると
https://www.youtube.com/watch?v=xxFZraWma68
こんな風にVerticalBoxとHorisontanBoxにSpacerを組み合わせてキレイにレイアウトを作っていた。
f:id:toncrimentan_w:20210719225118p:plain



解説編中級・上級の動画を見ていて初めて知ったのがこちら、
デバッグフィルタを指定することで実行中に変数の中身を見れるということでした。
これはとても有益な情報でした。
f:id:toncrimentan_w:20210719225313p:plainf:id:toncrimentan_w:20210719225316p:plain





工事中

UE5:オンラインラーニング(Unreal Engine 5 へのアップグレード)

UE5オンラインラーニング
Unreal Engine 5 へのアップグレード
を受講した際のおぼえ書きです。

https://learn.unrealengine.com/course/3754785



UE4プロジェクトのUE5早期アクセスプロジェクトへの移行方法)

UE5の起動ボタンから、UE5早期アクセスをクリックします。
f:id:toncrimentan_w:20210531212248p:plain

UpgradeしたいUE4プロジェクトを選択し開く
f:id:toncrimentan_w:20210531212407p:plain

これで簡単にUE5プロジェクトへ移行できてしまいます。
f:id:toncrimentan_w:20210531212441p:plain




UE5変更点)

メインツールバーが小さくなりました。
これは何気にうれしいです。
いままでプレイボタンが右端にいっちゃってクリックしづらかった。
f:id:toncrimentan_w:20210531212544p:plain

ボトムバーができました。
こちらもうれしい、
画面が大きく使えます。
f:id:toncrimentan_w:20210531213059p:plain

アクターパネルの出し方。
作成 > アクターパネルを配置
でいつものアクターパネルを常に表示することができます。
f:id:toncrimentan_w:20210531213609p:plain

アクターパネルを常に出さないで利用できるようになりました。
画面を大きくりようできますね。
f:id:toncrimentan_w:20210531214014p:plain

ワールドセッティング、プロジェクト設定はこちらから
設定>ワールドセッティング
設定>プロジェクト設定
f:id:toncrimentan_w:20210531214121p:plain

コンテンツブラウザのフィルタ指定
このハンバーガーメニューっぽいのをクリックすることでフィルタ指定できます。
ハンバーガーメニューではないっ)
f:id:toncrimentan_w:20210531214256p:plain



新しいサウンドシステム)

新しいサウンドシステム、メタサウンドシステムは
プラグインからMetaSoundを検索し有効にすることで利用できます。
f:id:toncrimentan_w:20210531214618p:plain

メタサウンドの作り方はこちら
f:id:toncrimentan_w:20210531214810p:plain



ドキュメント)
ドキュメントはこちら
https://docs.unrealengine.com/5.0/ja/



UE5では色々パネルまわりがすっきりした印象を受けました。
いつも利用している、あのパネルはどうやって出すかを理解できるコースです。

UE4:オンラインラーニング(インディーズ フィルム制作での Unreal Engine)

UE4オンラインラーニング
インディーズ フィルム制作での Unreal Engine
を受講した際のおぼえ書きです。

https://learn.unrealengine.com/course/3748536


シーケンサのに関して)

カットごとのトラックに追加方法
+トラック>ショットトラック
をクリックすることで、カットを編集するトラックを追加することができます。
f:id:toncrimentan_w:20210421093947p:plain



カメラの追加
カメラアイコンをクリックすることで、
カットごとのカメラアクタを追加することができます。
f:id:toncrimentan_w:20210421094203p:plain



コンポーネントのトラックの追加方法
ここにDroneLaserコンポーネントを持つBPがあったとします。
f:id:toncrimentan_w:20210421094452p:plain
シーケンサにアクタを追加した際、デフォルトでTransformトラックのみ生成されており。
DroneLaserコンポーネントは出現していません。
でも大丈夫です。
+トラック>DroneLaser をクリックすることで
そのクラスBPがもつコンポーネントをトラックに追加することができます。
f:id:toncrimentan_w:20210421094620p:plain



パーティクルトグルトラックの追加方法
DroneLaserトラックの
+トラックをクリックすることで
f:id:toncrimentan_w:20210421094829p:plain
パーティクルトグルトラックを追加することができます。
f:id:toncrimentan_w:20210421094901p:plain
このような形でパーティクルのアクティベートをきりかえることができます。
f:id:toncrimentan_w:20210421094929p:plain



カットの分割
右クリック>編集>分割
をクリックすることでカットを分割できます。
f:id:toncrimentan_w:20210421095231p:plain



フレームレートの「!」表示
フレームレートが関連するカットと指定が違う場合、
注意表示がでてくれます。
f:id:toncrimentan_w:20210421095259p:plain



ポストエフェクトのオススメパラメータ)


ボリュームの効果範囲指定
ご存じ、InfiniteExtentで距離制限なく、
ポストエフェクトを適応することができます。
f:id:toncrimentan_w:20210421095417p:plain



レンズ>Bloom
強度:4.1
しきい値:-1.0
マジックアワーっぽくできます
f:id:toncrimentan_w:20210421095622p:plain


レンズ>Exposure
露出補正で露出を指定できます
f:id:toncrimentan_w:20210421095713p:plain


レンズ>ChromaticAberration
フリッジエフェクト
f:id:toncrimentan_w:20210421095823p:plain


レンズ>LensFlares
強度でレンズフレアを指定できます。
f:id:toncrimentan_w:20210421095908p:plain


レンズ>ImageEffect
グレイン強度
でノイズをいれることができます。
f:id:toncrimentan_w:20210421095950p:plain



カラーグレーディング>WhiteBalance
温度、色合いでホワイトバランスを指定できます。
f:id:toncrimentan_w:20210421100030p:plain



カラーグレーディング>Global
彩度
f:id:toncrimentan_w:20210421100143p:plain
コントラスト
f:id:toncrimentan_w:20210421100159p:plain
ガンマ補正
f:id:toncrimentan_w:20210421100213p:plain



レンダリング機能>GlobalIllumination
こちらはスタティックライトを利用しているときに効果を発揮するパラメータです。
f:id:toncrimentan_w:20210421100241p:plain



フォントの追加方法
・フォントを適当なサイトから取得し(ttfファイル)解凍する
 例:https://fontfree.me/
f:id:toncrimentan_w:20210422091204p:plain
f:id:toncrimentan_w:20210422091352p:plain
・コンテンツブラウザから右クリック→インポート
f:id:toncrimentan_w:20210422091540p:plain
・無事インポートが成功する
f:id:toncrimentan_w:20210422091601p:plain
・ヴィジェットBPを開き
 テキストなどのコントロールの詳細
 アピアランス>Fontでフォントを変更できる。
f:id:toncrimentan_w:20210422091734p:plain



PLANEでシーンに文字を配置するメリット
ヴィジェットBPで画面上に文字を配置することもできますが、
PLANEで直接配置するのも一つの手です。
・ポストエフェクトなどが反映されること(ブルームなど)
シーケンサで透明度を変更したりすることができること
が理由です。
f:id:toncrimentan_w:20210422091853p:plain



ムービー再生中に、すこしカメラの向きを変えられるテクニック
リアルタイムにレンダリングされているムービーのため、
あらかじめ決められたカメラの向きから少し変更することができます。
(たしか、昔メタルギアとかZOEとかでみたかもしれません)

シーケンサを再生したときに変数として覚えておく
f:id:toncrimentan_w:20210422094452p:plain
・入力があった時に
 GetActiveCameraComponentノードを利用し取得し
 AddRelativeRotationでカメラを回すことができます。
f:id:toncrimentan_w:20210422094514p:plain
・無事シーケンサ再生中にカメラを回すことができるようになる
f:id:toncrimentan_w:20210422094526p:plain
これで没頭感のあるコンテンツがつくれるかもしれませんね!



シーケンサのループ再生
OnFinishedにカスタムイベントをバインドすることで
ループ再生を実現できます。
f:id:toncrimentan_w:20210422095957p:plain



ラーニングを受けるためだけに、
ものすごく重たいアセットのダウンロードを要するのが非常に手間でした。
後半の外部フォントの導入手順、シーケンサのループ再生、
イベント中にカメラ向きのみ動かくテクニックについては有益な情報でした。
導入に時間がかかった割に学びは少ない印象でした。

UE4:一番手っ取り早いエンジンソースコードの取得方法

僕なりに試行錯誤して、
最短でエンジンソースコードを手に入れる方法を見つけたため、
そのメモ書きです。

※正確な取得方法やPerforceを利用し,
 指定バージョンのソースコードにアクセスする方法ではないです

僕なりの試行錯誤手順を明記してあります。



まずは参考にしたお世話になってるヒストリア様のサイト
https://historia.co.jp/archives/231/
こちらも参考にしました。



手順)
・UnrealEngineアカウントとGitHubアカウントの紐づけ
 https://www.epicgames.com/account/connections
 へアクセスし、
 接続>アカウント>GITHUBをクリック
 UEとGitHubを紐づけます。
f:id:toncrimentan_w:20210406235752p:plain

 そして登録したメアドにメールが送られてくるので
 Joinのリンクから進めると、
 UnrealEngineのエンジンソースコードにアクセスできるようになります。
 うまくいくとメールが送られてきます。



・Web上からソースコードを取得する
 https://github.com/EpicGames/UnrealEngineへアクセスし
 Code>DownloadZIPをクリックし取得します。
 (紹介するのは一番手っ取り早い方法です。)
f:id:toncrimentan_w:20210406230513p:plain



・ファイルの解凍
 ダウンロードしたUnrealEngine-release.zipを解凍します。
 これには超時間がかかります。
f:id:toncrimentan_w:20210406230538p:plain



・短いパスの場所へ移動
 次の工程(Setup.batを実行)の際に
 デスクトップで展開するとパスが長くてエラーが出てしまうので、
 短いパスの場所へ移動しておきます。
f:id:toncrimentan_w:20210406231120p:plain



・Setup.batの実行
 Setup.batを実行し完了するまで待つ
f:id:toncrimentan_w:20210406231058p:plain



・GenerateProjectFiles.batの実行
 ここで会社などでUE4を利用している方にはおなじみの
 GenerateProjectFiles.batを実行します。

 でもどういうことかエラーが出てしまいます!!
 でも大丈夫!これはエラーログに従えば解決できます。 
f:id:toncrimentan_w:20210406231020p:plain

 言われた通り
 https://aka.ms/msbuild/developerpacks へアクセス
 (自動的に
  https://docs.microsoft.com/ja-jp/dotnet/framework/install/guide-for-developers
  にリダイレクトされるので)
 ログに従い.net Framework 4.6.2 のリンクをクリックするとー
f:id:toncrimentan_w:20210406231242p:plain

 net framework4.6.2 のダウンロードサイトに移動します。
 (https://dotnet.microsoft.com/download/dotnet-framework/net462

 DeveloperPackをクリックし
 .net framework4.6.2 のDeveloperPackを取得しインストールすれば解決しました。
f:id:toncrimentan_w:20210406231304p:plain



・再びGenerateProjectFiles.batにチャレンジ
 再度GenerateProjectFiles.batを実行すると
 無事UE4.slnのソリューションファイルを作成することができました。
f:id:toncrimentan_w:20210406231407p:plain



UE4のビルド
 ビルドにはかなり時間がかかります。
 実行するとエディタが起動します。
 ※この段階でフォルダ容量が100GBを超えます。
  容量が足りないとビルドが通りません。
f:id:toncrimentan_w:20210406231539p:plain



・プロジェクトの作成
 指定したパスにプロジェクトを作成します。
f:id:toncrimentan_w:20210406231637p:plain

 プロジェクトができました。
f:id:toncrimentan_w:20210406231743p:plain


・プロジェクトのVisualStudioプロジェクトの作成
 メニューバー>ファイル>新規C++クラス
 を選択し何でもいいからクラスをつくることで
 2つ目のVisualStudio(プロジェクトのVisualStudioプロジェクト)
 を作ります。
 ※そして後で無駄に作ったクラスは消しましょう。
  少々変な手順ですが、

 詳細は
 https://learn.unrealengine.com/course/3548019
 の動画を参照のこと
f:id:toncrimentan_w:20210406232021p:plain

 無事プロジェクトができました。
f:id:toncrimentan_w:20210406232253p:plain



・プロジェクトのVisualStudioプロジェクトのビルド
 2つ目のVisualStudioプロジェクトをビルドするとー
f:id:toncrimentan_w:20210406232429p:plain
 プロジェクトのソースコードも含んだエディタが起動します。
f:id:toncrimentan_w:20210406232457p:plain



手っ取り早いとはいえ長かった・・
手っ取り早いには違いないがSSD容量がものすごく圧迫された。

UE4:第15回UE4ぷちコンに応募しました。

今回もヒストリア様で行われている
UE4ぷちコンに応募しました!
https://historia.co.jp/ue4petitcon15


タイトルは
「戦え!ボンバーマンvsエアーマン」です。
f:id:toncrimentan_w:20210405083009p:plain


さっそくですができたものはこちら
youtu.be


テーマは"かわる"ということなので
自身を"気体"に変化できるという無敵能力を持った主人公による
潜入ステルスアクションゲームを開発しました。


かわる。なので最初は
変身スーパーヒーローもので!とか思っていましたが・・


変身するにはしますが、細かく変身と解除を繰り返して
ミッションをクリアする作品を制作しました。



ルームBP)
ダンジョンをつくるのが面倒だったのでー
ドロップし、拡縮するだけで自動で壁と床が生成できる部屋BPを作成しました。
f:id:toncrimentan_w:20210405083911p:plain


やってることとしては、コンストラクションスクリプト
メッシュコンポーネントを追加し編集の段階で壁や床を作るようにしています。
f:id:toncrimentan_w:20210405084117p:plain

StaticMeshComponentを追加ノードを利用して編集毎に追加しています。
f:id:toncrimentan_w:20210405084207p:plain
はたしてUE4では、
こういったコンストラクションスクリプトの使い方で正しいのか?
というとそこは不明。使えるには使えます。
※ライティングのビルドまわりがうまく機能していないかもしれないです。
 これはちょっと調べたほうがが良いかもです。



ワープBP)
ワープコリジョンの位置調整に関してはスプラインコンポーネントの始点と終点に
自動でコリジョン位置が調整されるBPを配置することで対処しました。
(これもコンストラクションスクリプトで行っています)
f:id:toncrimentan_w:20210405085023p:plain



ドロップしてスプラインを編集するとこんな感じ。
(スプラインの編集方法はAltを押しながらエディットポイントを
 調整することで自由にカーブをつくれます)
f:id:toncrimentan_w:20210405085103p:plain



非破壊メッシュ)
オブジェクトの破壊に関しては以前書いた
非破壊メッシュのやりかたのおぼえ書きを参照のこと
UE4:非破壊メッシュのやりかた - とあるゲームプログラマの挑戦と敗北の歴史
f:id:toncrimentan_w:20210405085325p:plain



演出過多)
あまりにもテーマ感が薄かったので
テーマに沿ってる感をわかるよーにしました。
変身UIを表示、変身時カメラが寄るように修正。などなど
f:id:toncrimentan_w:20210405085543p:plain



マテリアル)
変身時に固体から気体に対して徐々に変化するマテリアルをつくり
それをフィーチャーした作品にするよていでしたが。
どうせ一瞬だったりするので、残念ながら小さくに収まっている作品になっています。
それにいちいち長い変身演出見せられても飛ばしたくなる。というのもあり
f:id:toncrimentan_w:20210405090316p:plain
f:id:toncrimentan_w:20210405090023p:plain



レベルデザイン
レベルデザインへの挑戦、
マップ設計のようなところが、製作中とてもおもしろかったです。
ダクト、ターゲット、エネミー、ダメージ床、自動発砲装置といった
多様なギミックがうまい具合にかみ合っている仕様でないと、
ゲームとして面白くならないので、ルールづくりみたいなところは結構大事でした。


うーん、ここは気体にならないとダメージを受けてしまうマップ設計)
f:id:toncrimentan_w:20210405091630p:plain


自動発砲装置にダメージ床でエネミーも・・でもその先にダクトがあるぞ!なマップ設計)
f:id:toncrimentan_w:20210405091829p:plain


ルートによっては敵との戦闘を回避できるマップ設計)
f:id:toncrimentan_w:20210405090729p:plain
そして安全なエリアからターゲットを破壊!
f:id:toncrimentan_w:20210405092112p:plain


ダクトに入ったが最後、ダメージ床なマップ設計)
※これがやりたいためにダクトを通った後は強制変身OFFルールにしました。
f:id:toncrimentan_w:20210405091408p:plain


ダメージ床怖いけど、勇気を出して飛び込めば先に進めるのでは・・なマップ設計)
f:id:toncrimentan_w:20210405092258p:plain



いろいろつくったけど、基本的には俯瞰からのカメラ映像なので、
コンパクトにまとまっちゃってる感はある作品だと思います。

PCがカメラに寄っても問題ないゲームデザインであれば
もうちょっとダイナミックな絵ができたかもしれないですね。
なかなかレベルデザイン業務が楽しい開発でした。

二次創作系のネーミングなのでNGっていわれたら、
しれっとタイトルは変えましょう。(内容ちがうし)

開発中はエアーマンが倒せないのBGMが頭の中で流れていました!

UE4:非破壊メッシュのやりかた

非破壊メッシュにかんする
ApexDestructionプラグインを利用した
UE4標準の破壊表現のやり方のおぼえ書きです。

f:id:toncrimentan_w:20210311004309p:plain



プラグインの有効化
Apex Destructionプラグインを有効にし再起動します
f:id:toncrimentan_w:20210311001634p:plain



非破壊メッシュの作成
・破壊したいメッシュを右クリック
・非破壊メッシュを作成をクリックする
 (図ではSM_TableRoundを破壊する想定です)
・非破壊メッシュウィンドウが表示される
・フラクチャメッシュをクリックし割っておく。
メッシュが細かいと時間がかかります。
f:id:toncrimentan_w:20210311001857p:plain
・無事スタティックメッシュと同じフォルダにできています。
f:id:toncrimentan_w:20210311002006p:plain



壊れるアクターBPの作成
・コンテンツブラウザを右クリックし、ブループリントクラスを選択
・Actorのクラスを選択、
・壊す用のアクター(BP_Actor)を作成する
f:id:toncrimentan_w:20210311002133p:plain



壊れる前のスタティックメッシュの追加
作成したBP(BP_Actor)を開き
コンポーネントを追加を選択
・StaticMeshコンポーネントを追加
・スタティックメッシュに壊す前のメッシュ(SM_TableRound)を指定
f:id:toncrimentan_w:20210311002648p:plain



イベントグラフの作成
(図は一定時間後破壊する例)
・DestroyComponentノードで現在のStaticMeshコンポーネントを削除
・Add Componentと入力すると出てくる
 クラスごとにコンポーネントを追加ノード を作成する
・Classピンに DestructableComponent を指定し
 DestructableComponentを追加ノード に変化させる
・SetDistructibleMeshノードを作成し
 NewMeshピンには先ほど作成した非破壊メッシュ(SM_TableRound_DM)を指定
・ApplyDamageノードで一発ダメージを与えて壊すようにする
f:id:toncrimentan_w:20210311003353p:plain



レベルに配置しプレイすると
一定時間後ごらんのとおり破壊されます。
f:id:toncrimentan_w:20210311003433p:plain



おしまい。

UE4:オンラインラーニング(ブループリントによるツインスティック シューター)

UE4オンラインラーニング
ブループリントによるツインスティック シューター
を受講した際のおぼえ書きです。

https://learn.unrealengine.com/course/2855684


スカイライトのキューブマップ指定
・ライトの SourceType を SLSSpecifiedCubemap に変更
・一例として Cubemap を HDRI_Epic_Courtyard_Daylight に変更
するとキューブマップを指定することできます。
f:id:toncrimentan_w:20210309183442p:plain
ちなみにキューブマップを開くと
こんな風なepic本社だったりします。
f:id:toncrimentan_w:20210309183522p:plain



動的にシーンの輝度調整を無効にする方法
・ポストプロセスボリュームを配置
・レンズ>Exposure の
 最小輝度、最大輝度を1.0にすることにより
シーンの明るさが動的でないようにできます。
f:id:toncrimentan_w:20210309183736p:plain



このコースでは Actor Pawn Character のに関して解説がなされており。
利用された図が非常にわかりやすいです。
Actor      - ワールド配置物
 + Pawn    - 操作可能なもの
  + Character - 歩行可能なもの、MovementComponentを持っています。
Component   - Actorの部品
Controller    - PlayerController AIController があり Pawnクラスが持っています
GemeMode   - ゲームのルールです。
f:id:toncrimentan_w:20210309183905p:plain
※動画からパクった図



親クラスの変数の表示方法
・目のマークをクリックし
・継承した変数を表示にチェックを入れることで
親クラス(コースではBaseCharacter)の変数を表示することができます。
f:id:toncrimentan_w:20210309184445p:plain



SpringArmコンポーネント
SpringArmコンポーネントはカメラを子階層に追加することで、
カメラまでの相対的な距離を指定するコンポーネントです。
・DoCollisionTestのチェックを外すことでコリジョンテストを無効にできます。
・InheritPitch Yaw Roll のチェックを外すことで回転を無効にできます。
f:id:toncrimentan_w:20210309184707p:plain
使用例として、こんな感じに親子階層を作って利用します。
f:id:toncrimentan_w:20210309185052p:plain



ProjectileMovementコンポーネント
アクターを発射物としてあつかうための専用コンポーネントです。
IntialSpeedに速度を入力することができます。
こういった簡単な処理は、ついつい自前で製作してしまいそうになりますが、
すでに出来上がっているものがあるのでこちらを利用しましょう。

f:id:toncrimentan_w:20210309185449p:plain



タグ付けにる判別
プレイヤーが銃などを利用し攻撃した時の
発射物が接触したものがエネミーなのかどうかを判別することがあります。
その際、方法のひとつとして ActorTag を利用し判別することができます。

設定方法)
・クラスのデフォルトを選択
・Tagにタグ名を記述(ここではfriendlyとしています。)
f:id:toncrimentan_w:20210309190048p:plain

判別方法)
・ActorHasTagノードを利用することで
 接触物のアクタータグを判別することができます。
f:id:toncrimentan_w:20210309190103p:plain



プレイヤーの死亡と再生成の仕方
事前にGameModeクラスに
新しいプレイヤーの生成処理 & 操作キャラのバトンタッチ処理
を作っておく必要があります。
バトンタッチは Possessノードを利用します。

そしてPlayerクラスでは死亡した際に
GameModeクラスに制作した 再生成&バトンタッチ処理 を呼び出すようにし、
自身をDestroyすることでプレイヤーの死亡とリスポーン処理を実現できます。
f:id:toncrimentan_w:20210309190557p:plain
※ここで重要なのはゲームのルールに関する処理は
 GameMode に書くべきということです。
 こういった処理はついついレベルBPに書いてしまいがちです。
 実際、私はそうしてしまっていることがよくありました。
 本コースではGameModeに実装する方向で解説されています。
 (エネミー生成のトリガー処理などもGameModeに書くべきです。)



ボックスボリューム内のランダムな座標の取得方法
画像のようにRandomPointInBoundingBoxノードを利用すると
ボリューム内のランダムな位置を楽に取得することができます。
f:id:toncrimentan_w:20210309191330p:plain



アクターを一定時間後破棄する方法
発射物を一定時間後に自動削除したい場合などに利用します。
・クラスのデフォルトを選択
・アクタ>InitalLifeSpawn
 に書きされるまでの時間を指定することで自動的に破棄することができます。
簡単な処理なので意外と自分で作ってしまいそうなところですが、
こういった機能は最初から存在するため利用した方がよいです。
f:id:toncrimentan_w:20210309191440p:plain



ブレンドスペース
ブレンドペースは複数のアニメーションを
値に応じてブレンドする機能です。

軸の設定方法)
アセット詳細タブの
水平軸の Name Minimum Maximum の値
垂直軸の Name Minimum Maximum の値
をそれぞれ入力することで
ブレンドする際のグラフの軸を指定することができます。
f:id:toncrimentan_w:20210310005415p:plain

グラフの設定方法)
あとはアセットタブから
グラフ上のポイントごとのモーションを配置していきます。
f:id:toncrimentan_w:20210310005526p:plain




移動方向とキャラの向きの差分の取り方
・GetVerocityノードを取得しRotationFromXVectorで移動向きを取得
・GetControlRotationからポーン自身の向きを取得
・Deltaノードを利用
 すると2角度間の差分を取得することができます。
GetControlRotationで自身の向きを取得できるのは発見でした。
f:id:toncrimentan_w:20210310010044p:plain



複数の死亡モーションからランダムなものを再生
整数値でのブレンドポーズノードを利用すれば
アニメーションBPで複数のモーションから
ランダムなものを一つ再生することができます。
f:id:toncrimentan_w:20210310010149p:plain
※ピンが足りないときは
右クリック>ブレンドピンを追加
でピンを増やすことができます。



ソケットの追加方法
ケルトンに対し、武器などをアタッチする際の追加ポイントを
をソケットといい、自由に追加することができます。
・アニメーションシーケンスを開く
・スケルトンタブを選択し
・適当なボーンを右クリック
・ソケットを追加を選択
するとアタッチポイントを追加することができます。
f:id:toncrimentan_w:20210310011517p:plain


プレビューアセットの指定
さらにデバッグで武器をアタッチさせ確認することができます。
装備中のイメージを確認しやすいので
もしイメージと違ったら、ソケット位置を調整することができます。
・ソケット右クリック
・プレビューアセットを追加を選択
・確認したいアセットをリストから選択する
f:id:toncrimentan_w:20210310011534p:plain
イメージとちがったらソケット位置を調整しましょう
f:id:toncrimentan_w:20210310011556p:plain


プレビューして問題ないようなら
ゲーム中ではAttachActorToComponentノードを利用しアタッチします。
f:id:toncrimentan_w:20210310011704p:plain



アニメーションBPの子ブループリント
アニメーションBPを全キャラ分、
たとえば、人型、剣士人型、武道家人型、魔法使い人型と
共通する部分もあるのに、全部作らなくてはならないのかというと
そうではなく、
アニメーションBPも子ブループリントを作ることができ、
違う部分をオーバーライドすることで量産することができます。

・子ブループリントをひらく
・アニメーションBPを右クリック
・子ブループリントクラスをを作成を選択
でキャラのABPをもとにした
エネミーのABPを作成することができます。
f:id:toncrimentan_w:20210310013039p:plain

・子ブループリントをひらく
・アセットオーバーライドタブを選択
・差分になる部分の上書き値を設定
この手順で子ブループリントの差分の部分を指定できます。
※この機能は正直しりませんでした。
 てっきり全部根性で作るのかと思っていました。

f:id:toncrimentan_w:20210310013057p:plain



入力を無効化する方法
方法はいくつかありますが、このコースでは
プレイヤーはDisableInputノードを利用し入力を無効化し
エネミーはDetachFromControllerPendingDestroyノードを利用し
コントローラを破棄することで移動を無効化しています。

プレイヤー操作無効化)
f:id:toncrimentan_w:20210310013539p:plain
エネミーの移動無効化)
f:id:toncrimentan_w:20210310013602p:plain



フィル指定
ヴィジェットBPのフィル指定にチェックをいれると
のこる領域を埋め尽くすように配置できます。
f:id:toncrimentan_w:20210310120502p:plain



パッケージTIPS
プロジェクト設定>パッケージ化>圧縮およびクック済みのパッケージを作成
にチェックを入れることでファイルサイズが小さくなります。
プロジェクト設定>パッケージ化>パッケージ化されたビルドに含めるマップのリスト
にパッケージ対象のレベル一覧を作成することができます。
f:id:toncrimentan_w:20210310120643p:plain
f:id:toncrimentan_w:20210310120656p:plain
パッケージは周知のとおり
メニューバーのファイル>プロジェクトをパッケージ化
から作成します。
f:id:toncrimentan_w:20210310121005p:plain



出来たやつ)
youtu.be



このコースでは空のレベルから作成し
最速でシンプルなシューターゲームを作るまでの手順を解説しています。
内容は幅広くC++についての解説も入っているほどです。
講師のテンションが高いです!!

自動輝度調整の無効化、アクタとポーンの関連性、タグ付けにる判別、
ProjectileMovement、操作キャラの変更、ブレンドスペース、アタッチ、
アニメーションBPの子BPの作り方、入力の無効化、ヴィジェットBP
など非常に幅広く学ぶことができます。

ゲームのルールをレベルBPではなくゲームモードに実装しているところは
これまでの私が作ってきた部分を見直す重要な情報と思えました。
またアニメーションBPを継承して使用する方法など
あたしい発見もありました。

UE4:オンラインラーニング(シネマティックショット制作のためのシーケンサートレーニング)

UE4オンラインラーニング
シネマティックショット制作のためのシーケンサーレーニン
を受講した際のおぼえ書きです。

https://learn.unrealengine.com/course/2573344




焦点面をデバッグで表示
カメラデバッグ焦点面の描画にチェックをいれることで
焦点面をデバッグで表示することができます。
f:id:toncrimentan_w:20210308192250p:plain



そのカットのみの一時的なカメラ生成
シーケンサのカメラマークをクリックすると
そのカットのみスポーンされる
一時的なアクタを生成することができます。
f:id:toncrimentan_w:20210308192556p:plain



カメラカットの選択方法
カメラカットの+マークをクリック、
新しいバインディングから
有効なカットを追加することができます。
f:id:toncrimentan_w:20210308192630p:plain



シーケンサを利用した
カットシーンの作り方について学べるコースでしたが、
あまり有益と思える情報はなかったです。

UE4:ImGui導入手順

デバッグ用GUI(ImGui)の導入手順に関するメモです。
ImGuiを導入するとUE4でデバッグ用のウィンドウが楽につくることができます。



とはいっても・・
おかずさんのブログを参考に(いやむしろ8割ぐらいコピって)
自前で試して学習した内容なので正確な情報はそちらを見ましょう。
なんならコードそのまま。

pafuhana1213.hatenablog.com



GuiTestのプロジェクトを作成します。
C++で作成、ここでは例としてプロジェクト名をGuiTestとしています。
f:id:toncrimentan_w:20210308144939p:plain



ImGuiのソースコードはこちらから取得してきます。
Code>DownloadZIPで取得
https://github.com/segross/UnrealImGui
f:id:toncrimentan_w:20210308145156p:plain



落としてきたファイルはプロジェクトのあるフォルダに
GuiTest\Plugins\ImGui とフォルダを作成し、
そこに落としてきたファイルをすべて入れます。
f:id:toncrimentan_w:20210308145456p:plain



いつも通りファイルが追加されたら
GenerateVisualStudioProjectFilesを実行しVisualStudioプロジェクトを更新します。
f:id:toncrimentan_w:20210308145534p:plain



VisualStudioプロジェクトを起動すると
無事ソースが組み込まれていることを確認できます。
f:id:toncrimentan_w:20210308145703p:plain



無事ビルドが通るはずなので実行し、
ImGuiプラグインが有効になっていることを確認します。
f:id:toncrimentan_w:20210308145849p:plain



プレイし ImGui.ToggleDemo を実行することで
ウィンドウを出すことができた。
f:id:toncrimentan_w:20210308145944p:plain



デフォルトでマウスが効かないようになっているので
ImGui.ToggleInput を実行することでマウスがきくようになります。
f:id:toncrimentan_w:20210308150045p:plain



いちいちImGui.ToggleInputするのが面倒くさいときの対処手順
・プロジェクト設定を開く
・ImGui>ToggleInput に適当なキーボードショートカットを割り振る
・ImGui>ImGuiInputHandlerClass を ImGuiInputHandler に設定
すると ImGui.ToggleInput をしなくてもよくなります。
f:id:toncrimentan_w:20210308150246p:plain



ImGuiのデモの表示方法はわかったので、
次に自作のウィンドウの作成方法を試してみました。

プロジェクトのBuild.csファイルを修正し ImGui のモジュールを追加します。
ImGuiTest.Build.cs)

using UnrealBuildTool;

public class GuiTest : ModuleRules
{
	public GuiTest(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
	
		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "ImGui" });

		PrivateDependencyModuleNames.AddRange(new string[] {  });
	}
}


ImGuiCommon.h、ImGuiTest.h、ImGuiTest.cpp
ファイルを作成しそれぞれ以下のコードを入力し試してみた。
※参考サイトのコードそのままですが・・
f:id:toncrimentan_w:20210308151023p:plain

※GenerateVisualStudioProjectFilesを実行はおわすれなく。

ImGuiCommon.h)

#pragma once

#ifdef IMGUI_API
#define WITH_IMGUI 1
#else
#define WITH_IMGUI 0
#endif

#if WITH_IMGUI
#include <ImGuiModule.h>
#include <ImGuiDelegates.h>

#include <imgui.h>
#endif

ImGuiTest.h)

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ImGuiCommon.h" 

#include "ImGuiTest.generated.h"

UCLASS()
class GUITEST_API AImGuiTest : public AActor
{
	GENERATED_BODY()

public:	
	AImGuiTest();

	virtual void BeginPlay() override;
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
	virtual void Tick(float DeltaTime) override;

#if WITH_IMGUI
	void ImGuiTick();
#endif
};

ImGuiTest.cpp)

#include "ImGuiTest.h"

AImGuiTest::AImGuiTest()
{
	PrimaryActorTick.bCanEverTick = true;
}

void AImGuiTest::BeginPlay()
{
	Super::BeginPlay();
#if WITH_IMGUI
	FImGuiDelegates::OnWorldDebug().AddUObject(this, &AImGuiTest::ImGuiTick);
#endif
}

void AImGuiTest::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	Super::EndPlay(EndPlayReason);
#if WITH_IMGUI
	FImGuiDelegates::OnWorldDebug().RemoveAll(this);
#endif
}

void AImGuiTest::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
#if WITH_IMGUI
	ImGui::Begin("ImGui Debug Order Test");
	ImGui::Text("Actor Tick: Actor = '%ls', World = '%ls', CurrentWorld = '%ls'", *GetNameSafe(this), *GetNameSafe(GetWorld()), *GetNameSafe(GWorld));
	ImGui::End();
#endif
}

#if WITH_IMGUI
void AImGuiTest::ImGuiTick()
{
	ImGui::Begin("ImGui Debug Order Test");
	ImGui::Text("ImGui World Tick: Actor = '%ls', World = '%ls', CurrentWorld = '%ls'", *GetNameSafe(this), *GetNameSafe(GetWorld()), *GetNameSafe(GWorld));
	ImGui::End();
}
#endif

ビルドがとおり実行すると
ImGuiTestアクターというアセットが作られています。
アクターのスポーンと同時にウィンドウが表示される仕組みになっています。

レベルに配置してプレイすると
無事自作ウィンドウが表示されていることを確認できました。
f:id:toncrimentan_w:20210308151651p:plain



サンプルのパクり方!
ImGuiの仕様のコツはimgui_demo.cppからパクってくるのがコツです。
f:id:toncrimentan_w:20210308151911p:plain
適当にコードをコピーするだけでこんなウィンドウを自作することができました。
f:id:toncrimentan_w:20210308152052p:plain



なおimgui_demo.cppからもってきたソースコードです。
ImGuiTest.h)

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ImGuiCommon.h" 

#include "ImGuiTest.generated.h"

UCLASS()
class GUITEST_API AImGuiTest : public AActor
{
	GENERATED_BODY()

public:	
	AImGuiTest();

	virtual void Tick(float DeltaTime) override;
};


ImGuiTest.cpp)

#include "ImGuiTest.h"

AImGuiTest::AImGuiTest()
{
	PrimaryActorTick.bCanEverTick = true;
}

void AImGuiTest::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
#if WITH_IMGUI
    if (ImGui::TreeNode("Basic"))
    {
        static int clicked = 0;
        if (ImGui::Button("Button"))
            clicked++;
        if (clicked & 1)
        {
            ImGui::SameLine();
            ImGui::Text("Thanks for clicking me!");
        }

        static bool check = true;
        ImGui::Checkbox("checkbox", &check);

        static int e = 0;
        ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine();
        ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine();
        ImGui::RadioButton("radio c", &e, 2);

        // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.
        for (int i = 0; i < 7; i++)
        {
            if (i > 0)
                ImGui::SameLine();
            ImGui::PushID(i);
            ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.6f));
            ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.7f));
            ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i/7.0f, 0.8f, 0.8f));
            ImGui::Button("Click");
            ImGui::PopStyleColor(3);
            ImGui::PopID();
        }

        // Use AlignTextToFramePadding() to align text baseline to the baseline of framed elements (otherwise a Text+SameLine+Button sequence will have the text a little too high by default)
        ImGui::AlignTextToFramePadding();
        ImGui::Text("Hold to repeat:");
        ImGui::SameLine();

        // Arrow buttons with Repeater
        static int counter = 0;
        float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
        ImGui::PushButtonRepeat(true);
        if (ImGui::ArrowButton("##left", ImGuiDir_Left)) { counter--; }
        ImGui::SameLine(0.0f, spacing);
        if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { counter++; }
        ImGui::PopButtonRepeat();
        ImGui::SameLine();
        ImGui::Text("%d", counter);

        ImGui::Text("Hover over me");
        if (ImGui::IsItemHovered())
            ImGui::SetTooltip("I am a tooltip");

        ImGui::SameLine();
        ImGui::Text("- or me");
        if (ImGui::IsItemHovered())
        {
            ImGui::BeginTooltip();
            ImGui::Text("I am a fancy tooltip");
            static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
            ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
            ImGui::EndTooltip();
        }

        ImGui::Separator();

        ImGui::LabelText("label", "Value");

        {
            // Using the _simplified_ one-liner Combo() api here
            // See "Combo" section for examples of how to use the more complete BeginCombo()/EndCombo() api.
            const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
            static int item_current = 0;
            ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items));
            ImGui::SameLine();
        }

        {
            static char str0[128] = "Hello, world!";
            ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
            ImGui::SameLine();

            static char str1[128] = "";
            ImGui::InputTextWithHint("input text (w/ hint)", "enter text here", str1, IM_ARRAYSIZE(str1));

            static int i0 = 123;
            ImGui::InputInt("input int", &i0);
            ImGui::SameLine();

            static float f0 = 0.001f;
            ImGui::InputFloat("input float", &f0, 0.01f, 1.0f, "%.3f");

            static double d0 = 999999.00000001;
            ImGui::InputDouble("input double", &d0, 0.01f, 1.0f, "%.8f");

            static float f1 = 1.e10f;
            ImGui::InputFloat("input scientific", &f1, 0.0f, 0.0f, "%e");
            ImGui::SameLine();

            static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
            ImGui::InputFloat3("input float3", vec4a);
        }

        {
            static int i1 = 50, i2 = 42;
            ImGui::DragInt("drag int", &i1, 1);
            ImGui::SameLine();

            ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%");

            static float f1=1.00f, f2=0.0067f;
            ImGui::DragFloat("drag float", &f1, 0.005f);
            ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns");
        }

        {
            static int i1=0;
            ImGui::SliderInt("slider int", &i1, -1, 3);
            ImGui::SameLine();

            static float f1=0.123f, f2=0.0f;
            ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f");
            ImGui::SliderFloat("slider float (curve)", &f2, -10.0f, 10.0f, "%.4f", 2.0f);

            static float angle = 0.0f;
            ImGui::SliderAngle("slider angle", &angle);

            // Using the format string to display a name instead of an integer.
            // Here we completely omit '%d' from the format string, so it'll only display a name.
            // This technique can also be used with DragInt().
            enum Element { Element_Fire, Element_Earth, Element_Air, Element_Water, Element_COUNT };
            const char* element_names[Element_COUNT] = { "Fire", "Earth", "Air", "Water" };
            static int current_element = Element_Fire;
            const char* current_element_name = (current_element >= 0 && current_element < Element_COUNT) ? element_names[current_element] : "Unknown";
            ImGui::SliderInt("slider enum", &current_element, 0, Element_COUNT - 1, current_element_name);
            ImGui::SameLine();
        }

        {
            static float col1[3] = { 1.0f,0.0f,0.2f };
            static float col2[4] = { 0.4f,0.7f,0.0f,0.5f };
            ImGui::ColorEdit3("color 1", col1);
            ImGui::SameLine();

            ImGui::ColorEdit4("color 2", col2);
        }

        {
            // List box
            const char* listbox_items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
            static int listbox_item_current = 1;
            ImGui::ListBox("listbox\n(single select)", &listbox_item_current, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
        }

        ImGui::TreePop();
    }
#endif
}

imGuiはとても便利です。
プレイ中UI:ヴィジェットブループリント
プレイ中のデバッグ用UI:ImGui ←☆New
プレイ前のデバッグ用UI:エディタユーティリティヴィジェット
といったところでしょうか。