AssetManagerでPrimaryAssetを読み込む手順を紹介してる記事はまぁまぁある。
しかし、C++での非同期読み込みについて言及してる日本語の記事が少ないと思ったので、備忘録がてら記載しておこうと思う。
前提として、今回の実装は
● DataTableにC++からアクセスする為に、DataTableのインスタンスを管理するためのPrimaryDataAsset(class UDataTableReference)を作っておく。
● C++側でUDataTableReferenceの読み込みを行うことで、DataTableのインスタンスをC++で能動的に使えるようにする
という流れで実装したものの一部。
BP側からDataTableのインスタンスを直接C++側に渡すことも出来るが、BPとC++のやりとりが増えれば増えるほど処理が追いづらくなるので、今回はあくまでもC++主導でDataTableの管理を行いたい。
また、C++のみでBPで実装されている特定のDataTableを参照する事もできるが、ファイルパスの指定をハードコーディングする必要があったのが気に入らなかったので却下した。
ちなみに、ここで読み込みたいDataTableはレベルに依存したものであり、今回はプレイヤーがゲーム世界を探索する際の各種マスターデータとして実装しているDataTableを読み込んでいるので、読み込み処理はレベル(class ABaseMap)が実行している。
void ABaseMap::LoadDataAsset() { auto& assetManager = UAssetManager::Get(); TArray<FPrimaryAssetId> assetIdList; if (assetManager.GetPrimaryAssetIdList(UDataTableReference::AssetType, assetIdList)) { assetManager.LoadPrimaryAsset(assetIdList[0], { }, FStreamableDelegate::CreateUObject(this, &ABaseMap::OnDataTableReferenceLoaded, assetIdList[0])); } }
● GetPrimaryAssetIdListについて
引数で指定したPrimaryAssetTypeに該当するPrimaryAssetIdを配列で取得できる。
(PrimaryAssetTypeの実態はFNameみたいなものなので、直接TEXT("")を渡すことも可能)
該当したPrimaryAssetIdは、同じく引数で指定されたTArrayに格納されるので、アウトプット用の変数を作っておく。
(ここで言うassetIdList)。
また、該当するPrimaryAssetIdが1つ以上あるかどうかが関数の戻り値でboolとして返ってくるので、ifで制御しておく。
● LoadPrimaryAssetについて
実際にPrimaryAssetの読み込みを行う関数。
読み込みたいPrimaryAssetに対応するPrimaryAssetIdを、引数として”一つだけ”渡せる。
(複数読み込みたい時は、LoadPrimaryAsset"s"を使う)
2番目の引数には、いわゆるAssetBundlesを配列として渡せる。
今回はmeta tagでのAssetBundlesの指定はしていないので空の配列を渡している。
3番目の引数には、ロードが完了した時のコールバックを渡す。
コールバックの引数に渡したいものは、 FStreamableDelegate::CreateUObjectの引数に渡せば良い。
細かい事は調べてないが、多分ラムダ式と似たような感じな気がする。
恐らくキャプチャした変数を渡してるだけだと思うので、ローカル変数を渡したい時は値渡しするのが無難だと思う。
void ABaseMap::OnDataTableReferenceLoaded(FPrimaryAssetId assetId) { if (const auto& dataTableReference = UAssetManager::Get().GetPrimaryAssetObject<UDataTableReference>(assetId)) { ~~ } }
これはコールバックで指定した関数の実装。
引数で渡されたPrimaryAssetIdを使い、AssetManager::GetPrimaryAssetObjectを実行することでロード済みのPrimaryAssetを取得出来る。
終わり。
今回、C++でAssetManagerを使う為の参考資料がガチで少なくて困った。
普段なら、一つの機能に関して複数の参考資料を参照して自分の理解が正しいか多方面的に確認していくのだが、PrimaryAssetに関しては有名な資料が2、3個あるだけだったのでそれが難しかった。
というか、複数の資料が1つの資料を参照してる事が多く、情報としては結局一つしか手に入らないという事が多かった。。
この参考資料の少なさは、C++使えるなら自分でエンジンのコード見て理解できるよね?という暗示なのだろうか。
僕は昔取った杵柄でC++もBPも理解できるからギリギリ何とかやれているが、初心者にとってあまりに厳しい環境だなと思う。
PrimaryAssetに限らないが、自分が使いたい機能を調べてみると、有名で色んな人が参考にしてる記事が2、3個出てくるだけで、そこで紹介されている使い方から少しでも外れたことをしようものなら途端に情報不足に陥ってしまう。
まぁ、基本的な使い方が分かれば後は当人の工夫次第でどうにでもなるし、使い方も千差万別なので解説しようがないのかもしれない。。
だとしても、皆がどの機能をどうやって使ってるのかとか、工夫の仕方とかの情報がもっと充実してればいいなと思う。
とりあえず、(Unityはもっと情報に溢れてて楽しかったぞ!)という事だけ心の中で叫んでおきたい。
と思ったので、まだまだ理解力不足だと思うものの、一旦記事にしようと思った次第です。
間違ってることがあれば適宜修正するのでご連絡ください。
(ΦωΦ)フフフ…
参考記事
今回参考にした記事。
unrealcommunity.wiki
↑の記事が参考にしてるリポジトリの該当箇所付近。
github.com
多分、この記事を参考にして一番困るのがMonsterIdというPrimaryAssetIdの存在だと思う。
これはDataTableに登録されているPrimaryAssetIdを使ってるということになると思う。
しかし、そうなるとPrimaryAssetを読み込むためのPrimaryAssetIdを保持しているDataTableを読み込む必要が出てくるので、少なくとも僕はそのまま流用できなかった。
まぁ、PrimaryAssetを使う上で、PrimaryAssetIdないしはPrimaryAssetTypeをどう管理するかが人によって分かれる所なのかなぁと思った。
(ΦωΦ)フフフ…