PaperSloth’s diary

主にゲーム開発関連についての記事を書きます。

UE4 推しに学ぶMaterial入門

この記事は もなふわすい~とる~む Advent Calendar 2021 - Adventar
12/8(8日目)の記事です。
先日12/7はこまつさんのLooking Glass Portrait用の推しの画像を3D TextureでUnityに召喚する記事でした。
GitHub - troubear/MonafuwaGlass: もなふわすい~とる~む Advent Calendar 2021 12/7(7日目)の記事


環境

UE5.0.0 Early Access 2
UE5を使用していますが、UE4でも同様に動作します。

Texture2D To CubeMap

Material 全体像は以下です
f:id:PaperSloth:20211205021215p:plain

これだけでTexture2DをCubeMapに変換してくれます。
Materialの設定は「Unlit」にして「Two Sided」を有効化しています。

あとは特大Sphereに割り当てるだけで、ミテルゾSkyの出来上がり!
難点としては元々CubeMap想定で作られていない画像をCubeMapに変換するため、画像が伸びてしまってかわいさが半減します。
f:id:PaperSloth:20211205021518p:plain

Mosaic PostProcess

Material 全体像は以下です
f:id:PaperSloth:20211205022629p:plain

Materialの設定としては「MaterialDomain: Post Process」です
あとはこのMaterialをPostProcess Volumeに追加
f:id:PaperSloth:20211207151951p:plain

特大Planeに推しのTextureを割り当てるだけでなんだか意味深な感じになります。やったね!
f:id:PaperSloth:20211207151813p:plain

SphereMaskで穴あき PostProcess

Material全体像は以下2枚です
前半
f:id:PaperSloth:20211207153008p:plain
後半
f:id:PaperSloth:20211207153025p:plain

こちらもMaterialの設定としては「MaterialDomain: Post Process」です
先程同様にMaterialをPostProcess Volumeに追加
f:id:PaperSloth:20211207153106p:plain

特大Planeに推しのTextureを割り当てるだけでまたなんだか意味深な感じになります。やったね!!
f:id:PaperSloth:20211207153251p:plain

RGBずらしPostProcess

Material全体像
f:id:PaperSloth:20211207160437p:plain

シンプルにOffsetXとYのRGBチャンネルに適当な値を入れてズラすだけです。
こちらもMaterialの設定としては「MaterialDomain: Post Process」です
先程同様にMaterialをPostProcess Volumeに追加
f:id:PaperSloth:20211207160528p:plain

特大Planeに推しのTextureを割り当ててそれっぽい絵になったことが確認できました。
f:id:PaperSloth:20211207160614p:plain

おまけ
PostProcessInput0 をRGBに割り当てるだけで以下のようにそれっぽいグレーな絵になりますね
f:id:PaperSloth:20211207154128p:plain
f:id:PaperSloth:20211207154307p:plain

ババーンって感じの集中線のWidget用Material

Material全体像
f:id:PaperSloth:20211207162951p:plain

なんかエイってやってバーンなやつです
Noise作ってLerpで適当な形にくり抜くだけのシンプル構成です

あとはWidgetを作ってWidget内にImageを置いてMaterialを割り当て
f:id:PaperSloth:20211207163133p:plain

LevelBlueprintでWidgetを作成して画面に割り当て
f:id:PaperSloth:20211207163139p:plain

あとはPlayすればババーンって感じになります
f:id:PaperSloth:20211207163441g:plain


Material 入門

ここまでは割とお遊び的なアレです。

ちゃんとMaterialの説明をしていくよ。
UE4のPBRMaterialでよく使う以下のParameterについて
・BaseColor
・Metallic
・Specular
・Roughness
・Emissive Color
・Opacity
・Opacity Mask
Emissive Colorは例外ですが、基本的な考え方としては色情報やParameterは0~1の範囲で扱います。
これはもう一方のUなエンジンでも大体同じですね。
大雑把に言ってしまうと色情報の白が1で黒が0です。
(実際はUE4のBaseColorに1以上の割当をしてしまっても不具合にはなりません。1, 1, 1と同じ結果になるように処理されています)

階調反転

OneMinus(1-x)のノードを使用します。
今回使用しているようなカラー画像に適用するとヒェって結果になりますが
白黒の画像を用意するとわかりやすいですね。
OneMinusはその名前の通りで 1から入力された値を引いたものになります。
f:id:PaperSloth:20211207165105p:plain

色の合成について

Addは色情報の加算
Multiplyは色情報の減算
f:id:PaperSloth:20211207165905p:plain

上記で上がベースのTexture、下がMask用のテクスチャとしています。
黒(0, 0, 0)にベースのTextureが加算されるとベースのTextureの色がそのまま出力されます。
逆に白(1, 1, 1)にベースのTextureを加算してもBaseColor的には1, 1, 1になります
f:id:PaperSloth:20211207170325p:plain

Emissiveの場合は若干光ります
f:id:PaperSloth:20211207170406p:plain


次にMultiply(乗算)を行った場合ですが
この場合は白(1, 1, 1) x ベースTextureではベースTextureの色がそのまま出力されます。
逆に黒(0, 0, 0) x ベースTextureでは0 と掛け合わせているため、黒(0, 0, 0)が出力されます。

これがShaderでMaskする際や色計算をする際の基本になります。

Subtract(減算)については、Multiply(乗算)と逆の結果になります。
f:id:PaperSloth:20211207201107p:plain

また、SubtractしてOneMinusをするとAddと逆の結果になります。
f:id:PaperSloth:20211207201245p:plain


おまけ
Maskした範囲に色を乗せる例
f:id:PaperSloth:20211207201506p:plain

色をAddする際にTextureを割り当てて別のMaskと加算といったこともできます。
f:id:PaperSloth:20211207201756p:plain

0 ~ 1で収めるということについて

先程の画像でさらっとsaturateが登場しています。
このノードは入力された値を 0 ~ 1の範囲に収めるというものです。
例えば、R: -1, G: 100, B: 0のような色があった場合に 0 - 1の範囲に収めて
R: 0, G:1, B: 0といった結果になります。

saturateとClamp(in, 0, 1)は同じ結果です。
f:id:PaperSloth:20211207202043p:plain

0 - 1の範囲で計算が行われるのがベースということを踏まえて
R:-1, G:100, B:0 に対してsaturateを行った後にOneMinusを行えば
R:0, G: 1, B: 0からR: 1, G:0, B:0になります。
f:id:PaperSloth:20211207202318p:plain

色の合成についてのまとめ

Material(Shader)には他にもUVをこねこねしたり、頂点シェーダーをこねこねしたり、Timeを活用したり
語るべきことは沢山あるんですが、基本としては上記の原則のように0~1の範囲で色が表される
ということを抑えておけばいいかと思います。
この色をこねこねするということ、0 - 1の範囲で値を計算するということについてはもう一方のUのエンジンでも基本的には考え方は同じです。

おまけ。Timeを活用した例
f:id:PaperSloth:20211207202902g:plain
f:id:PaperSloth:20211207202932p:plain

まとめ

PostProcess多めであんま画像関係ないじゃん!って感じになってしまった( ´∀`)
かわいいからヨシッ!

※穴開けに関して、昔見かけたツイートをそのまま記事にしたような感じなんですが、誰のどのツイートか忘れてしまった……

推しをLooking Glass Portraitに召喚する方法

この記事は もなふわすい~とる~む Advent Calendar 2021 - Adventar
12/5(5日目)の記事です。

はじめに

こんなこともあろうかと(?)巻乃もなかさんがLooking Glass Portrait(以下LGP)用に画像データを用意してくれています!(かわいい!やったー!)
www.fanbox.cc

環境構築

LGPに画像を転送するには、「HoloPlay Service」と「HoloPlay Studio」をダウンロードする必要があります。
以下のURLからDLすることができます。
DLをするにはアカウントが必要なので、登録をする必要があります。
Looking Glass Factory. The World's Leading Holographic Display Company.

HoloPlay ServiceはHoloPlay Studioを起動する際に必要で
HoloPlay StudioはLGPに画像を転送する際に使用します。
HoloPlay Serviceを起動していない状態でHoloPlay Studioを起動すると以下のようにエラーが出ます。
f:id:PaperSloth:20211205004357p:plain

HoloPlay Studioを使ってみる

まずは巻乃もなかさんのFANBOXからLGP向けの画像をDLします。
あとはHoloplay StudioにD&Dもしくは、右上の「ADD HOLOGRAM」から画像をImportします。
f:id:PaperSloth:20211205002659p:plain

続いて、Importする際のFile Formatを「Quilt Photo and Video」にします。
f:id:PaperSloth:20211205002918p:plain

次にImportしたファイルを選択してPropertyの設定を行います。
今回はいずれの画像も「Columns: 8」「Rows: 6」ですね。
f:id:PaperSloth:20211205003200p:plain


さて、ここでSYNC PLAYLISTを押下して同期!!
同期中
f:id:PaperSloth:20211205005055p:plain
同期完了
f:id:PaperSloth:20211205005106p:plain

再生できた!やったー!かわいい!!
f:id:PaperSloth:20211205005423j:plain

PlayListを同期したあとはHDMIケーブルを抜いても再生ができますので、USB-Cで給電さえできていればいつでも見れます!

まとめ

推しがmy new gearで喜ぶ可愛い姿を見てくれ

UE5 起動から初めの1歩 Lumen/Naniteを体験してみよう

環境

UE5.0.0

はじめに

UE5のEarly Access について以下のdocに対象ユーザーの説明があります

Unreal を初めて使用されるユーザーの方は、UE5 が製品版としてリリースされるまでは、まずは、UE4 で学習することをお勧めします。

Unreal Engine 5 早期アクセスへようこそ | Unreal Engine ドキュメント

理由としては大きく2点挙げられます
1. UE5はUE4と比較して公式の学習資料がまだ充実していない
 リリースされたばかりなので、そのとおりですね
 これによって困る点として初学者の方が躓いた際に
 エンジン側の問題なのか実装上の問題なのか調べてもヒットしにくく
 何かを始めようと思った際に資料が少なくて手詰まりになってしまう等があげられます

2. 新機能やワークフローが変更される可能性がある
 UE5はまだEarly Access段階ですので、UIが変わったり致命的な変更が発生する恐れもあります
 仕事で既にプロトタイプを作成されている方などであれば、そこを理解しているので何も問題がないとは思いますが
 初学者の方でこの状態にハマるとどうやって同じ機能を実現するのかが分からなくなったりと
 コンテンツ作成外の分野で詰まってしまって時間がもったいないです
 そのため、先ずはUE4を学習するか上記を理解した上で両方に触れられるのが良いでしょう。

UE5について

UE5はEarly Access と書かれているように
まだ正式リリースされたものではありません。
そのため、以下の公式ブログにあるように実プロダクトではまだ利用すべきではないです

この早期アクセスビルドは新機能をテストして、将来のゲームのプロトタイピングを開始したいと考えている最先端を目指すゲーム開発者に向けたものです。

さて、気になる正式リリース日ですが
そちらについても下記の公式ブログに記載があります
2022年初頭を予定されているようですので、ちょうど1年先くらいになるでしょうか。

すべての業界のクリエイターを助ける追加の新機能を含むフルリリースは 2022年初頭に行いたいと考えています。

Unreal Engine 5 の早期アクセスがリリースされました! - Unreal Engine

UE5をインストールしてからやること

やること というと少し乱暴な口調ですが
UE5をインストールしてみたけど、何から手を付ければいいか分からないという方に向けて助けになればと思います。

先ずは何事も公式doc を参照するのが一番ですね
EGJ(Epic Games Japan)のローカライズチームの方々の仕事は本当に早く
既に日本語のドキュメントが用意されています
Unreal Engine 5 早期アクセス ドキュメント | Unreal Engine ドキュメント

次に道標となるのはOnlineLearningとなるかと思います。
現在2つのコースが用意されています。
先ずはUE4をこれまでに触れてきた方やUE4でプロジェクトを既に作成されている方向けですね
UIや機能など、従来のUE4からUE5に向けての変更点について学ぶことができます
UE5 早期アクセスへのアップグレード - Unreal Engine

次にUE5のQuickStartです
エディタの概要やパッケージ作成方法等を学ぶことができます
UE5 早期アクセス クイックスタート - Unreal Engine

UE5のインストール方法についてはヒストリアさんのブログが手助けになるでしょう
[UE5] Unreal Engine 5の導入手順|株式会社ヒストリア

UE5を起動した!次は?

まずはUE5の大きな更新内容から見ていきましょう
Unreal Engine 5 早期アクセス リリースノート | Unreal Engine ドキュメント
よく注目されているものとしては下記があげられます

  • Lumen による動的GIおよびReflections
  • Nanite によるVirtualized Geometry
  • 次世代Shadow Virtual Shadow Maps
  • Temporal Super Resolution
  • World Partition
  • Full Body IK Plugin
  • Motion Warping
  • MetaSound
  • Chaos Physics

...etc

今回はこの中でもお手軽に体験できるLumenとNaniteについて紹介させていただきます。

まずはUE5を起動していつものようにThirdPersonTemplateでProjectを作成します
f:id:PaperSloth:20210608120300p:plain

Lumenを使ってみよう

実はUE5を起動した段階で、何もしなくてもLumenが有効になっています。
まずは設定の確認から
「Edit -> Project Settings... 」から設定を開きます
f:id:PaperSloth:20210608125817p:plain

設定内の「Engine / Rendering -> GLOBAL ILLUMINATIOON | REFLECTIONS」内で
Dynamic GIとReflectionでLumenが選択されています。
f:id:PaperSloth:20210608125904p:plain

早速LumenのDynamic GIの機能を見てみましょう
f:id:PaperSloth:20210608130105p:plain
「Create -> Shapes -> Sphere」で適当な球体をLevel上に配置します

続いてContentDrawer内で新規にMaterialを作成します
f:id:PaperSloth:20210608130234p:plain

名称は「M_EmissiveSphere」としました。
Material Editorを開いたら「V + 左Click」で
新規に「Vector Parameter」のノードを作成し、「EmissiveColor」と名付けました
f:id:PaperSloth:20210608130413p:plain

そのまま「Emissive Color」につなぎます
f:id:PaperSloth:20210608130441p:plain

「EmissiveColor」ノードを選択した状態で
Details Panelからデフォルト値を「10, 7, 0, 1」に設定しました
f:id:PaperSloth:20210608130605p:plain

ここで一旦このMaterialを保存して閉じます。

Level Editorに戻って、Sphereを選択した状態で先程のMaterialを割り当てます。
emissive で検索をかければ出てくるため、こちらをSphereに割り当てます。
f:id:PaperSloth:20210608130752p:plain

この段階でも既にLumenの恩恵を受けれているのですが
もう少しいじっていきます
f:id:PaperSloth:20210608130843p:plain

Level上の床に置いてあるFloorをDuplicateして天井を作成します。
Floorを選択した状態で「Alt」を押しながら床を移動させるとDuplicate(複製が可能です)
このまま上に移動して天井にします。
f:id:PaperSloth:20210608131215g:plain

再度Sphereを選択して「Simulate Physics」にチェックを入れると
物理が有効になって球がコロコロと転がるようになります
f:id:PaperSloth:20210608131335p:plain

f:id:PaperSloth:20210608131631g:plain

これだけ見てもイマイチLumenの機能が分からないという方も多いでしょう
そこで先程のProjectSettings内のLumenをNoneに変更してみましょう
f:id:PaperSloth:20210608155154p:plain

先程と大きく結果が変わることが確認できました
f:id:PaperSloth:20210608155241p:plain

なんだか明るいですね。
こちらはLighting Buildが行われていないのでこのような結果になっています。
Build All Levels でビルドをすると以下のような暗い画面(正しい結果)が得られます
f:id:PaperSloth:20210608155652p:plain
f:id:PaperSloth:20210608155749p:plain

同様のLevelをUE4.26で作成したものが以下になります
f:id:PaperSloth:20210608155856p:plain


Dynamic GIの効果によって、EmissiveのMaterialの光り方が大きく変わるのが見て取れたと思います。

以上、大変簡潔にでしたがLumenについて触れてみようという内容でした。
コーネルボックスを作ってみたり、暗闇の中で光を頼りに進むタイプのゲームなど色々作ってみてはどうでしょう。

実際にはDynamic GIによって変わるものというと、Emissiveだけでなく
SkyLightの遮蔽によって屋内のライティングがよりリアルに近しいものになったり
ライトの照り返しが別のオブジェクトにリアルに反映されたりと
Emissive以外にも様々な描画結果の違いを得ることができます。

Naniteを使ってみよう

Naniteを使用する前に、まずはQuixel Bridgeの準備を整えようと思います。
UE5にQuixel Bridgeをインストールしましょう
インストール方法はLauncherからQuixel Bridgeを検索してUE5にインストールするだけです。
f:id:PaperSloth:20210608162250p:plain
f:id:PaperSloth:20210608162306p:plain

続いてUE5 Editorを立ち上げて、Pluginsを開きます
f:id:PaperSloth:20210608162526p:plain

Installed タブ内のBridgeのEnabledにチェックが入っていれば使用準備が整いました。
f:id:PaperSloth:20210608162634p:plain

Quixel Bridgeの使用方法はContentから呼び出すか
f:id:PaperSloth:20210608162714p:plain

Content Drawerから呼び出すことができます
f:id:PaperSloth:20210608162747p:plain

適当なAssetを選択してDLすると
Content/Megascans 以下にアセットが追加されます。

今回は適当な岩を持ってきました
f:id:PaperSloth:20210608163203p:plain


前置きが大変長くなりました。
ようやくNaniteの出番です。
まず、今回DLしたアセットのデータを確認します。
以下のようなMeshデータです。
Triangles : 4606
Vertices : 3141
f:id:PaperSloth:20210608163320p:plain
f:id:PaperSloth:20210608163313p:plain

このMeshに対してNaniteを有効にします。
Detailsタブ内のNANITE SETTINGS からEnabledにチェックを入れて
Apply Changes を押下します。
するとMesh情報が以下のように変更されました。
Nanite Enabled
Triangles : 1999
Vertices : 1504
f:id:PaperSloth:20210608163441p:plain
f:id:PaperSloth:20210608163451p:plain

3角形ポリゴンの数が半数以下になりましたが、スクリーンショットを比較した限りでは大きな遜色も見られません。

とても便利なNaniteですが、1点注意点があります。
Naniteは現在Masked Material には対応しておりません。

そのため、Naniteを有効にする前にMaterialのBlend ModeがOpaqueかどうかを事前にチェックされることを勧めます。

まとめ

本当にふわっと触りだけでしたが、ざっくりとLumenとNaniteについて触れていきました。
UE5は今後のアップデートも楽しみで魅力的な機能に溢れています。
ですが、最初にも述べたようにこれからUnreal Engine に触れてみようと思っている方には
まずはUE4Unreal Engineの文化に触れてもらうのが良いかなと思います。

多少UI等に変更はあるものの、UE4.26で作成したProjectはUE5に移行することも可能ではありますし
ベースとなるエンジンの根幹の考え方、BlueprintやMaterial等についての知識が流用できます。

逆にUE4に既に詳しい方にはどんどんとUE5に触れていただいて
最新のアップデート情報を広く共有いただけるとUE5ユーザーみんながハッピーになります!

ざっくりとでしたが、以上です。

おまけ

Lumenの効果がより分かるGifを用意しました

  • 変更点

・球を置いたLevelから球を削除
・SkyLightのIntensity Scaleを1.0 -> 10.0 に変更
f:id:PaperSloth:20210608171349g:plain

UE4 オンラインラーニングコースの紹介 初めてUE4を触る人向け

Unrealオンラインラーニングコースとは

Unrealオンラインラーニングコースとは実習形式のビデオで観ながら実際に手を動かしてUE4を学ぶことができるラーニングコースになります。
www.unrealengine.com

このオンラインラーニングコースの良い点として以下が挙げられます。
1. 無料
 なんとUnrealオンラインラーニングコースは全て無料です。
 Udemy等で販売されていてもおかしくないようなものがいくつもあり
 それらを無料で学ぶことができます。

2. 興味のある分野だけピックアップして学べる。
 ゲームエンジンを新しく覚える時に何から手をつけていいか分からない人や
 特定の機能について学びたいとは思ってはいるものの
 公式ドキュメントだけでは理解ができなかったという人にオススメです。
 また、中上級者の方でも意外と知らなかったという機能や
 理解が間違っていたという気付きも得られるかもしれません。

3. 手を動かしながら学べる
 講演資料や公式ドキュメントを見たり読んだりして
 分かった気になっていたという部分でも
 実際に手を動かすことによって、より理解が深まります。

4. 日本語の字幕が付いているので英語が理解できなくても大丈夫
 これはかなり嬉しいポイントですね。
 ゲームエンジンに限らず、様々なDCCツールの動画は英語が多めですね。
 ですが、Unrealオンラインラーニングは日本語字幕が付いているので
 英語が聞き取れないという方も安心して学べます。

実は2018年1月頃からこのオンラインラーニングコースは存在していたのですが
現在では日本語字幕付きの動画がどんどん出てきており、今も更新され続けています。



Unrealオンラインラーニングコースへのアクセス方法

UE4のHPの一番上にあるメニューから
「ラーニング&サポート」->「オンラインラーニング」でアクセス可能です
Online Learning Courses - Unreal Engine


もしくはEpic Games Launcherを起動して
「Learn」タブに切り替えて「Unreal Online Learning」からもアクセスできます
f:id:PaperSloth:20210219144924p:plain

Launcherの言語設定を日本語にしている場合も同様に
「ラーニング」の「Unreal Online Learning」からアクセスできます。

今回は「Unreal Engine 最初の1時間」と「Unreal Engine入門」をやってみました。

Unreal Engine 最初の1時間 (UE4.22)

www.unrealengine.com

f:id:PaperSloth:20210319010212p:plain
UE4.22と少し古いものでプロジェクト作成画面にいくつか違いがありますが
解説される内容の多くは現在のUE4.26でも同じように操作できます

このチュートリアルでは1時間という短時間の中でEditorの立ち上げから
Editor内の基本的な要素の解説、Editor操作を学ぶことができます。
ゲームエンジンを触るのが初めてだという人には特にオススメですし
UE4自体が初めてだという人にも新しく学べることが多く存在するでしょう。
UE4をインストールしたけど学び方がよく分からないという人は多いです。
空いた時間にこちらのチュートリアルを触ってみるのもオススメです。

このラーニングでは大きく分けて以下のことが学べます。
既に全部知っているという人も動画を見てみると新しい発見があるかもしれません。
1. Epic Games Launcherの概要
2. Editorの起動/プロジェクトの作成方法
3. Content Browserの操作方法
4. Editor(Viewport)上でのカメラ操作、一部のショートカットキー
 因みにViewportの視点位置のブックマーク機能はここで初めて知りました
 Ctrl + 1 / 2... : Viewport視点のブックマーク
 1 / 2... : 保存したブックマーク先への切り替え
5. Editor内の各種Windowの紹介
6. Starter Contentの紹介
7. Marketplaceでの無料アセットの入手/プロジェクトへの追加方法
8. プロジェクト間でのアセットのMigrate(移行)方法
 ゲームジャムやモック作成等、よく使う操作なので覚えておくと便利です
9. 新規に空のレベルを作成/追加したアセットの利用
 アセットのSnap機能などは覚えておくとLevelの調整が大変楽になりますね
 同様にDuplicate(複製)機能も大変重宝します
10. 新規レベル内でMesh/Light/Player Startの配置
11. ビジュアルの調整、Content Browserのフィルタリング
  Fog(霧,空) / Reflection(反射) の追加
12. ビジュアルの本格的な調整
  空 / Sky Light / Light Shaft の追加
  Sky LightによってDirectional Lightだけでは暗いエリアも
  明るくすることができ、ゲーム/CGっぽい違和感を軽減できます
  Light Shaft の追加によってGod Ray の表現が可能になります
13. Actor/Blueprintの説明
  ActorはUE4で多くのアセットに共通するもので重要な概念です
  ここではActorを継承したBlueprintを使用して
  炎を灯した装飾物を作成しています
  Blueprint内ではライトの強度を一定規則で
  ランダムに変更させる機能を作成しています
14. Lighting情報のBake
  よくEditorの左上に「LIGHTING NEEDS TO BE REBUILT...」もしくは
  「ライティングを再ビルドする必要があります...」と
  表示されているスクショなどを見かけますが
  このエラーメッセージはライティングのビルドで解決できます


Unreal Engine入門 (UE4.18)

www.unrealengine.com

f:id:PaperSloth:20210319010227p:plain
先程の Unreal Engine 最初の1時間 では
基本操作をLevelとActorを通して学びました。
こちらのチュートリアルでは
より深いEditorの基本操作や見方についてを学びます。

これを2つめのラーニングとして行うのがよいかというと難しいところですが
いずれも覚えておいて損はない機能ですので
時間がある時に見ておくと良いかと思います。

このラーニングでは大きく分けて以下のことが学べます。
1. Editorの全体像
 Mode Panel, Main Toolbar, Viewport, World Outliner, Detail Panel, Content Browser
 Editor Layoutの初期化方法等
2. Viewportの操作
 カメラのブックマーク方法やViewportの外観の切り替え方法(Lightingなし/Wireframe表示等)
 GameView, Immersive Mode, PostProcessの表示/非表示切り替え等
 UE4の操作に慣れた人でも知らない機能がいくつかあると思います。
 特にカメラの移動速度の変更方法は覚えておくと便利です。
3. LevelEditor上のActorの操作
 World / Local Spaceの切り替えやSnap機能を利用したActorの移動等
 複数軸を選択した移動等については知らなかったという人もいるかもしれません。
4. World Outlinerの操作
 Level内のActorの管理をする上で重要な要素になってきます。
 特に大きなLevelを作成する上では管理のために
 適切なフォルダ分けが必要になってきます。
 チーム作業ではもちろん、個人でもある程度のルール決めをしておくと
 作業をする上でActorを探したい時に便利になるでしょう。
 名前での検索以外にもActorの種別に応じてフィルタリングができたりと
 実は便利な機能がいくつかあります。
 また、Actorのグループ化はModular Assetを管理したい場合など
 実作業でも役立つ事が多いかと思います。

 ※Modular Asset については下記のスライドが大変分かりやすいです。
 UE4背景アーティスト勉強会(前編) 背景ワークフロー解説
  オープンワールドのゲームや複雑なビルの作成
  はたまた背景用の車のバリエーションを増やしたい場合など
  活用されるシーンは多くあり
  UE4のMarketplaceにもこういったAssetも売られています。

5. Detail Panelについて
 選択したActorの座標/回転/拡縮や
 コンポーネントの追加やMaterialの変更等
 Level上で変更する多くのParameterをこちらで変更することになります。
 余裕があればProperty Matrixの使い方も覚えておくとよいでしょう。
6. Mode Panelについて
 Mode Panelについては詳細まで説明すると
 それだけで1本動画になるほどなのでここでは触りだけになっています。

 ※Mode PanelはUE4.26ではToolbarに統合されています。
  基本的にはUE4.18とUE4.22同様に
  Place/Landscape/Foliage/Brush Editing/Mesh Paintと共通です

7. Content Browserについて
 フォルダの色分けができるというのは知らなかったという人もいるかもです
 アセットのカテゴリごとに色を分けたり
 検証用と本番用のデータで色を分けたりと色々と使い道があるかと思います
 検証用についてはDevelopersフォルダを使うかもですが。
 Column Viewは各フォルダやアセットの詳細情報を見たい時などに便利です

 また、Engine ContentはUE4側に既にImport済のアセットが豊富で便利です
 ですが、Engine Contentは間違って更新をしないように
 開発用のプロジェクトのフォルダにDuplicateして使用するのが推奨です
 また、thumbnailの回転ができたりと意外と知られていない機能があります
 他にもコレクション機能など便利な機能が豊富なので
 これらの操作方法は覚えておいて損はないでしょう。

8. Main Toolbar について
 この中でもSettings から右側のボタンは特に使う機会が多いでしょう。
 例えば、Settings にはEditor を軽量化するための設定項目もあります。
 papersloth.hatenablog.com
 他にもLevel BlueprintやCinematics(Sequencer)や
 Lighting BuildやGame Playに関する設定や
 Launch(パッケージングに近い実行形式)等があります。
 PlayメニューからVRモードやNetwork対応のテストも出来るのも強みですね

9. Editorの設定関連全般
 Editor Preference(エディタの環境設定)
  Editorの色やショートカットキーの設定など
  使用しているUE4のバージョン毎に設定が保存されるため
  プロジェクトを切り替えた場合でも変更が適用されます
 Project Settings(プロジェクト設定)
  動作させるPlatformやCollisionや入力や
  パフォーマンスやRendering設定などゲーム全般で重要な設定があります
  これらはプロジェクト固有の設定になります
  ゲーム開始時のLevelやNetwork関連の設定など
  ゲームをリリースする際には必須の設定項目がいくつかあります
 World Settings(ワールドセッティング)
  Engine側で自動的にActorを破棄する高度や
  GameModeの設定やLightmassの高度な設定など
  Levelに紐付いたGameModeの設定なんかは特に重要です
  頻繁に使用するものではないですが覚えておいて損はないでしょう

まとめ

まず大前提としてラーニングは動画を見つつ作業を行えた方が良いため
PCモニターは最低でも2枚以上あった方が良いです。
これに関してはどの動画教材でも同じですね。

どのチュートリアルも時間がかかって大変な印象を受けるかもしれませんが
章区切りで中断もできるため、一気にやるのが大変な時は
少しずつ進めてみるのも良いかもしれません。

入門は大丈夫という方は自分の気になる技術トピックを探ってみると
新しい発見があって楽しいかもしれません。
もちろん、知ってるつもりになっている分野の復習にもよいでしょう。
実際、私もこの2つのチュートリアルで知らなかった機能がありました。

是非ともラーニングを進めてみてSNS等でも布教してもらえればと思います。
以上です!

UE4 Blueprintで使える便利なフロー制御のノードについて

環境

UE4.26.0

概要

Blueprintにはデフォルトで用意されているノードにFlipflop, Gate, DoN, MultiGate等の便利なノードがあります。
C++で同じような処理を組む際には面倒なものでも、こういったノードを上手く使えば簡潔に処理を書くことができます。
今回紹介するのは以下のノードです。
f:id:PaperSloth:20210113232832p:plain

Flipflop

f:id:PaperSloth:20210113175149p:plain
実行される度にA, Bの処理を交互に実行する。
簡単な例でいうとドアの開閉処理や、ボタン操作等が分かりやすいかもしれません。

例で組んだノードではEnterキーを押下する度に「Open」と「Close」のログが出力されます。
f:id:PaperSloth:20210113173608p:plain

最初にEnterキーを押下した場合には「Open」が出力され
次にEnterキーを押下した場合には「Close」が出力されます。
さらにもう一度Enterキーを押下した場合には「Open」が出力されます。

こういったようにFlipflopノードに繋いだ処理をAの出力とBの出力が交互に実行されるわけです。
例えば、デバッグ用に録画開始ボタンと録画終了ボタンを設定しておくなどの使い方もできます。
f:id:PaperSloth:20210113174217p:plain

この方法で撮影した動画はProjectのDirectoryの Saved/VideoCapture/(ProjectName).avi の形式で保存されます。

Flipflopを使用せずに同じ処理を組もうとした場合には以下のような組み方になります(IsCaptureのdefault値はfalse)
Flipflopを使用した場合と異なるのはbooleanの変数を1つ追加する必要があることですね。
極力Blueprintを複雑にしないためにも、削減可能な変数は削減したいところです。
f:id:PaperSloth:20210113174615p:plain

Gate

f:id:PaperSloth:20210113175308p:plain
Enter : GateがOpen状態なら処理が実行される
Open : GateをOpen状態にする(Enterに処理が来た時に処理が実行される状態になる)
Close : GateをClose状態にする(Enterに処理が来た時にClose状態では処理が実行されない)
Toggle : Open <-> Close状態を切り替える
Start Closed : デフォルトのGateの状態をClose状態にするかどうかのフラグ

ちょっぴり複雑なノードが出てきました。
挙動としては上記に書いたように、Enterに処理が来た時にOpen状態ならExitに繋いだ処理が実行され、Close状態なら処理が実行されないといったシンプルなものになります。
Gate(入り口、門)という名前の通りで門が開いている時には処理が行われ、閉じている時には処理が行わないというものです。


例 : 右クリックを押下している時だけ回転するカメラの実装
今回の使用例では右クリックを押下している時にだけしか回転しないカメラを実装しました。
f:id:PaperSloth:20210113214123p:plain

MouseXノードはMouseを動かしている時、そうでない時に関わらず前フレームからのマウスの横方向への移動量を返します。
Tickのように毎フレーム処理される入力ノードです。
そこにGateを組み合わせて右クリックを押した時に開いて離すと閉じるようにしています。
こうすることで、右クリックを押している時だけ、AddControllerYawInput(カメラの左右方向の回転)が呼び出されます。

GateはTimelineやTickと組み合わせることが多いかと思います。
一定のボリュームの中でだけ動作する機能や、一定の入力を行っている時だけ動作する機能などを簡単に実装することができます。

DoN

f:id:PaperSloth:20210113205010p:plain
Enter : Nに設定した回数が残っていればExitに繋いだ処理が実行される
N : 実行可能な最大数
Reset : Nで指定した値でCounterをリセットする
Exit : 実行したい処理を繋ぐ
Counter : 実行された回数(1,2,3と増えていくため実行可能な残り回数ではない)
     また、Resetした際にCounterもResetされます。

一定回数だけ実行可能な機能を作成したい場合に使用するノードです。
勘違いしがちなのは、DoNでNに指定した回数連続で処理が実行されると思うかもしれませんが
そういった機能ではありません。

回数制限を加えた処理を作成したい時などに使えるノードになっています。
例1. 一定回数だけ取得が可能なイベント(某ランゲームのコインが取得可能なブロックのイメージ)
例2. 一定回数攻撃を加えることで破壊可能なオブジェクトの破壊処理
f:id:PaperSloth:20210113230737p:plain

MultiGate

f:id:PaperSloth:20210113205025p:plain
入力 : デフォルトでは、入力は順番に機能し、すべての出力が終了すると、機能は実行されません。
Reset : StartIndexで指定した数値に初期化されます。
Is Random : 出力をランダムに実行します。
      Loopのフラグが立っていない場合は、すべて実行すると機能しなくなります。
Loop : 全ての実行が終了した後も再度実行可能になります。
Start Index : 関数の最初の出力を示すIndex。-1の場合でLoopが立っていない場合は上から順次実行します。

例:カメラを3つ順次切り替えたい場合
まずはLevel上に下図のように3つカメラを配置します。
f:id:PaperSloth:20210116163146p:plain

スクショで1画面に収める都合でノードの繋ぎ方が汚いですが
以下のようにMultiGateを使用してLoopにチェックを入れることでカメラ1 -> 2 -> 3 -> 1 ...と切り替えることができます。
f:id:PaperSloth:20210116163615p:plain
f:id:PaperSloth:20210116163809g:plain

Loopフラグを使わない場合でも以下のように最後の処理が実行された後にResetに繋ぐことでLoopを組むこともできます。
挙動としては先程と同様です。
f:id:PaperSloth:20210116163921p:plain

Randomにチェックを入れた場合には以下のような挙動になります。
ただし、Randomの実行結果としてOut0 -> Out0のように同じ出力を行うケースも存在するため
使用する際にはその点に留意してお使いください。
f:id:PaperSloth:20210116164229g:plain

まとめ

上記で説明した以外にBlueprintには便利なノードが数多く存在します。
今回の例でいうとGateやMultiGate等はC++で組むとなるとちょっと面倒くさいです。
Flipflopに関してはC++でも楽ですが。
また、Blueprintでの利点としてはMultiGate等のように出力数を簡単に増減できるところも魅力的ですね。
既存のノードを頭の片隅に入れておいてより読みやすいノードの流れが組んでいけるといいですね。

以上です。

UE4 Editor軽量化 改訂版

Unreal Engine 4 (UE4) Advent Calendar 2020 - Qiita の19日目の記事です。

環境

UE4.26.0

PC Spec
RAM : 64GB (65448 MB)
CPU : AMD Ryzen 5 3500 6-Core Processor (6 CPUs), ~3.6 GHz
GPU : GeForce RTX 2070
Display Size : 1920 x 1080
4Kモニターを使用してますが、PBPで1920 x 1080でEditorを立ち上げています

概要

UE4が一般公開されるようになった5年ほど前と比べてUE4 Editor自体は随分と軽くなりました。
それでも、ラップトップで作業されている方やどうしてもPC Specにはお金をかけれないという人向けに本記事を書くことにしました。
いくつか情報を出してくださっている方がいるため、それらをまとめたものにはなります。

検証環境
今回は新規にThird Person Templateを使用したプロジェクトを作成しています。
・プログラミング : Blueprint
・Quality : Maximum Quality
・Raytracing : Disabled
・Target Hardware : Desktop / Console
・Starter Content : No Starter Content
f:id:PaperSloth:20201218193315p:plain

Editorの軽量化について

EditorFPS表示

まずはEditorの実行速度を確認するためにEditorのFPSを表示します。
Edit -> Editor Preference -> General -> Performance内の
「Show Frame Rate and Memory」から有効化できます。
f:id:PaperSloth:20201218193002p:plain

有効化するとEditorの右上にFPSが表示されます。
※今回は検証用に最大FPSを300にしています。
FPSの変更方法については後ほど

f:id:PaperSloth:20201218195208p:plain
この段階で180 fpsほど出ています。

Realtimeを切る

次にEditorのViewportのRealtimeをOFFにします。
Ctrl + RもしくはViewport左上のメニューからViewport Optionの「Realtime」をオフ
無効化するとViewportに「Realtime : Off」と黄色く表示されます。
f:id:PaperSloth:20201218193603p:plain

これをOffにしただけで200 fpsほどになり、かなり早くなりました。
動くものが多ければ多いほど高速化されることになります。
f:id:PaperSloth:20201218195357p:plain

Third Person Templateで分かりやすい部分でいえば画面中央の「?」のアイコンの回転が止まりました。
このFlagを切ることによってスクロールするMaterialや移動するActorなどの更新を止めることになります。
空も動いていることが多いため、そこそこの効果が見込めるかと思います。
特に動くものがない場合はデフォルトで切っておいてしまってもいいかもしれません。

Realtime Thumbnailオフ

次にContent Browser内に表示されるMaterial等のRealtime Thumbnailを切ります
Content Browser内の右下の目玉アイコン(View Options)から
「Real-time Thumbnails」をオフにします。
f:id:PaperSloth:20201218195003p:plain

こうすることで回転や移動を行うMaterial等のThumbnail表示のリアルタイム更新がストップします。

これで210 fpsほどになりました。
スクショのタイミング問題もあるため、実際にはそこまで大きな効果がないとは思いますが多少軽量化されます。
f:id:PaperSloth:20201218195526p:plain

Background CPU

続いてBackgroundにある際のCPU更新頻度を下げるオプションについてです。
Edit -> Editor Preference -> General -> Performance内の
「Use Less CPU when in Background」のフラグをONにすると有効になります。
f:id:PaperSloth:20201218195821p:plain

このフラグを有効にすることでEditorを操作していない時のEditorの更新頻度を大幅に下げることができます。
フラグが無効な場合
何の操作をしていなくとも90 fpsが出ており、それなりにCPUパワーが持っていかれます。
f:id:PaperSloth:20201218195914p:plain

フラグが有効な場合
フラグを有効化すると10 fps以下まで落とされ、Editorを操作していない時のCPUへの負荷が大幅に軽減されます。
ラップトップ等で直ぐに熱を持ってしまうという方は有効化しておくと調べ物をする時などに負荷を減らせるかと思います。
f:id:PaperSloth:20201218200030p:plain

Rendering品質を落とす

この変更は見た目に影響を及ぼしますが、大幅に軽量化できるかと。
Settings内の「Engine Scalability Settings」から設定項目が開けます。
「Auto」を押下することで、PCに合ったQualityに設定してくれます。
Low等、PC Specに応じて変更してみると良いかと思います。

同様にMaterial Quality Levelの方も変更してみても良いかもしれません。
f:id:PaperSloth:20201218200824p:plain

手元の環境ではGPUがそこそこのものなので、大きな変更はなかったです。

Mobile Rendering Preview ON

さらに別途Renderingの設定を変更していきます。

プロジェクト作成時にTarget Hardwareを「Desktop / Console」にしていました。
Rendering設定をMobile向けに変更します。

先程同様にSettings -> Preview Renderig Levelを「Android ES 3.1」に変更します。
Shader Compileが結構な量走るため、実行する際は時間がある時に行うことをオススメします。
f:id:PaperSloth:20201218205115p:plain

変更が完了するとSettingsの隣に「Android ES 3.1」のアイコンが出てきます。
f:id:PaperSloth:20201218211438p:plain

こちらもGPU都合で手元の環境では大きな変化はなかったですが
人によってはすごく効果があるかと思います。

t.MaxFPS

Output Logか実行時にUSキーボードだと「`」JISキーボードだと「@」でConsole Command が入力可能です。
f:id:PaperSloth:20201218211750p:plain

ここのConsole Command入力画面に
「t.MaxFPS (任意の最大FPS値)」を入力することでEditorの最大FPSを抑制することができます。

記事の冒頭で最大FPSを300 に設定していたのもこのコマンドです。
UE4のDefault設定では120 fpsが設定されているかと思います。
この値をPC Specに応じて30 fps 等まで下げることで随分と軽量化されると思います。

PIEの解像度を落とす

PIEとはゲームを実行する際に別Window として立ち上げるPIEという機能です。
Playの「New Editor Window(PIE)」から立ち上げることができます。
f:id:PaperSloth:20201218212137p:plain

こちらの解像度の設定はPlay方法の変更と同様にPlayの横のOptionから
「Advenced Settings」を開きます。
f:id:PaperSloth:20201218212546p:plain

するとEditor PreferenceのLevel Editor -> Play の部分が開かれます。
この中の「Game Viewport Settings」の「New Viewport Resolution」からPIE時の解像度の変更が可能です。
デフォルトでは1280 x 720ですが、解像度を下げることで負荷の削減が可能ですので
テストするにあたって許容可能な範囲で下げてみるのも手かもしれません。
f:id:PaperSloth:20201218212724p:plain

EditorのViewport解像度を落とす

最終手段ですが、効果はあります。
デフォルトでは大体これぐらいのViewportサイズになっているかと思います。
f:id:PaperSloth:20201218213001p:plain

この解像度を下げることでもちろん負荷は下がります。
Viewportを一切触らない時には多少下げてみるのも手なのかもですね。
個人的には作業しにくいため、ここの解像度を下げることはありませんが。
f:id:PaperSloth:20201218213059p:plain

XAudio2 で新しいフォルダー (2)を活用する話

概要

この記事は もなふわすい~とる~む Advent Calendar 2020 - Adventar
12/18(18日目)の記事です。

17日目の記事は I am コイケヤ さん による「もなふわアドベントカレンダー17日目。わーい!「各位なかよく小学校」の校章ロゴ作ったよー!\(^o^)/|I AM コイケヤ|note」でした。
校章がとても可愛らしいので何かしらグッズ化されるといいなぁと思います。
他の方の記事も、どれも熱量がすごくいい記事ばかりです!


また、本記事とは別にV沼にハマって狂ったニンゲンのポエムもこちらに公開しました。
papersloth.hatenablog.com
巻乃もなかさんとは?という人はこちらに詳細を書きましたので、目を通していただければです。


本記事では新しいフォルダー (2)を活用し、Visual Studioのビルド時に 巻乃もなか さんのかわいいボイスで開発を応援してもらうツールを作った話です。
本家というかこの記事の元ネタになったのは ねぎぽよ❣️/ニアちゃん👉 (@CST_negi) | Twitter 氏 が公開されているVoiceer というUnity向けのEditor拡張です。
github.com

UE4向けのPluginもぼくが以前にこっそり作りました。
1日で作ったもので出来がかなりアレなので、いずれアップデートをしようと思っています。
papersloth.hatenablog.com

環境

新しいフォルダー (2) とは

新しいフォルダー (2) とは 巻乃もなか さんが公開してくださっている素材用のショートボイス集です。
公開用.zip という名前なのですが、解凍すると新しいフォルダー (2)が展開されます。
現在新しいフォルダー (3)も準備中のようですので、そちらも大変楽しみですね。
※因みに新しいフォルダー、新しいフォルダー (1)は存在しません。
www.fanbox.cc

完成したもの



実装方法について

実装にあたって用意したものは2つです。

  • XAudio2 でサウンドを再生するためのexe
  • ビルドイベントを仕込んだなんかしらのプロジェクト

 今回はむかーしむかし作ったDX12のプロジェクトを引っ張り出してきました。
 C++プロジェクトでもC#プロジェクトでもビルドイベントが仕込めればなんでもいいです。

実装は至って簡単で以前にMicrosoftが公開していたXAudio2 のサンプルを叩き台にします。
現在、XAudio2 のサンプルプロジェクトのリンクが切れているため
土田さんが公開されているXAudio2 のサンプルプロジェクトを使用します。
中身としてはMicrosoftが公開していたサンプルと同様のものになっています。
こちらの書籍のリンクからサンプルがDL可能です(本も良い本ですので、興味がある方は買ってみるといいかもです)
booth.pm

サンプルをDLして展開するとその中にXAudio2BasicSoundというプロジェクトがあります。
その中にあるXAudio2BasicSound.cppとWAVFileReader.h/cpp を利用します。
WAVFileReader.h/cpp についてはDirectXTKに含まれていますので、こちらから最新版をDLして使用することも可能です。
https://github.com/Microsoft/DirectXTK

新規プロジェクトの作成

まずは新規にC++プロジェクトを作成します。
今回作成するのはコンソールアプリケーションなので、テンプレートからコンソールアプリを指定します。
f:id:PaperSloth:20201213142350p:plain

プロジェクト名はXAudioSandboxとしました。
f:id:PaperSloth:20201213142636p:plain

WAVFileReader.h/cppを使用したいため、プロジェクトに追加します。
f:id:PaperSloth:20201213142858p:plain
f:id:PaperSloth:20201213142958p:plain

XAudio2 の初期化

XAudio2 を利用したサウンドの再生にあたって
XAudio2BasicSound.cpp内にあるPlayWave()とFindMediaFileCch() をそのまま流用するため
コピペで持ってきます。

// 中身の解説等は省略
HRESULT PlayWave(_In_ IXAudio2* pXaudio2, _In_z_ LPCWSTR szFilename);
HRESULT FindMediaFileCch(_Out_writes_(cchDest) WCHAR* strDestPath, _In_ int cchDest, _In_z_ LPCWSTR strFilename);

_Use_decl_annotations_
HRESULT PlayWave(IXAudio2* pXaudio2, LPCWSTR szFilename)
{
    // 省略
}

_Use_decl_annotations_
HRESULT FindMediaFileCch(WCHAR* strDestPath, int cchDest, LPCWSTR strFilename)
{
    // 省略
}

次に、XAudio2を利用するための諸々のincludeを追加します。

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <iostream>
#include <xaudio2.h>
#include <string>
#include <wrl/client.h>

#include "WAVFileReader.h"
#pragma comment(lib,"xaudio2.lib")

ここからXAudio2 を使用してwav再生を行っていきますが
ざっくりと流れを説明すると以下のような流れになります。

XAudio2Create() // IXAudio2 の初期化
    ↓
CoInitializeEx() // コンポーネント オブジェクト モデル (COM)の初期化
    ↓
CreateMasteringVoice() // IXAudio2MasteringVoice の初期化
    ↓
PlayWave() // wavの再生 (XAudio2BasicSound.cpp内の関数)
    ↓
DestroyVoice() // IXAudio2MasteringVoice の終了処理
    ↓
CoUninitialize() // COMの終了処理

先ずは先程の流れに沿ってIXAudio2 の初期化処理を追加します。

int main()
{
    Microsoft::WRL::ComPtr<IXAudio2> pXAudio2 = nullptr;
    UINT32 flags = 0;
    HRESULT hr = XAudio2Create(&pXAudio2, flags);

    if (FAILED(hr))
    {
        wprintf(L"Failed to init XAudio2 engine: %#X\n", hr);
        return 1;
    }
    return 0;
}

続いてCOMの初期化、終了処理を追加します。

int main()
{
    // IXAudio2 の初期化
    // ...

    CoInitializeEx(nullptr, COINIT_MULTITHREADED);
    // TODO : wavの再生処理
    CoUninitialize();

    return 0;

TODOの中ではIXAudio2MasteringVoice の初期化とwavの再生とIXAudio2MasteringVoice の終了処理を行っていきます。
まずはIXAudio2MasteringVoice の初期化と終了処理を追加します。

int main()
{
    // IXAudio2 の初期化
    // ...

    CoInitializeEx(nullptr, COINIT_MULTITHREADED);

    // IXAudio2MasteringVoiceの生成と初期化
    IXAudio2MasteringVoice* pMasteringVoice = nullptr;
    if (FAILED(hr = pXAudio2->CreateMasteringVoice(&pMasteringVoice)))
    {
        wprintf(L"Failed creating mastering voice: %#X\n", hr);
        CoUninitialize();
        return 1;
    }
    // IXAudio2MasteringVoiceの破棄
    pMasteringVoice->DestroyVoice();

    CoUninitialize();

    return 0;

ここまででおおまかなXAudioの初期化と終了処理ができました。
あとはPlaySound() を呼んでwavを再生すれば、ひとまずの音声の再生は完了です。

int main()
{
    // IXAudio2 の初期化
    // ...

    CoInitializeEx(nullptr, COINIT_MULTITHREADED);

    // IXAudio2MasteringVoiceの生成と初期化
    ..

    if (FAILED(hr = PlayWave(pXAudio2.Get(), /*file pathの指定*/)))
    {
        wprintf(L"Failed creating source voice: %#X\n", hr);
        CoUninitialize();
        return 1;
    }

    // IXAudio2MasteringVoiceの破棄
    pMasteringVoice->DestroyVoice();

    CoUninitialize();

    return 0;

ボイスの再生

新しいフォルダー (2) に含まれる音声データはmp3ですので、適当なツールを使ってwav に変換しておきます。
変換したwav は以下のdirectory構造で配置しました。

+- Root
    |
    +- XAudioSandbox
    |   |
    |   +- Resources
    |       |
    |       +- Voice
    |           |
    |           +- いいコード書いてる?.wav
    |           +- ...etc
    +- XAudioSandbox.sln

先程のPlayWave内にファイルパスを通してやればひとまずボイスの再生ができることの確認ができるかと思います。

if (FAILED(hr = PlayWave(pXAudio2.Get(), L"Resources\\Voice\\再生したよ~!.wav")))

ここまでのコードを一旦載せておきます。
gist.github.com

次にビルド開始時と終了時で別々のボイスを再生するように処理を分けたいためenumと実行時引数を追加します。
また、実行時の入力引数は1つでよいため指定がない場合や複数指定されている場合はエラーを返すようにします。

enum class BuildType : uint8_t
{
    Start,
    Finish
};

int main(int argc, char* argv[])
{
    if (argc <= 1)
    {
        wprintf(L"The number of arguments is not enough.\n");
        return 1;
    }
    if (argc > 2)
    {
        wprintf(L"There are too many arguments, please specify one argument.\n");
        return 1;
    }

    BuildType type = BuildType::Start;
    std::wstring file_path = L"Resources\\Voice\\";
    std::string option = argv[1];
    if (option.compare("start") == 0)
    {
        // TODO : ビルド開始時の複数ボイスからのランダム再生
        file_path.append(L"いいコード書いてる?.wav");
        type = BuildType::Start;
    }
    else if (option.compare("finish") == 0)
    {
        // TODO : ビルド終了時の複数ボイスからのランダム再生
        file_path.append(L"コンパイルおわったよ~!.wav");
        type = BuildType::Finish;
    }
    else
    {
        wprintf(L"Incorrect argument options.\n");
        return 1;
    }

    // XAudioの処理
    // ...
    return 0;


続いて、複数ボイスの中からランダムなボイスの再生について
まずは乱数の生成を行います。
今回は実装がお手軽なメルセンヌ・ツイスタ(mt19937)を使用します。

#include <random>

// 範囲指定の乱数生成
uint64_t GenerateRandomRange(uint64_t min, uint64_t max)
{
    std::random_device device;
    static std::mt19937_64 mt64(device());

    std::uniform_int_distribution<uint64_t> uniform(min, max);

    return uniform(mt64);
}

// 呼び出しイメージ
// GenerateRandomRange(0, 10)   0-10の乱数を生成する

乱数生成関数はこれだけです。非常にお手軽ですね。

あとは先程のファイルパスの初期化部分で乱数の生成結果に応じて呼び出すファイルを変えてやればランダムなボイスが再生されます。
今回は決め打ちでarrayに突っ込んでいますが、真面目に作るなら特定のdirectory以下のfileからランダム呼び出しを行うなどの変更が必要かなとは思います。

#include <array>

int main(int argc, char* argv[])
{
    ...
    std::array<std::wstring, 5> finishArray
    {
        L"コンパイルおわったよ~!.wav",
        L"コンパイルおわり!その調子!.wav",
        L"コンパイルおわり!順調かな?.wav",
        L"コンパイルおわり!順調かな?2.wav",
        L"コンパイル終わり~!その調子~!.wav",
    };
    ...
    else if (option.compare("finish") == 0)
    {
        type = BuildType::Finish;
        file_path.append(finishArray[GenerateRandomRange(0, finishArray.size() - 1)]);
    }
    ...

呼び出すアプリケーションでの設定

アプリケーション側からの設定はVisual Studioのビルド前イベント、ビルド後イベントにexe のpathと実行時引数を与えるだけです。
ビルド前のイベントにはexe へのパスと start の引数を設定しています。
f:id:PaperSloth:20201213201256p:plain

ビルド後のイベントにはexe へのパスと finish の引数を設定しています。
f:id:PaperSloth:20201213201351p:plain

また、ボイスを入れたResourcesフォルダも実行側のプロジェクトから呼び出し可能なdirectoryにコピーしています。
あとは通常通りビルドを行えば音声が再生されます。

最後にコードの全文を載せておきます。
gist.github.com

まとめ

これでVisual Studioでも推しのボイスを再生する方法がわかりましたね!
UnityであればVoiceerを使ったり、別途Editor拡張から気軽に音声の再生ができるのでいいですね!
UE4であればVoiceer4Uを使うか、Engine側の既存のAudioを直接上書きするかEditor拡張で呼び出せるのでこちらもお手軽ですね!

また、冒頭の動画を見てお気付きになった方もいるかもしれませんが
音声再生 -> 再生終了後にビルド というステップになるため、イテレーションは落ちますw
推しの声が聞けるんだから、それぐらいの時間は我慢してください( ´∀`)

最近のゲームエンジンは喋りますが、最近のIDEもよく喋るようになりましたね!やったね!

明日はニワカ先輩 さんによる記事が公開されますね!どんな内容になるのか楽しみです!

以上です!
f:id:PaperSloth:20201213203808p:plain