UE4でMOD対応ゲームを作る その4 MAP読み込み
前回までに、MODを作成する基本的な方法を覚えることができた。
今回はMODとして追加した.pakファイルからMAP名を取得して実際にそのMAPを開くことを目指してみる。
noroue4.hatenablog.com
その前に前回の補足を。
補足
前回は
「プロジェクト作成→新規プラグイン「myMOD」追加→.uplugin編集→「myMOD」の中身作成→ゲーム本体のビルド→MODのビルド」
という流れだったけど実はこれだと、ゲーム本体のビルドにMODの中身が既に組み込まれちゃってる。
つまり、わざわざMODをビルドしなくてもゲーム本体で「open NewWorld」したらNewWorldを開くことができちゃう。
なので、MODフォルダに.upluginだけ入れた状態で本体をビルドしておいたらよかったね。
それでは今日の本題。
C++を使ってMOD内のMAPを開く方法。
ブループリントでの方法は見つからなかったので、C++を使う方法を説明するよ。
準備
UE4でC++を使うには、VisualStudioが必要だ。
Microsoftの作っているIDE(ソフトウェア開発ソフト)で、VisualStudio communityという無料バージョンがある。
容量が10GB以上あるので、ダウンロードとインストールにはかなり時間がかかる。余裕をもって準備しておこう。ディスクの空き容量にも注意だ。
動画にしてみたのでこっちも見てね。
【ゆっくり解説】UE4でMOD対応ゲームの作り方 その2
準備ができたら
手段はいくつかあるみたいだけど、今回はそのひとつ、UObjectLibrary::LoadAssetDataFromPath()を使う。
まずは、Epic Games LauncherからUnreal Engine 4.21.1を起動し、新規のC++プロジェクトを作成しよう。New Project→ThirdPersonを選んで、プロジェクト名を付けよう。今回は「myCPP」にする。
C++のコードも作成される分、時間がかかるよ。
作成が終わると自動的にUE4EditorとVisualStudioが起動される。作成されたプロジェクトの見た目は、ブループリントプロジェクトとほぼ変わりない。これが起動したVisualStudioの初期画面。
画面の下に緑色のバーが動いていると思うが、生成されたコードを解析している。もうしばらく待とう。
解析が終わったら、ようやくC++に取り掛かろう。
「Source」フォルダ内にいくつかファイルが生成されているが、今回触るのは「myCPPCharacter.h」「myCPPCharacter.cpp」の二つだけだ。
myCPPCharacter.hを開いたら、#includeを追加しよう。
#include "Engine/ObjectLibrary.h" #include "Kismet/GameplayStatics.h"
それぞれ、UobjectLibraryとUGameplayStaticsを使うのに必要だ。
次に、protected:の一番下に
UFUNCTION(BlueprintCallable, Category = "myLibrary") void scanMaps(); UFUNCTION(BlueprintCallable, Category = "myLibrary") void openMaps(int32 mapNumber); TArray<FName> mapNames;
を追加しよう。
「UFUNCTION」はUE4に情報を伝えるためのおまじないで、BlueprintCallableと設定するとブループリントから関数を呼ぶことができるようになる。
Category名は、ブループリントから呼ぶときに表示されるカテゴリ名。好きな名前をつけられる。
今回は、 「scanMaps」「openMaps」という二つの関数と、「mapNames」というマップ名配列の二つを宣言した。
追加するのはこれだけなので、次はmyCPPCharacter.cppを開こう。
一番下に、
void AmyCPPCharacter::scanMaps() { UObjectLibrary* ObjectLibrary = UObjectLibrary::CreateLibrary(UWorld::StaticClass(), false, true); ObjectLibrary->LoadAssetDataFromPath(TEXT("/myMOD")); TArray<FAssetData> AssetDatas; ObjectLibrary->GetAssetDataList(AssetDatas); for (int32 i = 0; i < AssetDatas.Num(); ++i) { mapNames.Add(AssetDatas[i].AssetName); } } void AmyCPPCharacter::openMaps(int32 mapNumber) { if (mapNames.Num() <= mapNumber) { return; } else { UGameplayStatics::OpenLevel(GetWorld(), mapNames[mapNumber]); } }
を追加する。
UObjectLibraryのLoadAssetDataFromPath関数で「/myMOD」フォルダ内のアセットデータを読み込む。
/myMODは前回作ったMODのフォルダ名だが、このフォルダが存在しなかったらフリーズするので気を付けて。
既存のマップで動作確認したい場合は、「/Game/StarterContent/Maps」のようにするといい。
これでC++の編集は終わり。「Build」→「Build Solution」でビルドしてからUE4エディタに戻ってThirdPersonCharacterのブループリントを開こう。
ThirdPersonCharacterはコンテンツエディタ上で「Content→ThirdPersonCPP→Blueprints」内にあるはずだ。
最初はブループリント全部が見えないので、「Open Full Blueprint Editor」をクリックしよう。
Event Graphを開いたら、右クリックして
「Event BeginPlay」ノードを設置して、Execピンをドラッグして,さっき作った関数「scanMaps」ノードにつなげよう。
同様に、Keyboard Eventの「0」「1」「2」ノードを設置して、Execピンから、さっき作った関数「openMaps」ノードにつなげよう。
それぞれの「openMaps」ノードの入力値は、キーボードイベントと同じ「0」「1」「2」を入れておいてね。
さあ、これだけでもう完成だ。Compileボタンでコンパイルして、エディタ上でプレイしてみよう。
「/myMOD」フォルダ内にマップがあれば、キーボードの「0」「1」「2」を押してマップを開けるはずだ。
これでMOD内のマップにゲーム内からアクセスできたけど、問題は残っている。
MOD名をあらかじめ知っておかなければこの方法は使えない。
つまり、あらかじめMOD用のフォルダをいくつも作成した上で配布して、ユーザーにはそのフォルダを利用してMODを作ってもらうことになる。
なんだか、スマートじゃないよね?
もっとちゃんとした方法があるのかもしれないけど、これしか見つからなかったんだ。
もし何か見つかったら続きを書くつもり。
それではまた。