非同期ロード画面 Asynchronous Loading Screen【第11回UE4勉強会 in 大阪 2019】

32.9K Views

March 12, 19

スライド概要

2019年03月08日に行われた「第11回UE4勉強会 in 大阪」で登壇した際に使用した資料です。
https://ue4study-osaka.connpass.com/event/120568/

profile-image

Unreal Engineを開発・提供しているエピック ゲームズ ジャパンによる公式アカウントです。 勉強会や配信などで行った講演資料を公開しています。 公式サイトはこちら https://www.unrealengine.com/ja/

シェア

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

非同期ロード画面 Asynchronous Loading Screen

2.

自己紹介 Axel Riffard (アクセル リファール) ● 国籍:フランス ● Twitter : @AxRiff ● サポート エンジニア ● エピックゲームズジャパンに12月入社 ● 趣味はPerfume、ベイスターズ、ウイスキー、日常最適化 ● 最近の勉強:ASM x86-64 ● 今プレイしてるゲーム:KH3 #UE4 | @UNREALENGINE

3.

このセッションで学ぶこと ● UE4のモジュールの作り方 ● スレッドを分けて、綺麗でヒッチしないロード画面UIの作り方 ● UE4の非同期コードの動き方 スライドは後で公開しますよ!!Twitterで見てね! #UE4 | @UNREALENGINE

4.

初期検討 ● マルチスレッドとは? ● UE4での実装は? #UE4 | @UNREALENGINE

5.

マルチスレッドとは? ● 同じCPUで複数な計算を動かすことです ● プラットフォームによって、別コアで動くものと、 同じコアでロジカルスレッドを作成するものがある。 OSレベルで決めることです。マルチプラットフォー ムゲームを開発したら、注意! #UE4 | @UNREALENGINE Process

6.

UE4内のマルチスレッド ● 何もしなくても、UE4がすでにマルチスレッドを使っている ● GameとDraw以外のスレッドを作れる ● エンジン内の非同期コール機能は、FAsyncTaskという関数です。いろんな所 で使われてるから、検索してみて! 実は… FAsyncTaskは、別スレッドで走っているとは限らない! #UE4 | @UNREALENGINE

7.

ロード画面はどうやって作れる? ● レベルロードはゲームスレッドでしか出来ない ● だからロード画面は別スレッドにすれば、ゲームスレッドの邪魔にならない ● レベルのロードが終わったら、非同期で他のアセットをロードする #UE4 | @UNREALENGINE

8.

スレッドを作って、 画面を表示する #UE4 | @UNREALENGINE メインスレッドで LoadLevelを呼ぶ LoadLevelが終わったら、 作ったスレッドを閉めてメ インスレッドを表示する

9.

ActionRPG ● サンプルプロジェクト「ActionRPG」のロード画面の実装が いいベース ● Googleかアンリアルラウンチャーで無料 #UE4 | @UNREALENGINE

10.

https://youtu.be/FMtNr8xwam0 #UE4 | @UNREALENGINE

11.

Game Engine LoadingModule Implementation IModuleInterface SCompoundWidget FSlateDynamicImageBrush #UE4 | @UNREALENGINE FLoadingScreenModule GameModule Interface Use ILoadingScreenModule C++ BlueprintLibrary SLoadingScreen FLoadingScreenBrush Blueprint Use

12.

使い方 #UE4 | @UNREALENGINE

13.

ブループリント側 BP_GameInstance 実際は、Absoluteパスを必 Ji ず使いましょう! Small text can be placed in at 10pt #UE4 | @UNREALENGINE

14.

ごめん、これからは、 プグラマー向けの話になる #UE4 | @UNREALENGINE

15.

モジュールとは ● モジュールはUE4のビルドブロックです ● エンジンは、モジュールの大きなコレクションとして実装され、ゲームは独 自のモジュールでそれらを拡張する ● モジュールを追加することが可能 #UE4 | @UNREALENGINE

16.

モジュールのアプローチ メリット ● ゲームのロジックと分かれている ● 管理しやすい ● 使いまわせる ● エンジンのアップデートがあっても、マージは楽(多分) ● ヒューマンエラーを防げる:関係ない人からみると実装が隠れているので、 副作用が少ない #UE4 | @UNREALENGINE

17.

#UE4 | @UNREALENGINE

18.

モジュールのロードについて ● ロード画面だから、ゲームの前に作らなきゃいけない ● ELoadingPhase::TypeというEnumで設定する ● ゲームのモジュールはDefaultなので、ゲームとエンジンのinitの前にロードし なきゃいけない。PreLoadingScreenでぴったり #UE4 | @UNREALENGINE

19.

.uprojectの編集 "Modules": [ { "Name": “GameModule", "Type": "Runtime", "LoadingPhase": "Default" }, { "Name": “NewGameLoadingScreen", "Type": "ClientOnly", "LoadingPhase": "PreLoadingScreen" } ], #UE4 | @UNREALENGINE

20.

実装 #UE4 | @UNREALENGINE

21.

インターフェイス #UE4 | @UNREALENGINE

22.
[beta]
モジュールインターフェイス作成
class INewGameLoadingScreenModule : public IModuleInterface
{
public:
static inline INewGameLoadingScreenModule& Get()
{
// Check if newly created module is correctly Loaded
return FModuleManager::LoadModuleChecked<INewGameLoadingScreenModule>(“NewGameLoadingScreen");
}
virtual void StartInGameLoadingScreen(bool bPlayUntilStopped, float PlayTime) = 0;
virtual void StopInGameLoadingScreen() = 0;
};

#UE4 | @UNREALENGINE

23.

モジュールインターフェイスは完了です! 簡単でしょう? #UE4 | @UNREALENGINE

24.
[beta]
モジュールインターフェイス実装作成
virtual void StartupModule() override
{
//Load assets to display during the loading screen
LoadObject<UObject>(nullptr, TEXT("/Game/UI/T_ActionRPG_TransparentLogo.T_ActionRPG_TransparentLogo") );
if (IsMoviePlayerEnabled())
{
CreateScreen();
}
}
virtual void CreateScreen()
{
FLoadingScreenAttributes LoadingScreen;
LoadingScreen.bAutoCompleteWhenLoadingCompletes = true;
LoadingScreen.MinimumLoadingScreenDisplayTime = 20.f;
LoadingScreen.WidgetLoadingScreen = SNew(SRPGLoadingScreen);
// Set up created loading screen UI and and movie to display in Slate
GetMoviePlayer()->SetupLoadingScreen(LoadingScreen);
}
};
#UE4 | @UNREALENGINE

25.

UI #UE4 | @UNREALENGINE

26.

Slateとは ● アンリアルのカスタム仕様の UI プログラミングフレームワークの名称です ● エディタ インターフェースはスレートを使ってビルドされる #UE4 | @UNREALENGINE

27.
[beta]
Slate Widget実装
class SNewGameLoadingScreen : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SNewGameLoadingScreen) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs)
{
static const FName LoadingScreenName(TEXT(“ImagePathThere"));
LoadingScreenBrush = MakeShareable(new FLoadingScreenBrush(LoadingScreenName, FVector2D(1024, 256)));
FSlateBrush *BGBrush = new FSlateBrush();
// Creation of the ChildSlot in Slate
ChildSlot[...];
}
}

#UE4 | @UNREALENGINE

28.

ChildSlot実装 ChildSlot [ SNew(SOverlay) + SOverlay::Slot() .HAlign(HAlign_Fill) .VAlign(VAlign_Fill) [ SNew(SBorder) .BorderImage(BGBrush) ] +SOverlay::Slot() .HAlign(HAlign_Center) .VAlign(VAlign_Center) [ SNew(SImage) .Image(LoadingScreenBrush.Get()) ] #UE4 | @UNREALENGINE +SOverlay::Slot() .HAlign(HAlign_Fill) .VAlign(VAlign_Fill) [ SNew(SVerticalBox) +SVerticalBox::Slot() .VAlign(VAlign_Bottom) .HAlign(HAlign_Right) .Padding(FMargin(10.0f)) [ SNew(SThrobber) .Visibility(this, &SRPGLoadingScreen::GetLoadIndicatorVisibility) ] ] ];

29.

ChildSlotについて 書き方がおかしく見えるかもしれませんが、実は、正しいC++ですよ。 +SOverlay::Slot()はオペレターオバーロードです。 なれたら、読みやすくなります! 詳細はhttps://wiki.unrealengine.com/Slate,_Helloまで! #UE4 | @UNREALENGINE

30.
[beta]
モジュール実装作成
class FActionRPGLoadingScreenModule : public IActionRPGLoadingScreenModule
{
virtual void StopInGameLoadingScreen() override
{
FLoadingScreenAttributes LoadingScreen;
LoadingScreen.bAutoCompleteWhenLoadingCompletes = !bPlayUntilStopped;
LoadingScreen.WidgetLoadingScreen = SNew(SRPGLoadingScreen);
// Set up created loading screen UI and and movie to display in Slate
GetMoviePlayer()->SetupLoadingScreen(LoadingScreen);
}
virtual void CreateScreen()
{
FLoadingScreenAttributes LoadingScreen;
LoadingScreen.bAutoCompleteWhenLoadingCompletes = true;
LoadingScreen.MinimumLoadingScreenDisplayTime = 20.f;
LoadingScreen.WidgetLoadingScreen = SNew(SRPGLoadingScreen);
// Set up created loading screen UI and and movie to display in Slate
GetMoviePlayer()->SetupLoadingScreen(LoadingScreen);
}
};
#UE4 | @UNREALENGINE

31.

あれ?非同期のロジックがなくない??! と思いますよね。 #UE4 | @UNREALENGINE

32.

と思いますよね。 実は、あります。 #UE4 | @UNREALENGINE

33.

Slateは、別スレッドで動いています。 #UE4 | @UNREALENGINE

34.

スレッドと非同期で何をする? ● MoviePlayerがSlateThreadで動いています。 ● 実装はRuntime\MoviePlayer\Private\MoviePlayerThreading.cpp ● 是非、ブレークポイントを入れてフローを詳しく見て下さい。 #UE4 | @UNREALENGINE

35.
[beta]
void FSlateLoadingSynchronizationMechanism::Initialize()
{
check(IsInGameThread());
ResetSlateDrawPassEnqueued();
SetSlateMainLoopRunning();
MainLoop.Lock();
FString ThreadName = TEXT("SlateLoadingThread");
ThreadName.AppendInt(LoadingThreadInstanceCounter.Increment());
// Create new thread
SlateRunnableTask = new FSlateLoadingThreadTask( *this );
SlateLoadingThread = FRunnableThread::Create(SlateRunnableTask, *ThreadName);
}

#UE4 | @UNREALENGINE

36.

ロード画面完了! #UE4 | @UNREALENGINE

37.

Q&A #UE4 | @UNREALENGINE