PaperSloth’s diary

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

UE4 Editorでの動画像の撮影について

環境

UE4.20.3
Windows10

概要

SNSやHP等で制作中のスクリーンショットをアップすることはよくありますね。
その中でEditor上でスクリーンショットを撮影される方も多いでしょう。
ですが、せっかくの良いゲームなのに
デバッグログが出ていたりEditorOnlyのGUIが表示されているとすごく完成度が低く見えてしまい残念に感じます。
少しでも良いゲームがもっと良く見えるようになるといいなと思います。

ゲームのスクリーンショットの撮影について

まず、UE4ではF9キーを押下することでスクリーンショットを撮影することができますね。
撮影した画像は
(ProjectDir)\Saved\ScreentShots\Windows\ScreentShot(連番).png
に保存されます。
f:id:PaperSloth:20190129200652p:plain
ここまでは特に問題ありませんね。

EditorでHidden In Gameが有効なActor/Componentを非表示にする

ViewportでGキーを押下することでGameViewの切り替えができます。
Hidden In Gameのフラグが立っているActor/Componentを非表示にできます。

先ずありがちなのが、CollisionやSpline等の実行中に表示されないComponentがスクリーンショットに写っている例です。

「新ステージを実装しました!」と下記のような画像が出てくるよりは
f:id:PaperSloth:20190129201439p:plain

下記のような画像の方がまだいいですね。
f:id:PaperSloth:20190129201601p:plain

Editor画面がまるまる写っている場合

ViewportでF11キー押下でImmersive Modeにしてからスクリーンショットを撮ることで回避できます。

これはほとんど見かけませんが、Editor画面がまるまる写っている例です。
f:id:PaperSloth:20190129201946p:plain

見たいのはあくまでもゲーム画面なので開発における技術ブログでもなければ
Editor画面は不要です。

UE4.20.3の場合はF9キー押下で普通に撮影すればこうはなりませんが
Windows標準のスクリーンショット機能で撮影をした場合などでしょうか。

Lightmap Rebuildの警告やPrintStringやAddOnScreen系のログが出ている。

Console CommandからDisableAllScreenMessagesを打ちましょう。
再度表示したい場合はEnableAllScreenMessagesです。

これが一番多くて一番ダサいですね。
f:id:PaperSloth:20190129202844p:plain

実は警告の下にうっすらと
「DisableAllScreenMessages'to suppress」と書かれています。


以上です。
せっかくのステキなアート、かっこいいゲームを作ってもこれが出てるだけでげんなりします。
ゲーム本来のキレイな絵が見れる頻度が増えることを祈ります。

 

SDL SDLの導入について

環境

Windows 10
Visual Studio 2017 Community
SDL 2.0.9

SDLとは

SDL (Simple DirectMedia Layer) は、Graphic, Sound系のAPIを提供するC言語マルチプラットフォーム対応のライブラリ。

公式サイトは下記
Simple DirectMedia Layer - Homepage

Forumを見れば分かるのだが現在も使用しているユーザーはいる。
https://discourse.libsdl.org/


SDLを使用している書籍は下記等がある。
で、意外と導入で躓いたという人もいるかもしれないと感じたのでこの記事を書くに至った。

オンラインゲームを支える技術ではSDL1.2系が使用されている。

オンラインゲームを支える技術  ??壮大なプレイ空間の舞台裏 (WEB+DB PRESS plus)

オンラインゲームを支える技術  ??壮大なプレイ空間の舞台裏 (WEB+DB PRESS plus)

ゲームプログラミングC++ではSDL2.0.3が使用されている。

ゲームプログラミングC++

ゲームプログラミングC++


SDLの導入

まずは下記よりDownloadを行う。
もしリンクが切れていたらブログトップの公式サイトのリンクからDownloadページにいってください。
Simple DirectMedia Layer - SDL version 2.0.9 (stable)

今回はDevelopment LibrariesのVC++を使用する。


1. コンソールアプリケーションを新規に作成
 適当に空のプロジェクトで良い

2. ダウンロードしたファイルを適当な場所(Solution\External\SDL とか)に解凍

3. SDLのインクルードディレクトリの指定。
 構成プロパティ/C/C++/全般/追加のインクルードディレクト
f:id:PaperSloth:20190122220010p:plain

4. 追加のライブラリディレクトリの指定。
 リンカー/全般/追加のライブラリディレクト
f:id:PaperSloth:20190122220328p:plain

5. 追加の依存ファイルの指定。
 リンカー/入力/追加の依存ファイル
  SDL.libとSDLmain.libを追加
f:id:PaperSloth:20190122220551p:plain

6. DLLをビルド時にコピー
 ビルドイベント/ビルド後のイベント/コマンドライン
  xcopy "(SDLへのパス)\*.dll" "$(OutDir)" /i /s /y を入力
f:id:PaperSloth:20190122220848p:plain

ひとまずここまでで動かすための前準備が完了。

SDLを使用する際の注意点

まず、SDLを使用する際に下記の記述をするとエラーになってしまいます。

#include "SDL.h"

int main()
{
    SDL_Init(SDL_INIT_EVERYTHING);
    // メイン処理
    SDL_Quit();
    return 0;
}

エラーメッセージを見てみると
LNK2019 未解決の外部シンボル _SDL_main が関数 _main_getcmdline で参照されました。
と出てきます。

これはSDL_main.h内でmainでdefineが定義されているからです。

#if defined(SDL_MAIN_NEEDED) || defined(SDL_MAIN_AVAILABLE)
#define main    SDL_main
#endif

また、SDL_main.h内にはメイン関数は次のように定義してくださいと書かれています。

int main(int argc, char *argv[])


そのため、SDLを使用する際には引数付きのメイン関数を定義する必要があります。

void main() // NG!
int main() // NG!
int main(int argc, char* argv[]) // OK
int main(int argc, char** argv) // OK
#include "SDL.h"

int main(int argc, char** argv)
{
    (void)argc;
    (void)argv;
    SDL_Init(SDL_INIT_EVERYTHING);
    // メイン処理
    SDL_Quit();
    return 0;
}

ひとまずWindow, Rendererを作成してみるとこんな感じになります。
f:id:PaperSloth:20190122225202p:plain

DirectXOpenGLに比べるとすごく簡単なので、C++でとりあえずゲームを作ってみようかなという人は挑戦してみてください。

UE4 C++でfpsを取得する方法について

この記事は「Unreal Engine 4 (UE4) Advent Calendar 2018」16日目の記事です。
Unreal Engine 4 (UE4) Advent Calendar 2018 - Qiita

環境

UE4.20.3

FPSの取得、あるいは計算方法

UE4fpsの計算でググると真っ先に出てくるのが
Tick内で1.0f / DeltaTimeで計算する方法。
Blueprintからも計算できてお手軽。
あとはこれをログに吐くなり、Widgetで表示するなりして使う。

void AExampleActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
    float fps = 1.0f / DeltaTime;
    // ログ表示とかとか
}

fpsを単純に表示したい場合はConsole Commandから"stat fps"で表示ができる。
基本的にデバッグで使いたいというだけの場合はこちらを使うだろう。

しかし、stat fpsではできないことが2つある。
①Shippingでビルドした場合に確認できない(Shippingではコンソールコマンドを受け付けないため)
②Game内のUIでfpsの表示機能が作成できない
 PCゲームではfpsを表示するオプションがあったりする
 
fpsを計算したり、stat fpsで表示してみて気になるのは
Tickでの計算値とstat fpsで表示されるfpsの値に違いがある点。
これは計算方法が違うため結果が異なる。
f:id:PaperSloth:20181210145352p:plain

そこで、今回はこのstat fpsで表示される値の取得方法について紹介する。

そもそもエンジン側でfpsの値を保持しているで自分でわざわざ計算する必要もない。

stat fpsで表示される値

UnrealEngine.cpp内にstat fpsで表示されるfpsの定義がある。

ENGINE_API float GAverageFPS = 0.0f;

名前からも分かるようにこの値はグルーバル変数として定義されている。
この値はUnrealEngine.hのCalculateFPSTimings()内で計算されている。

C++側でのfpsの取得について

実際に使用する際はBlueprintFunctionLibraryにでもまとめてしまうと良いだろう。

#include "Engine.h"

float UExampleFunctionLibrary::GetAverageFps()
{
    extern ENGINE_API float GAverageFPS;
    return GAverageFPS;
}


また、stat fpsでは処理に何ms時間がかかったかも表示している。
こちらもグローバル変数で公開されているので取得することができる。

float UExampleFunctionLibrary::GetAverageMs()
{
    extern ENGINE_API float GAverageMS;
    return GAverageMS;
}

30fpsのゲームなら33.33ms
60fpsのゲームなら16.66ms
120fpsのゲームなら8.33ms

この時間内に処理を終える必要がある。


Widgetを作成し、fps, msを表示してみた結果が下記になる。
stat fpsで表示されている値と一致していることが分かる。
f:id:PaperSloth:20181210150145p:plain

この方法で取得した値であればShippingビルドでも使用することができる。

UE4 Actor間の距離の取得について

環境

UE4.20.3

距離の計算方法

数学的な計算方法は調べれば沢山出てくるので割愛してUE4での使い方の話をします。

C++側であれば下記のように求め

const float Distance = (GetActorLocation() - PlayerPawn->GetActorLocation()).Size();

Blueprintでは下記のように求めているという例をよく目にします。
f:id:PaperSloth:20181213154410p:plain
例えば敵とPlayerの距離とかアイテムとプレイヤーの距離とかですね。

Get ** Distance To

今回は分かりやすい例として何かしらのActorとプレイヤーの距離を求めるというケースです。

先程の計算をわざわざ書かなくともUE4.0の頃からActor内に便利な関数が複数用意されています。

GetDistanceTo

Actor間の距離を取得する便利関数です。
最初の例で書いたものと同様の結果を得ることができます。
f:id:PaperSloth:20181213155527p:plain

GetHorizontalDistanceTo

高さ(Z軸方向)を無視した距離を取得することができます。
平面での距離の取得なので、俯瞰視点のゲームやレーダーに使えそうですね。
f:id:PaperSloth:20181213155827p:plain

GetVerticalDistanceTo

先程と逆で高さ(Z軸方向)の距離のみを取得することができます。
float - floatなので一番計算コストが低いですね。
f:id:PaperSloth:20181213160005p:plain

GetSquaredDistanceTo

この関数だけはUE4.11から追加されたものです。
この関数ではベクトルの2乗の長さを取得します。
f:id:PaperSloth:20181213161353p:plain


意外と知られていないノードがたくさんあると思うので、気が付いたらいろんな人がシェアしてくれると嬉しいです。

UE4 昔ながらのSkydomeを使う

環境

UE4.20.3

SkydomeまたはSkyboxについて

ステージ全体を覆う球体を置いてそこにテクスチャを貼る昔ながらの天球表現方法です。
Unityみたいに画面を単色でクリアする方法はないのかと疑問に思っている人がいたので、その代替手段としての利用もできそうだなと思います。
f:id:PaperSloth:20181213141656p:plain

UE4にはBP_Sky_SphereというBlueprintがあり、天球の表現として大変優れていますが
今回のSkydomeのように局所的に空を表現したい場合や
極力テクスチャそのものの色味を表現したい場合等に今回の表現が使えると思います。
また、モバイルやVRなど負荷を抑えたい場合にも活用できるかもしれません。
f:id:PaperSloth:20181213153031p:plain

Skydomeを使う方法

Meshについて

 MeshはUE4内のアセットをそのまま流用してスケールだけ調整すれば良いでしょう。
 Engine/MapTemplates/Sky内にSM_SkySphereという球体のメッシュがあるのでこちらを使います。

Materialについて

 マテリアルもそのまま流用できるものがありますが、少し手を加えたいので今回は自作します。
 Unlitにして下記のようにCubeMapテクスチャに繋げば完成です。
 f:id:PaperSloth:20181213142304p:plain

ここまでで一旦LevelにMeshを配置してMaterialを割り当てると天球が表現できました。
f:id:PaperSloth:20181213142619p:plain

Materialについて(単色表現)

 冒頭に説明したようにUnityのように単色でクリアしたいというものの代替手段として天球で囲ってしまいましょう。
 因みにUnityのDefaultのSolidColorはR:49, G:77, B:121です。
 UE4のマテリアルで使用する値は0-255ではなく0-1ですので変換が必要です。
 LinearColorとColorの変換用のBlueprintなんかを作っておくとなにかの役に立つかもしれませんね。
 f:id:PaperSloth:20181213143631p:plain

 Colorを変換するとR:0.030713, G:0.074214, B:0.191202であることが分かりました。
 あとはこれをEmissiveColorに繋ぐだけです。
 f:id:PaperSloth:20181213144214p:plain

 しかし、あんまりUnityっぽくならないですね。
 f:id:PaperSloth:20181213144447p:plain

 これはUE4がデフォルトでポストエフェクトを色々かけているからですね。
 "ShowFlag.PostProcessing 0"でポストエフェクトを全て無効にします。
 AAも無効になるため、ジャギーも発生しますがデフォルトのUnityっぽい良い感じの絵になりました。
 f:id:PaperSloth:20181213145550p:plain

 脱線したので本題に戻ります。

Skydomeを回転させたい場合

 さて、このままでは天球を回転させても反映されません。
 そこでマテリアルにひと手間加えます。
 f:id:PaperSloth:20181213145112p:plain

 TransformVectorを追加し、WorldSpaceからLocalSpaceに変換しました。
 これでLevelに配置したメッシュを回転させた場合に見た目上も回転が反映されます。
 f:id:PaperSloth:20181213145351p:plain

CubeMapの変換

UE4では面白いことにCubeMapを2DTextureにしたり
2DTextureをCubeMapに変換してくれるようなMaterial Functionが提供されています。

注意点としてどちらもTextureの設定でNoMipMapsにしていないと意図しない線が表示されてしまいます。

CubeMap→2DTexture

UVToLongLatというMaterialFunctionを利用することでできます。
f:id:PaperSloth:20181213175724p:plain

f:id:PaperSloth:20181213175734p:plain

2DTexture→CubeMap

こちらはLongLatToUVというMaterialFunctionを利用することでできます。
f:id:PaperSloth:20181213175855p:plain

f:id:PaperSloth:20181213180208p:plain

ノイズ系のテクスチャを背景にしてみると面白そうですね。

その他

天球の設定をした後はSkyLightも設定することをオススメします。
天球によってはライティングの質がグッと良くなります。

ExponentialHeightFogも忘れてはいけません。
こちらもInscattering TextureからCubemapの設定ができるので設定しておくとより空気感のある絵になります。
f:id:PaperSloth:20181213152204p:plain

また、HDRテクスチャの圧縮方式ですがデフォルトではHDR(RGB, no sRGB)になっていますが
HDR Compressed(RGB, BC6H, DX11)に変更することで圧縮される場合もあるのでそちらも確認してみてください。

同じくテクスチャの設定ですがHDRテクスチャをインポートするとデフォルト解像度が
512 x 512 x 6になってしまいます。
なんだか思ったよりキレイにならないと感じたらチェックしてみてください。
Maximum Texture Sizeから変更でき、最大で2048 x 2048 x 6に変更できます。
ただし、元のTexture解像度が512や1024の場合は当然効果はありません。


天球を活用してよりリッチな絵作りを目指していきましょう!

Houdini ApprenticeとIndieについて

Houdini ApprenticeとIndieの違い

詳しくはSideFX公式の比較表がとても見やすいです。
www.sidefx.com

公式の比較表を見ると分かるように結構違いがあります。
その中でも個人的にHoudini Indieの契約を検討するラインが下記です。
Apprenticeではできないこと
・fbx形式でのExport(Importのみ可能, objでのExportは可能)
・Houdini Engine Pluginの利用ができない

fbxでのExportができないため、Houdini上でモデルを作成した場合などに
他の環境に移行して作業するのができなくて不便です。

そして、一番大きいのがHoudini Engineの存在ですね。
Maya, 3ds Max, Cinema4DなどのDCCツールや
Unity, UE4といったゲームエンジンにHDA(Houdini Digital Asset)を持っていくことができません。
(できないというよりは正しく動作しない)

Houdini Apprenticeは名前の通り、あくまでもHoudiniの学習用のライセンスです。

Houdini Engineについて

Houdiniの使い方を覚えたらUnity, UE4との連携をしたいという人も多いでしょう。
公式からUnity向け、UE4向けにそれぞれチュートリアル動画が出ています。
バージョンがHoudini14と15で古いですが、それでも取っ掛かりにはちょうど良さそうです。
どちらの動画も10分以内で比較的簡単にプロシージャルなモデルが作成できます。

Unity向けPluginについて
Unity Plug-in | SideFX
Unity向けHDAチュートリアル
Create Asset for Unity | SideFX


UE4向けPluginについて
Unreal Plug-in | SideFX
UE4向けHDAチュートリアル
Create Your Own Asset | UE4 | SideFX


HoudiniといえばBISHAMONのような
VFX用のミドルウェアだと思われてる方もいますがそうではありません。

特に興味深い例がGhost Recon Wildlandsで
昨年のGDC2017でプロシージャルな地形の生成について発表されました。
地面や川、道路だけでなくゲーム内の村もプロシージャルに生成して効率化しています。
崖や地面だけでもこだわって作られているのがよく分かります。
GDC Vault - 'Ghost Recon Wildlands': Terrain Tools and Technology
Procedural Technology in Ghost Recon: Wildlands

Houdini Indieについて

SideFX公式の購入ページから購入する場合
年間契約だと$269で2年契約だと$399でお得。
Houdini Store | SideFX

個人的にはいきなり契約するよりもApprenticeで基本操作を覚えてからの契約がオススメです。
Houdini Engine自体は無料でDLすることができます。
Houdini Engine自体は無料ですが、Apprenticeライセンスでは当然ゲームエンジンとの連携はできません。

また、最近はSteamからも販売されるようになりました。
Houdini Indie on Steam
12ヶ月のサブスクリプション(月々¥2495.75)と
24ヶ月のサブスクリプション(月々¥1896.66)が選べます。

公式のストアから2年契約が1番お得だったんですが
Steamでのセールを待ってみるのも1つの手段かもしれませんね。

Houdiniの学習について

幸せなことにHoudiniに関する書籍は日本語の書籍が世界中で最も多いのではないでしょうか。
書籍の他にも公式のチュートリアル動画やたくさんのHoudinistのブログを見るのも良いでしょう。

書籍は現在自分の知る限りでは4冊出ています。

・Houdiniではじめる3Dビジュアルエフェクト(改訂版)
http://amzn.asia/d/7D2xY0u
本の厚み的にも内容的にも最初に人にオススメできる本だと思います。
Houdiniに興味を持ったらここから始めてみるのもいいかもしれません。


・理論と実践で学ぶHoudini -SOP&VEX編-
http://amzn.asia/d/iXAfRyY
Houdiniの基本操作から応用までを扱った書籍。
元々は教科書として執筆されたもののようで、分かりやすいように丁寧な解説がされています。
また、Houdiniに限らず数学に関しての説明もあるのでプログラミングの知識がない人も安心です。


・Houdini ビジュアルエフェクトの教科書
こちらもHoudiniの基本操作から応用までを扱った書籍。
エフェクトとシミュレーションに特化しているため、そういった機能を特に学びたい人にオススメ。
Houdini Digital Assetについても書かれているので、ゲームエンジンと連携したい人にもオススメです。
http://amzn.asia/d/9QXUmFk


・Houdini実践ハンドブックWrangle×Python
http://amzn.asia/d/ep6e9Cz
現在はKindle Unlimitedに登録されているため、契約されている方は試し読みしてみてもいいでしょう。
(無料での公開ですが、読まれるとちゃんとお金が入るらしいので安心)

タイトルからも分かるようにWrangleとPythonについての基本から応用までが書かれています。
Houdini自体の操作の解説本ではないため、基礎を覚えてから読むと頭に入りやすいでしょう。

まとめ

Houdiniは書籍も充実して、CEDEC等の大きなセミナーでも登壇される方が増えてきました。
Houdiniを使って効率化されてきたと感じるまでの成長曲線が辛い時もありますが
最終的には覚えて良かったと言えるときが来るでしょう(多分)。

UE4の新エフェクトシステムのNiagaraとの連携も発表され、Houdiniを覚えるメリットが増えてきています。
たくさんの人がHoudiniを覚えて色々な知見が公開されるとみんなハッピーになれていいなと思います。
(仕事で使う人はちゃんと規約を読んで必要に応じてHoudini FXとHoudini COREを買ってね)

UE4 不要なComponentを継承先で作成させない方法

環境

・Unreal Engine4.20.3

不要なComponentを継承先で作成させない方法

例えばCharacterクラスを継承したいけど、Skeletal Meshを使用しないためMeshを継承させたくない場合

愚直に実装をするとctor内でこう書くと思います。

AExampleCharacter::AExampleCharacter()
{
    if (GetMesh())
    {
        GetMesh()->DestroyComponent();
    }
}

もちろんこうすることで継承先のCharacterからComponentを破棄することはできます。

ですが、もう少しスマートに書く方法があります。
普段あまり使用しないかもしれませんがObjectInitializerを使用します。

// AExampleCharacter.h
UCLASS()
class EXAMPLE_API AExampleCharacter: public ACharacter
{
    GENERATED_BODY()

public:
    AExampleCharacter(const FObjectInitializer& ObjectInitializer);
};

// AExampleActor.cpp
AExampleCharacter::AExampleCharacter(const FObjectInitializer& ObjectInitializer)
  : Super(ObjectInitializer)
{
}

ObjectInitializerからはDoNotCreateDefaultSubobjectというメソッドが提供されており
不要なComponentの作成を防ぐことができます。

今回はMeshを作成させたくないため、MeshComponentの名前を指定して作成を防ぎます。

AExampleCharacter::AExampleCharacter(const FObjectInitializer& ObjectInitializer)
  : Super(ObjectInitializer.DoNotCreateDefaultSubobject(MeshComponentName)),
{
}

同様にCharacterMovementComponentの作成を防ぐ場合は
CharacterMovementComponentNameを指定し

Collisionの作成を防ぐ場合は
CapsuleComponentNameを指定します。


こうすることでSkeletal Meshを使用しないCharacterを作成できます。
他にもCapsule Collision以外を持ったCharacterや
自前のMovementComponentを持たせたCharacterを作成することができます。
f:id:PaperSloth:20181106165119p:plain


また、前回の記事でTickについて書きましたが
Skeletal Mesh ComponentもTickComponentが走っているため、使用しない場合は作成を防止したほうが良いでしょう。
papersloth.hatenablog.com