げーむ開発徒然日記~怠惰のために勤勉~

Unreal Engineや3DCG制作について学んだことを記事にしていきます

UIマテリアルでテキストなどをおもしろくする

 この記事は、Unreal Engine (UE) Advent Calendar 202320日目の記事となります。

はじめに

 今回は、UE5のウィジェットで、テキストにエフェクトを加えたり、UIの部分的または全体にポストプロセス的にエフェクトを加えたりする方法を紹介します。

※使用したUEのバージョン:5.3

フォントマテリアル

 UE5のUIを作る際に使用するウィジェットには、フォントマテリアル(Font Material)というものがあります。これは、UTextコンポーネントなどで使用できます。テキストにアウトラインを付けたりするのは、フォントマテリアルを使わなくてもできるようになっておりますが、テキストにテクスチャを適用したり、変形したりといったちょっとしたエフェクト的なものを与えたい場合には、フォントマテリアルを使用することになります。

例)アウトラインにフォントマテリアルを割り当ててオーラ的な動きをつけたもの

フォントマテリアルの準備と適用方法

1)新規マテリアルを作成し、Material DomainUserInterfaceにします。

 Blend Modeは通常のマテリアルと同様にOpaqueMasked, Translucentなどが使え、出力が異なります。文字の一部を削りたいなどの場合はMaskedを使う必要があります。

 ↓通常のマテリアルとは出力が異なる(Blend Mode = Translucentにしたもの)

 

2)次に適用方法ですが、ウィジェットにText,Editable Text,Rich Text Blockなどを配置して、詳細パネルから割り当てます。なお、テキスト本体および輪郭のフォントマテリアルは分かれており、それぞれにマテリアルを割り当てられるようになっています。

Textureで柄を付ける

基本

 以下のようにVertex Color(テキストカラー)にUEロゴのテクスチャを乗算したものを最終カラーに出力してみます。

 ウィジェットのテキストの詳細パネルには上記画像のように、テキストの色と透明度を設定する項目Color and Opacityがありますが、ここで設定した値がフォントマテリアルのVertex Colorとして使用されます。

[結果]

 テキストカラーは白にしているので、UEロゴのテクスチャがそのまま乗りました。

文字ごとにテクスチャで柄を付ける

 先ほどの例では、テクスチャがテキスト全体に収まるようにストレッチがかかっていましたが、文字ごとにテクスチャの柄を付けたい場合には、どのようにすべきでしょうか。Texture SampleにTex Coordを入力してみます。Indexを「1」にすることで、文字ごとの座標が取得できるようです。

[結果]

 各文字に対してテクスチャの柄が付けられました。

スクリーン空間にテクスチャで柄を付ける

 先ほどまでの例ではすべて、テクスチャにストレッチがかかってしまっています。これの回避策としては、ScreenAlignedPixelToPixelUVsを使う方法がありますが、名前の通りスクリーン空間にテクスチャが貼られるような形になるため、パターン柄でない限りは使いづらい方法です。

[結果]

 テキストの位置が変わっても、テクスチャの位置は変わりません。

テキストを動かす・変形する

テキスト位置をテキストカラーによって動かせるようにしてみる

 マテリアルの出力にあるスクリーン位置に入力を与えることでテキストを動かしたり、変形したりできます。

 試しに以下のようなマテリアルを組んでみました。

 画像のコメントにある通り、テキストの色が変わるとスクリーン位置も変わると予想できます。

[結果]

 予想通り、テキストの色によって位置が変わりました。

テキストを変形させる

 テキストを変形させるマテリアルを適当に組みました。

[結果]

 ふにふに動きます。ただし、四隅しか動かせません。

 ↓動きを横方向に制限したもの

エフェクトマテリアル

 フォントマテリアルでは、テキストにエフェクトを与えられますが、RetainerBoxのEffect Materialを使うとUIの部分的または全体にポストプロセス的な加工をできます。これはおもしろくて、今回紹介する基本的なもの以外にもいろいろな活用方法があると思います。

エフェクトマテリアルの準備と適用方法

 まずは、ウィジェットにエフェクトを適用したい領域をRetainerBoxで形どります。

 次にフォントマテリアルと同様に新規マテリアルを作成し、Material DomainUserInterfaceにします。

 RetainerBoxの詳細パネルのEffect Materialに、作成したマテリアルを割り当てます。Show Effects in Designerにチェックを入れるとUMGデザイナー上でエフェクトを確認できます。

波打つような変形効果を与える

 以下のようにマテリアルを組みました。

(注意)RetainerBoxのEffect設定にある"Texture Parameter"と同名のテクスチャパラメータをマテリアル内に用意する必要がありますが、テクスチャは何でも大丈夫です。

[結果]

 RetainerBox内の領域のみに波打つような効果が与えられました。

※UE5.3のバグだと思うのですが・・・背景部分が黒くなってしまっています。Blend ModeAdditiveにしたら、透過できましたが、加算が入ってテキストカラーも変わってしまいました。

 もちろん、テキスト以外に画像やボタンなどにどれにでもエフェクトを与えられます。

おわりに

 以上、フォントマテリアルおよびエフェクトマテリアルの紹介でした。個人的に、フォントマテリアルは最初に載せた輪郭に適用したものは汎用性が高そうに感じました。

 また、エフェクトマテリアルはHUDに使ってBPとの連携でパラメータを動的に変更して…などで使うとおもしろいと思います。

 プロジェクトにマッチしそうなアイデアを見つけ、ぜひ使ってみてください!

参考

[UE4]UI用マテリアルの「Screen Position」で遊ぼう|株式会社ヒストリア

UMGのフォントをアレンジ - みつまめ杏仁

【Houdini】スプラッシュ画面が表示されるだけで起動しない

個人的備忘メモ

環境:Windows 11

Houdini 19.5.716(indie版使用)

概要

以前使っていたPCでも、新調したPCでも同様の問題が起きていた。

具体的には、ランチャーからの起動でも、直接houdini.exeを開いての起動でもスプラッシュ画面が表示されて数秒後に、スプラッシュ画面が消えるだけで結局起動しない。

その後、何度か試しても時々スプラッシュ画面が表示されるが同様に起動しない。

スプラッシュ画面が表示されない場合のほうが多く、青い読み込みの表示がマウスカーソルの横に出るだけである。

なお、原因を調べようとイベントビューアーを確認したところ、Windowsのntdll.dllというものに障害が発生とのことだったが、なぜなのかよくわからない。

 

調べたところ同様の事例がかなり多く報告されているのに対し、いまだに解決策が明確でない状況である。

今回は、調べても出てこなかった対策のひとつのメモとしつつも、同様の症状が出ている方の参考になれば幸いだと思ったので共有する。

もしこれで治った方がいれば、記事の下部にある★ボタンを押してくださると嬉しいです。

対策として試したこと

以下、効果がなかったことリスト。

Windows再インストール⇒実際には行っていないが、新調しても発生したので意味がないと思われる

・Houdiniやライセンスサーバー再インストール

・Houdiniを管理者として実行

ファイアウォール無効化

・DocumentフォルダにあるHoudini19.5のフォルダ削除

ライセンスサーバーをサービスから再起動

効果があったもの(確実に有効かは不明)

・私の場合、どうもウイルスバスターが悪さをしているみたいだったので、以下の「コンピュータの保護設定」でhoudini.exeをスキャンの対象外に設定した。

※私が使用しているライセンスはIndie版だが、設定するのはhindie.exeではなくhoudini.exeで良いと思う。

これだけで、Houdiniが起動しないなんてことはなくなってしまった。ウイルスバスターでない方も、ウイルス対策ソフトを疑ってみるとよいかもしれない。

注意点

フォルダシールドの設定画面からも「許可するプログラムの一覧」という上記と似たような設定画面が出てくる。が、こちらは上記の設定とはまた別の設定であり、こちらにhoudini.exeを設定しても効果がなかった(上記の「コンピュータの保護設定」でhoudini.exeをスキャン対象外としても、以下の「許可するプログラムの一覧」には登録されない)。

 

【UE5】Proceduralなナンバープレートのマテリアルを組んでみる

目次

0.はじめに

 今回組んでみたのは、様々な組み合わせの番号や用途表示などに対応可能なナンバープレートのマテリアルです・・・というのはあくまで具体例で、実際のところやっていることを抽象的に言えば、

 「あるテクスチャの任意の範囲だけ」「任意のモデルの任意のUV座標範囲」合成するというものです。

 イメージはこんな感じ↓

 今回のナンバープレートの場合で言うと、何も書かれていない"更地"のナンバープレートに、数字や文字を合成していくイメージですね。

 この方法は、色々なことに使えると思います。例えば、

【例1】UV空間のほんの一部にしか発光する部分を持たないオブジェクトで、わざわざ4K解像度のベースカラーテクスチャのAチャンネルをエミッシブのマスクに使いたくない場合

 ⇒今回の手法を使えば必要最低限のサイズ(64x64サイズなど)のエミッシブマスクを用意すればよくなります。

【例2】学校の教室のプレートや看板など、ベース部分を使いまわしたい場合

 ⇒今回紹介するナンバープレートと同じパターンです。

 

 きっかけはGhostwire: Tokyoで車が様々なナンバーだったのを見かけたことです。最初はテキストレンダーコンポーネントでも仕込んであるかと思ったんですが、ちゃんと文字がプレート表面から盛り上がっている=ノーマル情報があるんですよね。ただ、Ghostwire: Tokyoの車で使われている数字は完全にランダムではなく何らかの規則性はありそうな気がします。

1.実装例

 今回使用したUEはバージョン5.1.1です。

1-1.完成形

 以下の動画をご覧ください。

 付与した機能は色々ありますが、本記事で取り上げるのは以下の2つです。

①ナンバー(10-00~99-99)が、ランダム変化する

1~3桁ナンバーには対応させていないのでご了承ください。そこまで難しいことではないですが、対応させるには別途改変する必要があります。

②手動でも設定可能にする

⇒今回は、①②を実現するため最終的にBP Actorにします。

1-2.用意するもの

単純なアトラス化が施されたテクスチャ(合成したいもの)

※もちろんアトラス化されていないものでも大丈夫です(補足参照)。

 今回は、R+Gチャンネルに法線情報Bチャンネルにマスク情報を持つテクスチャを用意しました(上から順にR+G+B,R+G,B)。

※ブログ用に作ったものなのですごく雑ですし、サイズも圧縮のことも何も考えていません。ナンバーって特殊なフォントだなあ…。

 単純なアトラス化と言っているのは「要素が等間隔に分割されているもの」を指しており、上のテクスチャはどちらも各数字が等間隔に配置されています。

Tips:

・必要な解像度は使用する自動車モデルに使われているテクスチャの解像度に合うようにすることを推奨します。

・3桁ナンバーなどに対応させる場合は「・」もテクスチャに含めないといけません。

1-3.マテリアルの作成

最初はBチャンネルのマスク情報を使って合成するための準備段階から始めるので留意ください!!

1-3-1.テクスチャの任意の範囲を切り取る

 まず最初に、冒頭で述べた

「あるテクスチャの任意の範囲だけ」「任意のモデルの任意のUV座標範囲」合成する

の、「あるテクスチャ(この例では、合成に使うテクスチャ)の任意の範囲」を切り取ることから始めます。

 エンジンに標準で用意されているFlipBookというマテリアル関数を使うだけでこれを実現できます。以下(紫色でコメントされた部分)をご覧ください。

 0123456789から3だけが切り取られています。上の画像では、Numberというパラメータに与えられた数字が切り取られるようにしています。

Tips:FlipBookは本来的には、エフェクトに使う連番テクスチャを入力して、Animation Phaseの値を変化させることでパラパラ漫画のようにアニメーションさせることに使うことが多いと思います。

1-3-2.任意のUV座標範囲を切り取る

 次は、

「あるテクスチャの任意の範囲だけ」「任意のモデルの任意のUV座標範囲」合成する

の、「任意のモデルの任意のUV座標範囲」を切り取ることを行います。

 こちらもエンジンに標準で用意されているTextureCroppingというマテリアル関数を使うだけでこれを実現できます。以下(茶色でコメントされた部分)をご覧ください。

 UpperLeftCorner(V2)およびLowerRightCorner(V2)という入力を与える必要があります。これは切り取りたいUV範囲の正規化座標となります。

1-3-3.ナンバーを合成したい場所に合わせてポジショニングとスケーリングする

 ここまでできたら、先ほどの1-3-1で得られた「切り取られたナンバー」を、合成したい範囲の大きさに合わせてポジショニングおよびスケーリングしていきます。

 厳密に言えば、「タイリングをした後に、必要な部分のみを残す」といったことを行います。

 以下のように1-3-2で使ったTextureCroppingのCrop UVsという出力を、FlipBookのUVsに与えてやると、FlipBookの出力にタイリングをかけることができます。

 次に、タイリングで作られる不要部分を除去するためには、Crop Maskという出力が、切り取られた範囲のマスク情報として使えます。

 それでは、以下のようにFlipBook(タイリングされたナンバー)から、不要部分をマスクで除去します。なお、途中でBチャンネルをマスクしているのは、Bチャンネルには文字部分のマスク情報があるため、Crop Maskと乗算することで、CropMaskにある範囲内かつ数字のみのマスク情報というのを作ることができるためです。最終出力はMaskedNumberというNamed Rerouteに格納しました。この情報を後々使いまわします。

1-3-4.カラー情報を合成する

 ようやくカラーや法線を合成する準備が整いましたので、まずはカラーから乗せていきますが、これは簡単です。ナンバープレートのベースカラーテクスチャに対して、先ほどのマスク情報を使ってLerpで合成するだけです。

1-3-5.法線情報を合成する

 まずは、合成する法線情報を作ります。以下のようにマテリアルを組みます。

 1-2で説明したように、今回用意したテクスチャはR+Gチャンネルに法線情報があるだけであってBチャンネルを再構築する必要があるため、DeriveNormalZを使って法線情報を再構築します。その後、ナンバー以外の部分はFlattenNormalによって平坦化し、強度調整用のFlattenNormalも別途配置します。

 あとは、BlendAngleCorrectedNormalsを使って、ナンバープレートのベースの法線マップに対して合成をかけます。

1-3-6.4桁ナンバーにする

 4桁ナンバーにするにあたって、まずはマテリアル関数化し、コンパクトにしました。

 マテリアル関数内の、TextureCroppingのところも少し変更しています。

 あとは、この関数を4桁分=4つ配置して合成します。

 NumberSizeのパラメータのみ使いまわしています。さすがに若干コストが高くなります。とりあえずこれで一通りは完了です!あとはランダム化に対応していきましょう。

1-4.ランダム化への対応

1-4-1.Custom Primitive Data

 Material Instance Dynamics(MID)を使っても可能なのですが、今回はCustom Primitive Data(CPD)を使います。

 MIDではスカラーパラメータとベクターパラメータに加えて各種テクスチャパラメータなどを動的に変更可能なのに対し、CPDではスカラーパラメータとベクターパラメータしか扱えませんが、今回のケースではCPDで十分に対応できます。

 また、CPDのほうがドローコールを節約するうえで特に有効な手段ですので、CPDで対応できるものは積極的にCPDを利用したほうがよいです。これについては公式ドキュメントを一読しておくことを推奨します。

 マテリアル内のNumber_1~Number_4に、Custom Primitive Dataを使うように設定します。

 パラメータを選択した状態で、詳細タブからUse Custom Primitive Dataにチェックを入れて、Primitive Data Indexを指定します。

 今回は、Number_1~Number_4の順に、Primitive Data Indexに1~4を割り当てました。

1-4-2.Actorを継承したBPクラスを作成

 今回は、Actorクラスを継承したBP_LicensePlateMatTestを作成しました。この中のBP処理にてランダム化対応を実装していきます。

 あとはConstruction Scriptにて、それぞれのCustom Primitive Dataに0~9のランダムな値を与えてやるだけです。また、4桁の場合、先頭に0はこないので、先頭のみ1~9となるようにしています。

 ここまででランダムナンバーは終わりです!お疲れ様でした。次はオプション的なものですが、手動設定にも対応させていきます。

1-5.手動設定への対応

 すぐにできます。それぞれのナンバーに対応する変数と、手動で設定するかどうかを決めるbool変数を用意します(目玉マークが開いているようにすること)

 あとは以下のように、分岐処理を組んであげるだけです。

 レベル上で編集してみると、手動設定が機能していることを確認できます。

 おしまい!

補足

アトラス化されていないテクスチャを使用する場合

 切り取る必要がないということなので、FlipBookを使わずにTextureSampleを使用するだけです。

BP Actorにせず、単なるStaticMeshActorで実現したい

 ナンバーランダム化の柔軟性が落ち、手動設定機能も失われますが、以下のようにすればできます。この例では、シェーダー内でナンバーを自動で決めることによってBPで数値を変更しなくてもよくなっています。ただし、4桁全てをバラバラにするためには更なる工夫が必要です。

シェーダーコストを下げたい

以下のような対応で、多少は下がると思います。

・標準のFlipBookでは冗長なので、必要な計算だけを残したカスタムのマテリアル関数を作成しましょう。

・標準のTextureCroppingでは冗長なので、必要な計算だけを残したカスタムのマテリアル関数を作成しましょう。

・合成する部分の数が多いほどTextureSampleが増えたりとそれなりにコストも増加していきます。ナンバープレートの場合は、ナンバー4桁=4つ以上は合成する部分が必要になりますが、それ以外はある程度妥協しましょう。FlipBook内でも、TextureCropping内でもTextureSampleが使われているので注意。

【UE5】EQSを使って遮蔽物によるインタラクションアイコンの表示・非表示を実装してみる

本記事は、Unreal Engine (UE) Advent Calendar 2022の18日目の記事になります。

目次

はじめに

 本記事では、UEのEQS(Environment Query System;環境クエリシステム)を使って、アイテムピックアップ、ドア開閉などのインタラクション可能なオブジェクトのアイコンを遮蔽物の有無によって表示・非表示を切り替える機能を実装していきたいと思います。

※後述しますが、この方法、正直効果的ではないです。あくまで「EQSを使ってみた」だけのもので、利点は、実装がシンプルでわかりやすいくらいかなと思ってます(インタラクティブなオブジェクトにトレースなどの処理を書かなくて良いため)。プロトタイプや簡単なプロジェクトに使う分にはいいかもしれません。

 なお、今回使用したバージョンは5.1です。

docs.unrealengine.com

 上記の公式ドキュメントによれば「EQS のユースケースの例としては、最も近い体力のピックアップや弾薬を探したり、どの敵が最も脅威となっているのかを把握したり、プレイヤーが見える位置を見つけたりすることが挙げられます」と記載されており、EQSはUE標準のAIビヘイビアツリーなどと組み合わせることで様々な環境に対応可能なAIの作成に活用できるものですが、今回はあえてオブジェクトのアイコン表示に使ってみました。

完成形

 作成したものの完成形は以下のような感じ。

 インタラクション可能なオブジェクトが遮蔽物の奥に隠れている場合、アイコンが非表示になります

 厳密に言えば、Querierとなるキャラクターのカメラ位置からインタラクティブなオブジェクトの原点位置との間に遮蔽物があるかどうかを見ています。この時点でなんとなく、最初に注意点として述べた理由がわかるかと思います。

ウィジェットコンポーネントについて

 インタラクティブなオブジェクトにアイコンを表示しようとした場合、ウィジェットコンポーネントをアクターに取り付けることが多いかと思います。

 そしてウィジェットの描画方法としては、

スクリーン空間 ⇒ワールド座標をもとにスクリーン座標に2Dウィジェットを描画

ワールド空間 ⇒ワールド座標に3Dウィジェットを描画

があります。

 ワールド空間であれば特に何もせずとも遮蔽物の奥のアイコンは隠れるのですが、

「カメラとの距離に応じて表示サイズが変わる」「3Dウィジェットのため3次元の向きを持つ(後ろから見ると反転して見える)」などといった挙動となります。

 反対に、スクリーン空間であれば上記とは逆で「カメラとの距離によって表示サイズは変わらない」「常に正面を向いている」といった挙動にはなりますが、遮蔽物の奥にあったとしても関係なしに画面に描画されます。

 このように、どちらの描画方法も一長一短ですが、今回のようなインタラクションアイコンや敵のHPバーなどといったものに対しては、一般にスクリーン空間での描画が適しています。

 しかし、繰り返しにはなりますがスクリーン空間への描画をそのまま使うと冒頭で示した動画のような、遮蔽によるアイコンの表示・非表示というのができません。仮にこれをBPのみで実装しようとすると、ちょっと面倒だったりします。

 このため、今回は上述のEQS機能のひとつである「プレイヤーが見える位置を見つけたりすること」を使ってサクッと簡単に実装していきます。

実装

準備

 使用するUEのバージョンによっては、プロジェクト内の[Editor Preferences (エディタの環境設定)] > [Experimental (実験的)] > [AI]セクションで、Environment Querying Systemをオンにする必要があります。UE5.1ではそもそも項目が見つからないはずです。

EQS_QuickStart_01.png

※画像は公式ドキュメントから引用

環境クエリの作成

 まずはコンテンツブラウザの右クリックメニューから環境クエリを作成します。

 作成されたアセットを開くと、ビヘイビアツリーのようなエディタ(クエリグラフ)が開きます。

 最初から置いてある、ルートノードからドラッグ操作で出てくる[Actors Of Class]を選択します。

 これは、GetActorsOfClassに近いものであって、詳細パネルから取得したいアクタークラスと、球状のサーチを行うかどうかなどを設定できます。

 今回は、BP_Interactableというクラスをサーチするので、先に作成し、以下のように[Searched Actor Class]に設定しておきます。

 Generate Only Actors in Radiusは、TrueであればSearch Radiusで設定された半径の球状の範囲内のSearched Actor Classオブジェクトをサーチします。Falseであればワールド全体からサーチします。

 Search Radiusは後ほどキャラクタークラスからクエリにパラメータを与えるため、Query Paramsにしておきます。

 Search Centerはサーチの中心位置です。デフォルトのEnvQueryContext_Querierのままでも大丈夫ですが、今回はカメラ位置を中心にしたいので、コンテンツブラウザ右クリックから[EnvQueryContext_BrueprintBase]を作成します。これによって、Querierの情報をもとにカスタムの位置情報などを作成できます。

 作成したらアセットを開き、Provide Single Location関数をオーバーライドします。これで、Querierの位置をキャラクター原点ではなくてカメラ位置にオーバーライドできます。

 これができたら、先ほどのSearch Centerに、作成したEnvQueryContextを設定します。

 次に、クエリグラフに戻ってActors Of Classノードを右クリックして[テストを追加]>[Trace]を選びます。

 Actors Of ClassノードにTraceという項目が追加されるので選択すると、詳細を設定できます。

 設定は以下のようにします。

 [Context]に先ほど作成したカメラ位置を使えるようにするEnvQueryContextを設定します。

 

 これで、このクエリを実行すると、

カメラ位置を中心とするSearch Radius半径の球内に存在するBP_Interactableオブジェクトを取得⇒取得された全てのBP_Interactableオブジェクトの原点位置からカメラ位置にトレースによって遮蔽物があるオブジェクトについてはクエリ終了後の最終的な出力から弾かれる。といった具合になります。

プレイヤーキャラクターの作成

 まずは、近くにあるBP_Interactableを検出するためのコリジョンコンポーネントを追加します。

※InteractableCollisonは詳細パネルから全チャンネルへの応答をオーバーラップにしていますが、インタラクティブなオブジェクトのみをオーバーラップ、他のアクターやコンポーネントに対しては応答を無視にするとなお良いです。

 BeginPlayイベントで色々とセットアップするので、Enable Interactable Detectionというカスタムイベントを追加します。

 以下がイベントの中身です。コリジョンの半径を設定したり、オーバーラップイベントなどを作成しています。

 コリジョン内のBP_InteractableはInteractable配列内に格納されます。

 次はSequenceノードの2つ目からの内容です。先ほど、クエリグラフのActors Of Classノードにてサーチ半径にパラメータを使うことに設定していたので、キャラクターのBPから与えてやります。

 UpdateInteractionIconイベントでは、球体内に存在するBP_Interactableに対して、それぞれの可視・不可視に応じてウィジェットの可視性をトグルしています(次項参照)。

インタラクティブなオブジェクトの作成

 Actorクラスを継承したBP_Interactableは、スタティックメッシュコンポーネントと、ウィジェットコンポーネントを追加しただけの単純なものです。

 ウィジェットコンポーネントの詳細設定にて描画をScreenにしておき、ウィジェットの可視性(Visibility)はデフォルト値をFalseにしておきます。ウィジェットクラスには自作のアイコン表示用ウィジェットを設定してください(作成は割愛)。

 キャラクタークラスから実行していたToggle Iconイベントは以下の通り。

 

⇒実装おしまい

おわりに

 というわけで、今回はEQSを使って遮蔽物の有無によるインタラクションアイコンの表示・非表示をできるようにしてみました。

 実際にはトレースを飛ばし続けてさらに近づいたときに、あとはボタンを押すだけでインタラクトできることを示すようにアイコンの見た目を変えたり、もちろんインタラクション処理も追加実装する必要があります。

 そしてかなりデメリットであるのが、プロジェクトによっては複数の引き出しをコンポーネントとして持つタンスなどのアクターを作成する場合です。この場合、今回の方法を用いると、アクター(タンス自体)の原点の位置情報が使われるため、タンスの原点さえ見えていれば全ての引き出しに対してアイコンが表示されてしまうといったことが生じうるため根本から方法を変えるか大幅な変更を行う必要などが出てきますので、それでも良ければ構わないのですが、できれば今回の方法でも十分なプロジェクトやプロトタイプ程度に使うのが良いかと思います。

 また、タイマーでクエリを実行していますが、For Each Loopによるオブジェクト毎へのウィジェット情報の更新を行いますし、クエリのActors Of Classも決して処理負荷的に優しいものではないという点にご留意ください。

 なので、ちゃんと実装する場合は、素直にC++を使うのがいいです。

 

対象Actorの速度を監視するAbilityTask

概要

GASにてダッシュアビリティ(GA_Run)を実装した際、ダッシュのアクション入力をすると止まっているにも関わらずGA_Runの持つState.RunningのようなGameplayTagが付与されてしまうのが気になっていました。

AbilityTaskですが、どうやらTick動作させることができるみたいなので、それを利用してActorの速度を監視するAbilityTaskを作りました。

AbilityTaskの作り方については、あいす氏の記事でわかりやすく解説されていますのでそちらをご覧ください。 また、公式の詳しい作成手順はAbilityTask.h内に示されています。

[UE] AbilityTask のつくりかた - Qiita

使用UEバージョン:5.0.3

作成するAbilityTask

今回作ったものは以下のようなものです。

AbilityTaskを実行するとTargetに接続したActorの速度(高さ方向は無視)を監視し続け、Threshold(閾値)を超えるとOnStartMovingデリゲートが発行され、再度Threshold以下となるとOnStopMovingデリゲートが発行されるといった非常にシンプルな構成になっています。

実装

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FWaitGroundMovingDelegate);

UCLASS()
class YOURPROJECT_API UAbilityTask_WaitGroundMoving : public UAbilityTask
{
    GENERATED_BODY()

    UPROPERTY(BlueprintAssignable)
    FWaitGroundMovingDelegate OnStartMoving;
    UPROPERTY(BlueprintAssignable)
    FWaitGroundMovingDelegate OnStopMoving;

    virtual void TickTask(float DeltaTime) override;

    /** TargetActorのXY速度が閾値Thresholdを上回る、又は、Threshold以下となるのを待つ */
    UFUNCTION(BlueprintCallable, Category = "Ability|Custom|Tasks", meta = (DisplayName= "WaitGroundMoving", HidePin = "OwningAbility", DefaultToSelf = "OwningAbility", BlueprintInternalUseOnly = "TRUE"))
    static  UAbilityTask_WaitGroundMoving* CreateWaitGroundMoving(UGameplayAbility* OwningAbility, AActor* Target, float Threshold);

    virtual void Activate() override;

protected:
    UPROPERTY()
    AActor* TargetActor;
    
    float Threshold;

private:
    bool bIsMoving;
};
#include "Kismet/KismetMathLibrary.h"

void UAbilityTask_WaitGroundMoving::TickTask(float DeltaTime)
{
    if (TargetActor)
    {
        float GroundSpeed = UKismetMathLibrary::VSizeXY(TargetActor->GetVelocity());

        if (GroundSpeed > Threshold)
        {
            if (!bIsMoving)
            {
                if (ShouldBroadcastAbilityTaskDelegates())
                {
                    OnStartMoving.Broadcast();
                }
                bIsMoving = true;
            }
        }
        else
        {
            if (bIsMoving)
            {
                if (ShouldBroadcastAbilityTaskDelegates())
                {
                    OnStopMoving.Broadcast();
                }
                bIsMoving = false;
            }
        }
    }
    else
    {
        ABILITY_LOG(Warning, TEXT("UAbilityTask_WaitGroundMoving ticked without a valid Actor. ending."));
        EndTask();
    }
}

UAbilityTask_WaitGroundMoving* UAbilityTask_WaitGroundMoving::CreateWaitGroundMoving(
    UGameplayAbility* OwningAbility, AActor* InTarget, float InThreshold)
{
    auto* MyObj = NewAbilityTask<ThisClass>(OwningAbility);

    MyObj->bTickingTask = true;  //Tick動作に必要
    MyObj->TargetActor = InTarget;
    MyObj->Threshold = InThreshold;

    return MyObj;
}

void UAbilityTask_WaitGroundMoving::Activate()
{
    SetWaitingOnRemotePlayerData();
}

MetaSoundでお手軽ラジオボイス風表現

タイトル通りです。

なんとなく「外部ソフトを使用せずにUE5内でプロシージャルにラジオ風音声に変換したいな」と思ったので紹介します。

※MetaSoundの基本的な使い方は省略します。使用するにはプラグインをONにしてください。

また、音声サンプルはありません。

使用バージョン:UE5.0.3

フィルタを使ってこもったような音声にする

まだMetaSoundをほとんど触ったことがなく、機能を把握しきれていないので今回は単純にLPF(Low-pass filter)とHPF(High-pass filter)+αを使っていきます。もちろんBPF(Band-pass filter)でもできるはずです。

LPFは、所定の周波数以上の成分をカットするフィルターで、HPFはその逆です。

手順は以下の通りです。

入力ノードOn PlayピンからWave PlayerノードPlayピンに接続して音声アセットを再生できるようにします。

Wave PlayerノードOut Leftピンから、ワンポールハイパスフィルタノード(HPF)のInピンに接続します。

下図の例では、カットオフ周波数を"3000"に設定しているので、3000Hz以上の周波数成分を通します(数値は割と適当なので調節してください)。

なお、今回はデフォルト設定のモノラル音声のまま進めるので、Wave PlayerノードのOut Rightピンは使用しません。

ワンポールハイパスフィルタノードOutピンからワンポールローパスフィルタノード(LPF)のInピンに接続します。

再生してみるとわかりますが、元の音声に比べてこもったような感じになっていると思います。

音質を悪くする

先ほどまでの状態でこもった音声にはなりますが、元の音声の品質が高いとまだまだラジオっぽくなりません。

そこで、Bitcrusherノードなるものを、フィルタを通した先に接続します。

これは、ノードの説明にもあるように「入力オーディオ信号をダウンサンプルし、ビット深度も下げる」ものみたいなので使えそうだなと思いました。

サンプルレートとビット深度をお好みに合わせて調節してください。

これで再生してみると、音質が低下したことで更にラジオっぽくなっていると思います。

仕上げにノイズを追加する

先ほどまでで声のいじくりは終わったので、最後は仕上げにノイズを乗せることでよりラジオっぽくしていきますが、ノイズを追加するかどうかは必要に応じて選択してください。

手順は以下の通りです。

ノイズノードを出して、出力をPink NoiseかWhite Noiseかを選択する。

②今回はモノラル音声なのでMono Mixer (2)ノードで声とノイズをミックスする。

③声とノイズのゲインを調節する。

いかがでしょうか。

元の音声と比べるとだいぶラジオっぽくなっていると思います。

これで、わざわざ外部ソフトで加工しなくてもUE5内で完結できちゃいますね。また、パラメータを変数化して元の音声ファイルを残したままプロシージャルに調節可能なのもMetaSoundの大きな利点だと思います。

使い方を調べながら検証するつもりが思ったよりも使いやすかったため、一瞬で記事まで書けてしまいました。

 

つまり、MetaSoundは素晴らしい!

 

以上

CC3キャラクターの表情シェイプキーとフェイスリグを残し、Blender Auto-Rig Proのボディリグに統合する

 今回の記事はタイトル通りです。

 今回ご紹介させていただく方法は、Reallusion公式のチュートリアル動画やAuto-Rig ProとUE4との連携についての先人様のブログをいくつか参考にまとめたものです。

 こちらの方法を使うことによって、下記メリットが得られると考えられます。

・CC3キャラクターをBlenderにインポートしてもリギングされていないためすぐにアニメーション作成に取り掛かれないが、Auto-Rig Proの自動リグ生成によってこれを解消できる。iCloneなどよりBlenderでのアニメーション制作のほうが慣れている場合は特に推奨。

・フェイシャルリグはAuto-Rig Proの生成機能を使わず、CC3の表情シェイプキーとフェイシャルリグを統合させるため、Reallusionの強力なLive Faceアプリなどは引き続き使える(はず)。

・Auto-Rig ProはUE4やUnityなどのゲームエンジン向けのエクスポートに対応しており、これによってUE4やUnity標準スケルトンとほぼ同様の命名に自動変換してくれるので地味に嬉しい。

 ゲームエンジン側で自動でマテリアルなどを設定してくれるプラグイン(Auto-Setupプラグイン)はあるが、これを使っても標準スケルトンに沿った命名はなされない。ただしマテリアル設定に関してはAuto-Setupプラグインを使うのがよいと思われます。今回の手順はあくまでもスケルトンの入れ替えと、アニメーション作成などのためのみです。

・CC3で作成したヒト型キャラクターやそれ以外のソフト(Blenderなど)で作成したヒト型キャラクターを、Auto-Rig Proで作成したアーマチュアに統一することでリターゲティングが不要になったり簡単になる場合が多い。

CC3でのキャラクター作成~Blenderでのインポートと準備

CC3からエクスポートし、Blenderでインポートする

 ここは特に難しいことはしません。以下の設定でCC3からFBXエクスポートします。

f:id:raksul_01:20211218142514p:plain

 エクスポートされたFBXをBlenderにインポートします。

インポート時の設定はデフォルトのままでOKです。

f:id:raksul_01:20211218142837p:plain

Auto-Rig Proのための事前準備

 テンキーの1を押して正面から見ると、おそらく足がZ=0の面に設置していないことになっているので、アーマチュアを選択した状態で、足がZ=0にくるようにします

(X軸を示す赤色の線に合わせる)。

f:id:raksul_01:20211218143046p:plain

 その後、Aキーでアーマチュアとすべてのメッシュを選択した状態でCtrl+A→「適用:全トランスフォーム」をします。

 また、このままだとメッシュ内部に骨があって見えづらいので、以下のように「最前面」にチェックを入れます。

f:id:raksul_01:20211218143619p:plain

 次に、後で誤って操作しないようにするために各パーツのメッシュ(身体、服、靴、眼球、口、舌、髪の毛などすべて)それぞれに対して、頂点グループをすべてロックします。ちなみに、左クリックした状態でドラッグすると一気にロックできます。あるいは、下向きの「>」を押すと「すべてロック」というボタンがあります。

f:id:raksul_01:20211218144950p:plain

Auto-Rig Proによるアーマチュア・リグ生成とスキニング

アーマチュアの自動生成と修正

 キャラクターのメッシュをすべて選択した状態で、Auto-Rig ProのメニューからGet Selected Objectsを押します。

f:id:raksul_01:20211219114651p:plain

 すると、元のアーマチュアが非表示になりますが、後の作業のためにアーマチュアを再度表示します。

f:id:raksul_01:20211219115401p:plain

 ここからはAuto-Rig ProのSmart機能を使って、アーマチュアを生成します。Smart機能を使う際、首、アゴ、肩、手首、背骨のルート、足首のアタリをつけていくことになります。

 先ほどAuto-Rig Pro:Smart内のGet Selected Objectsボタンを押した後、メニュー内がAdd Neckなどのボタンに変わっていると思うので、そちらを押すとアタリをつけるためのマーカーが追加されるので、再表示した元のCC3アーマチュアをもとにアタリをつけていきます

f:id:raksul_01:20211219121522p:plain

 配置し終えたらGoボタンを押します。Auto-Rig Proのバージョンによってはこのとき、フェイシャルリグを生成するか聞かれますが今回はCC3のフェイシャルリグを統合することが目的なので生成しないようにします。

f:id:raksul_01:20211219121803p:plain

 すると、アーマチュアが自動生成されますが、元のCC3アーマチュアに対してずれているので各ボーンの位置を修正していきます。なお、手足などは左右対称に位置が移動されるので、片側のみでOKです。

f:id:raksul_01:20211219125709p:plain

足の3か所(leg_ref.l, foot_ref.l, toes_ref.l)

f:id:raksul_01:20211219130225p:plain

ひざ(thigh_ref.l)

重要!!必ずしもCC3アーマチュアの位置に合わせる必要はなく、間違った方向にまがらないようにすること。ひざはCC3アーマチュアよりもすこし前に出すような感じにするとよい。

f:id:raksul_01:20211219130457p:plain

腕(shoulder_ref.l, arm_ref.l)※正面視でも調整すること。

 ここもひじ関節に注意。画像よりも後ろ(画像上方向)にずらすとよいかもしれません。ボーン位置が適切でないと後で問題が発生しますが、後述するように修正することもできます。

 他のボーンと同様に、指のボーン位置も合わせた方がよいです。

UE4オプション)UE4標準スケルトンに合わせる

 UE4に持っていく場合は、標準スケルトンの仕様上、背骨の数を4つにしたほうがよいです。これをするにはいずれかの背骨(spine)を選択した状態で、Auto-Rig ProのメニューからLimb Optionsボタンを押して数を4にします。これはGoボタンでアーマチュアを生成する際にも設定できるのでそこで4つに設定していれば変更する必要はありません。

 さらに、ツイストボーンも追加した方がよいそうです。これをするには、腕のボーンを選択した状態で、Limb Optionsボタンを押してTwist Bonesを2~4にします。脚に関してはよっぽど左右のねじれが激しくなければ増やさなくてもよいそう。

(備考)Secondary Controllersについて

 なん氏によるブログ記事(AutoRigProの解説:その2 Smart編 - 当たったらどうすんだよ)より、Limb Optionsのほかにもセカンダリコントローラ設定ができますが、TwistコントローラはBlender独自仕様であり、ゲームエンジンにそのままエクスポートはできないためAdditiveのままでもよいそう。

リグの自動生成

 ここまでできたら、Auto-Rig Proのアーマチュアを選択した状態で、Match to Rigボタンを押します。するとリグがアーマチュアに従って自動で生成されます。

f:id:raksul_01:20211219131307p:plain

リグが上手く生成されない場合

 生成されたリグを見ると、脚は真っすぐですが、上腕や下腕のリグはねじれているように見えます。このようなときは肘関節のボーン位置などが原因のことが多いので、 Match to Rigボタンの上のほうにあるEdit Reference Bonesボタンを押してボーンを再度位置修正し、Match to Rigボタンを押してリグを再生成、という工程を繰り返します。

f:id:raksul_01:20211219133209p:plain

f:id:raksul_01:20211219132759p:plain

上は修正前(リグのねじれが激しい)、下は修正後。

自動スキニングする

  所望のリグが生成されたら、オブジェクトモードで最初にアウトライナーからメッシュをすべて選択し、最後にリグをShiftを押しながら3Dビュー上で選択した状態で、スキンメニューにあるBindボタンを押してしばらく待ちます。すると、Auto-Rig Proのリグに従ってメッシュが自動でスキニングされます。なお、Mesh Binding設定にてスキニングのメソッドをHeat MapかVoxelizedから選択することも可能です。

 ゲームエンジンに持っていく場合は「体積を維持」のチェックは外す方がよい。

f:id:raksul_01:20211219141459p:plain

 リグを動かしてみるとAuto-Rig Proのリグに従ってスキニングされていることが確認できますが、CC3のフェイシャルリグは動作しなくなっています。なので、これらを統合する作業に入ります。

Auto-Rig ProのリグとCC3のフェイシャルリグの統合

 まずはCC3のアーマチュアから不要なボーンを削除します。オブジェクトモードでCC3のアーマチュアを選択し、編集モードに切り替えます。

 サークル選択などを使って顔以外のボーンを選択して、Xキー→ボーンを削除します(胸にあるボーンも忘れずに削除)。

f:id:raksul_01:20211219142221p:plain

 オブジェクトモードに戻り、CC3の残ったアーマチュア(フェイシャルリグ)を選択し、Shiftを押しながらAuto-Rig Proのリグを選択し、Ctrl+Jでリグを統合します。統合後、フェイシャルリグがメッシュの内部に隠れますが問題ありません。

 次に、Auto-Rig Proの頭部のリグにCC3のフェイシャルリグが追従するようにします。ワイヤーフレーム表示に切り替えてCC_Base_Headボーン(CC_Base_Facialに隠れてます)を選択し、ボーン設定からc_head.xをペアレントに設定します。

ウェイト修正する

 今回は、髪の毛や服などすべて自動スキニングしたため高確率で修正が必要になります。そもそも髪の毛や服を自動スキニングしない方法もありますが、今回はすべて自動スキニングしたものとして修正の仕方の例を挙げておきます。

 前提として知っておくことは、Auto-Rig Proの命名規則として、プレフィックスのないものは基本、できあがりのスケルトンのボーンとなるもの、"c_"のつくものはコントローラです。なので、ウェイトはプレフィックスのないものにつけていくことになります。

・頂点グループhead.xで首以外を選択してウェイト1.0で割り当て

・首の頂点グループにまつげが含まれていたりするので首以外の部分をウェイト削除

・体メッシュ以外は、それぞれのメッシュに対して頂点グループメニューから「未ロックグループを削除」でOK

※基本的には、最初にロックしたCC3ですでにスキニングされたものだけを残すイメージです。なのでhead.xもすべてウェイト削除でよいかもしれません。

(備考)服のスキニングの別の方法

 こちらのツイートの方法を使えば、服は自動スキニングせずに身体メッシュから転送して対応できそうです。

UE4オプション)UE4-Aポーズにする

 CC3でもエクスポート時にAポーズを指定していますが、ここでいうAポーズとは同じAポーズでもUE4標準に近いAポーズを指します。

 厳密にいえば、Blenderでのリグ&アーマチュア再生成&CC3表情シェイプキー統合(要するに今回の方法)を用いないのであれば、CC3でエクスポートする際にUE4-Aposeを指定することができますが、今回の方法はBlenderで、かつ、AutoRig Proを使うことになるためUE4-Aposeでエクスポートは行わず、通常のAポーズでエクスポートしていることになります。そのため、AutoRig Proの機能を使ってUE4のAポーズに近づける必要があります。
 Set PoseでAポーズを選んでApply Pose at Rest Poseボタンを押した後に、Match to Rigボタンを押すことでUE4のAポーズに近いものとなります(Auto-Rig ProのAポーズはUE4のAポーズに非常に近い)。

(オプション)rootの子ボーンの追加

 rootに子ボーンを追加したい場合は、c_trajにペアレントすれば上手くいった。