環境
UE4.19.1
Logファイルの収集について
UE4でよく使うUE_LOGマクロ、PrintStringノードがありますね。
UE_LOG(LogTemp, Error, TEXT("Log message"));
これらで出力したLogはSavedファイルに保存されます。
(ProjectDirectory)/Saved/Logs/(ProjectName).log
エラー処理をした時など、ログを探したい時などに役立ててください。
Unreal Engine (Git:4.19)
Visual Studio 2017 Community
Windows 10
エンジンビルドの方法についてはヒストリアさんのブログが参考になります。
[UE4] エンジンのソースコード取得とビルド手順のまとめ UE4.6改訂版|株式会社ヒストリア
さて、カスタムビルドのエンジンを毎回IDEから起動するとどうしても時間がかかってしまいますね。
ですが、エンジンを一度ビルドすると実行ファイルが作られます。
(EngineDirectory)/Engine/Binaries/(Platform)/UE4Editor.exe
WindowsPCだと下記のフォルダに作成されます。
(EngineDirectory)/Engine/Binaries/Win64/UE4Editor.exe
実行するとLauncherからLaunchした際と同様です。
UE4.19.1
Visual Studio 2017 Community
Unreal C++のIDEはMacではXCode, WindowsではVisual Studioを使用することが多いと思います。
IDEの変更方法はEditor PreferencesのSource Codeから変更します。
Visual Studio 2017 Communityをインストールしたので、この機会に変更してみました。
因みにこの後にOpen Visual Studio 2017を選択しても
プロジェクトをVisual Studio 2015で作成していたらVisual Studio 2015が開きます。
Refresh Visual Studio 2017 Projectを選択してソリューションを更新します。
これでプロジェクトでVisual Studio 2017を使用出来るようになります。
Visual Stuidio Code等他のIDEを使用したい場合もここから変更出来ます。
UE4.19.1
Visual Studio 2015 Community
ここの部分の初期化についてです。
C++で作成したGameModeBaseだと編集できないのですが
Blueprintだと楽に編集ができますね。
ここをC++側で編集する方法について書きます。
GameModeBaseに登録されているのは下記のような処理です。
AGameModeBase::AGameModeBase(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer.DoNotCreateDefaultSubobject(TEXT("Sprite"))) { // 省略 DefaultPawnClass = ADefaultPawn::StaticClass(); PlayerControllerClass = APlayerController::StaticClass(); PlayerStateClass = APlayerState::StaticClass(); GameStateClass = AGameStateBase::StaticClass(); HUDClass = AHUD::StaticClass(); GameSessionClass = AGameSession::StaticClass(); SpectatorClass = ASpectatorPawn::StaticClass(); ReplaySpectatorPlayerControllerClass = APlayerController::StaticClass(); ServerStatReplicatorClass = AServerStatReplicator::StaticClass(); }
例えばGameModeBaseを継承したGameModeでnullptrを設定するとNoneになります。
AExampleGameModeBase::AExampleGameModeBase() { DefaultPawnClass = nullptr; }
継承したクラスを登録したい場合は下記のようになります。
#include "ExampleGameModeBase.h" #include "ExampleCharacter.h" #include "ExamplePlayerController.h" AExampleGameModeBase::AExampleGameModeBase() { DefaultPawnClass = AExampleCharacter::StaticClass(); PlayerControllerClass = AExamplePlayerController::StaticClass(); }
UE4.19.1
Visual Studio 2015 Community
いくつかやり方があって、今回は一番簡単でお手軽なenumを使ったやり方を紹介します。
先ずは下記のようなenumを定義します。
UENUM(BlueprintType)
enum class EErrorCode : uint8
{
Success,
Failed
};
続いてUFUNCTIONマクロを使用してBlueprintに関数を公開します。
UFUNCTION(BlueprintCallable, Category = "Example") void ExampleEnumInput(const EErrorCode ErrorCode); // 関数内でErrorCodeの値が変わる関数を想定 UFUNCTION(BlueprintCallable, Category = "Example") void ExampleEnumOutput(EErrorCode& ErrorCode);
constなしの参照にすることで引数が出力ピンに変わります。
constをつけた参照の場合は引数が入力ピンになります。
Blueprintから先程の関数を呼び出すと下図のようになります。
さて、ようやく本題です。
enumを使って複数の実行ピンを使用するにはUFUNCTIONのmetaに下記を追加することで実現可能です。
UFUNCTION(/*省略*/, meta = (ExpandEnumAsExecs = "ArgumentName"))
ArgumentNameの部分は任意の引数名を入力します。
実際に使用する引数名と一致するようにします。
先程の関数に手を加えて下記のように変更しました。
UFUNCTION(BlueprintCallable, Category = "Example", meta = (ExpandEnumAsExecs = "ErrorCode")) void ExampleEnumMultiInput(const EErrorCode ErrorCode); UFUNCTION(BlueprintCallable, Category = "Example", meta = (ExpandEnumAsExecs = "ErrorCode")) void ExampleEnumMultiOutput(EErrorCode& ErrorCode);
Blueprint側から呼び出すと下記のようになります。
enumで登録した値が全て実行ピンになっていますね。
後はC++側でswitchとかで処理を分けると良さそうです。
また、enumで定義を追加するとノードも変更されます。
UENUM(BlueprintType)
enum class EErrorCode : uint8
{
None,
Success,
InternalError,
ExternalError,
NetworkError,
UnknownError,
};
Noneを定義した場合は実行ピンには名前が出ません。
もう少し気の利いた処理になるように関数の中身も書いてみます。
Successの時、Failedの時でそれぞれ呼び出す関数を登録します。
C++だけで処理を実装するのは直ぐにできますが
今回はC++で関数の定義をしてBlueprintでロジックを実装する形にしてみましょう。
先ずは呼び出す関数の登録を行います。
UFUNCTION(BlueprintImplementableEvent, Category = "Example") void OnSuccess(); UFUNCTION(BlueprintImplementableEvent, Category = "Example") void OnFailed();
成功時、失敗時のそれぞれの関数を用意しました。
BlueprintImplementableEventはC++側で定義してBlueprintで関数のロジックを実装するときに使用します。
この定義だとBlueprintで処理の記述はできますが、関数呼び出しはC++側からしか呼び出せません。
Blueprintからも呼び出したい場合は、BlueprintCallableと組み合わせることで使用できます。
複数実行ピンを入力できる関数で呼び出しを行うように処理を記述します。
void AExampleActor::ExampleEnumMultiInput(const EErrorCode ErrorCode) { switch (ErrorCode) { case EErrorCode::Success: OnSuccess(); break; case EErrorCode::Failed: OnFailed(); break; } }
これでBlueprint側で処理の登録と呼び出しを行ってみましょう。
下図のように組むとSuccessに実行ピンを繋ぐとOnSuccessが呼ばれ
Failedに実行ピンを繋ぐとOnFailedが呼びだされます。
こういった処理を書く場合はDelegateで登録することが多いですが
今回は複数実行ピンを使用したイメージとして用意してみました。
また、余談ですがMultiOutput関数は
下図のようにOutputをSwitch分岐させるのと同様の処理になります。
ですが、C++側で何か処理を加えたい場合に役立ちますし、ノードもスッキリするため
ExpandEnumAsExecs を積極的に使用した方が良いでしょう。
UE4.19.0
Visual Studio Community 2015
SpawnActorを呼び出すにはWorld, 生成位置、回転情報、名前や所有者の登録等のオプションが必要になります。
#include "Engine/World.h" #include "ExampleActor.h" void AExampleGameMode::BeginPlay() { Super::BeginPlay(); auto const World = GetWorld(); const FTransform SpawnTransform = FTransform::Identity; FActorSpawnParameters parameters; auto const exampleActor = World->SpawnActor<AExampleActor>(AExampleActor::StaticClass(), SpawnTransform, parameters); }
基本的にはこれで問題ないのですが
BeginPlayが呼び出される前に処理を行いたい場合や値を渡したいという場合もあります。
そんな場合に役立つのがSpawnActorDeferredです。
一先ずコードから見ていきましょう。
#include "Engine/World.h" #include "ExampleActor.h" void AExampleGameMode::BeginPlay() { Super::BeginPlay(); auto const World = GetWorld(); const FTransform SpawnTransform = FTransform::Identity; auto const exampleActor = World->SpawnActorDeferred<AExampleActor>(AExampleActor::StaticClass(), SpawnTransform); // BeginPlayが呼び出される前に処理したい初期化処理等 exampleActor->Initialize(); // ここでBeginPlayが呼び出される exampleActor->FinishSpawning(SpawnTransform); }
SpawnActorDeferredを利用する機会は何かしら作っていると何度も出てきます。
頭の片隅に入れておくと便利です。
UE4.19.0
Visual Studio Community 2015
Spawn Actor from ClassでActorをSpawnする際に初期化できる変数のことです。
Blueprintで設定する際は下図のように設定を行います。
Expose on Spawnにチェックを入れるのはもちろんですが
Instance Editableにもチェックを入れる必要があります。
チェックを忘れた場合はコンパイル時に警告となります。
さて、これをC++側で定義する方法についてです。
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Game", meta = (ExposeOnSpawn = true)) float ExampleExposeValue;
このようにmetaにExposeOnSpawnと書くだけでSpawn時に値を割り当てることができます。
meta = (AllowPrivateAccess = "true")
このようにmeta指定子の種類によってはtrueを文字列として囲うものもあるので、ちょっとした注意が必要です。
また、C++側で生成時に値を割り当てる時はSpawnActorDeferredを使用しますが、それはまた別の機会に紹介させていただきます。
SpawnActorDeferredについて書きました。
こちらも合わせて読んでおくと便利です。
papersloth.hatenablog.com