Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
8
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

【UE4】StreamableManagerについて

StreamableManagerを使用する目的

ゲーム中に必要なアセットを動的にロードするときに使用します。
基本的な動作を記載いたします。
※4.2xの内容です

使用する前に

このクラスはゲーム中に複数存在すると、
ロードしているものの管理が困難になってしまいます。
ゲーム上に1つだけ存在する設計をオススメします。

ロード方法

EX
// シングルトン的なものから取得することを想定してます.
FStreamableManager &StreamableManager = MyApp::GetStreamableManager();

// ex : "Foo/AssetName.AssetName"
FStringAssetReference AssetReferense(TEXT(" ロードしたいもののパス "));

// 動的ロードを行います.
StreamableManager.RequestAsyncLoad(AssetReferense);

このようにロードします。
ロード状況などを調べたいときは戻り値でハンドルが渡されますので、
そちらを使用するとうまくいきます。
完了したときはコールバックを呼んでもらうこともできます。※後述

また、パスを直接ソースコード中に書くとアレなので、
外から取得したいときはソフトリファレンスを利用すると良いと思います。

// ソフトリファレンスしたオブジェクトからパスを受け取る例
TSoftObjectPtr<UDataTable> LoadObject = /* ... */
:
const FStringAssetReference& AssetPath = LoadObject.ToSoftObjectPath();

ハンドル(FStreamableHandle)

進行中かどうか確認する

ロード中かどうかなどはリクエストしたときに貰う FStreamableHandle で判断できます。
同じアセットに対してロードリクエストを2回以上行うと、
既にメモリにのっているので破棄されるまではすぐにロードがすぐ終わり、コールバックが呼ばれます。
(ハンドルの Handle->IsLoadingInProgress() が true)

FStreamableHandle Handle = StreamableManager.RequestAsyncLoad(AssetReferense);

// 存在しないものなどをリクエストし、
// 失敗したときはnullptrになっているので、スマートポインタのチェックが必要です.
if ( Handle.IsValid() == false ) return;

// ロードが完了したかどうか(2回目のロードならすぐtrue).
if ( Handle->HasLoadCompleted() )
{
     // ロード完了.
}

if ( Handle->IsLoadingInProgress() )
{
    // ロード進行中.
}

ロードをキャンセルする

ロード中であればキャンセルすることができます。
キャンセルするときは、
登録していた完了コールバックは呼ばれません。

また、すでにロードが完了していればキャンセルできません。

Handle->CancelHandle();

ロードしたものを取得する

ハンドル側からロードしたものを取得できます。

Handle->GetLoadedAsset()

コールバック

完了したときに呼ばれるコールバック

完了したときにコールバックを受け取ることができます。
AssetReferenseをTArrayで複数リクエストしたときは全て終わったときにコールバックが返ってきます。
ここではLambdaで記載します。

StreamableManager.RequestAsyncLoad(AssetReferense, []()
    {
        // 完了したときのコールバックをここに書きます.
    });

その他コールバック

完了時だけでなく他にもコールバックには種類があります。
また、コールバックを登録し直すこともできます。
ただ、ロードが完了するまでに登録しなければ登録できないので注意です。
(特に2回以上呼び出されたときはロードがすぐ終わります)

// 完了したときのコールバックを登録できます.
Handle->BindCompleteDelegate( ... )
// キャンセルしたとき.
Handle->BindCancelDelegate( ... )
// 更新したとき.
Handle->BindUpdateDelegate( ... )

:warning:気をつけること:warning:

メモリ管理

ロードした数だけ使用するメモリは増えます。
不要なものはロードしない&メモリから破棄することを忘れないようにしましょう。

破棄のミス

ロードをリクエストした後、
そのロードが完了する前にレベルを遷移してしまい、
遷移後に完了コールバック処理が呼ばれてエラーに…ということがありました:sweat_smile:
ロード中に遷移するようなシーンはキャンセルが必要だと思います。

最後に

メモ書きに近い内容でしたが、
読んでいただきありがとうございました。
間違っている所があれば修正いたします。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
8
Help us understand the problem. What are the problem?