PaperSloth’s diary

主にゲーム開発関連についての記事を書きます。

UE4 UFUNCTIONの種類について

環境

Visual Studio Community 2017
・Unreal Engine4.20.2


概要

UFUNCTIONの呼び出しについて日本語でまとまった情報が少なく
毎回BlueprintImplementableEventとBlueprintNativeEventあたりがごっちゃになるのでまとめる。

この記事で説明しないこと
メタデータ指定子(BlueprintAutocast, BlueprintInternalUseOnlyとかとか)
 https://docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/Reference/Metadata/DeprecatedFunction/index.html
・RPC(Client, Server, NetMulticast, Reliable, Validation)について
 RPCs | Unreal Engine Documentation



C++関数とBlueprintの連携について

BlueprintCallable

Blueprintからの呼び出しが可能になる。
UPROPERTYの場合はCategoryがなくてもエラーにならないが
UFUNCTIONはCategoryの指定がない場合エラーとなる。

UFUNCTION(BlueprintCallable, Category="Transformation")
void UpdateActorTransform(const FTransform& Transform);

f:id:PaperSloth:20180919193059p:plain

BlueprintPure

Blueprintからの呼び出しが可能。
実行ピンを持たないノードになる。
Pure関数の作成方法は下記の2種類がある。

①通常のPure関数

UFUNCTION(BlueprintPure, Category="Transformation")
FTransform GetTransformPure();

f:id:PaperSloth:20180919193139p:plain

②const指定した場合はBlueprintCallableであっても
Pure関数となり、実行ピンを持たない。

UFUNCTION(BlueprintCallable, Category="Transformation")
FTransform GetActorTransform() const;

f:id:PaperSloth:20180919193214p:plain

BlueprintImplementableEvent

Blueprintからの呼び出しが可能でC++側での実装は持たない。
BlueprintCallableを指定しない場合はBlueprint側で呼び出しはできない
C++側からは呼び出しが可能なため
意図的にBlueprintのみにロジックを書くこともできる

UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category="Vehicle")
void SpawnVehicle();

f:id:PaperSloth:20180919193324p:plain

BlueprintCallableを指定していればBlueprintからも呼び出しが可能
f:id:PaperSloth:20180919193740p:plain

戻り値がvoidの場合はEventNodeが生成されるが
戻り値を持つ関数の場合はEventではなく関数として生成される

Blueprint側でオーバーライドしたい場合は関数名を右クリックして
「Implement Function」で関数が生成される

UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category="Vehicle")
bool CanSpawnVehicle();

処理を記述する場合はOverrideして使用する
f:id:PaperSloth:20180919193434p:plain

f:id:PaperSloth:20180919193456p:plain

BlueprintNativeEvent

Blueprintからの呼び出しが可能でC++側での実装を持つ
BlueprintCallableを指定しない場合はBlueprint側で呼び出しはできない
C++で基本的な実装を行い、Blueprintでロジックを拡張する場合等に使う

UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category="Job")
void UpdateCharacterJob();

f:id:PaperSloth:20180919193927p:plain

C++側での実装は「"関数名"_Implementation」という書き方でなければならない

void AExampleActor::UpdateCharacterJob_Implementation()
{
}

C++側で関数を呼び出す場合は注意が必要
呼び出し時に_ImplementationをつけるとC++側の実装のみが呼び出される

呼び出し時に_ImplementationをつけなければBlueprint側の実装のみが呼び出される
この時にNode側でParentを呼び出していないとC++側の処理は実行されない

void AExampleActor::BeginPlay()
{
    Super::BeginPlay();
    // C++側の実装のみ呼び出し
    //UpdateCharacterJob_Implementation();

    // Blueprintの実装呼び出し
    UpdateCharacterJob();
}

その他

Categoryの階層構造について

UPROPERTY同様に"|"をつけることで階層構造になる。

UFUNCTION(BlueprintCallable, Category = "Utilities|Log")
void PrintLog(const FString& Log);

f:id:PaperSloth:20180919194145p:plain

参照について

引数を参照にした場合に入力ピンとなる場合と出力ピンとなる場合がある

①const参照の場合
入力ピンとして扱われる

UFUNCTION(BlueprintCallable, Category="Collision")
bool SimpleRayTrace(const FVector& StartLocation, const FVector& EndLocation);

f:id:PaperSloth:20180919194232p:plain

②constなしの参照の場合
出力ピンとして扱われる

UFUNCTION(BlueprintCallable, Category="Collision")
bool SimpleRayTraceHit(const FVector& StartLocation, const FVector& EndLocation, FHitResult& OutHit);

f:id:PaperSloth:20180919194304p:plain

③constなしの参照を入力として扱いたい場合
UPARAM(ref)を付けることで入力として扱われる

UFUNCTION(BlueprintCallable, Category="Collision")
bool RayTraceHit(const FVector& StartLocation, const FVector& EndLocation, UPARAM(ref)FHitResult& HitResult);

f:id:PaperSloth:20180919194341p:plain

空のUFUNCION()について

エンジンコードを眺めているといくつかUFUNCTION()を見かけます。
その中でも OnRep_ で始まる関数は変数のReplicationに関わるものです。
それ以外にもBindUFunctionを使用したデリゲートで必要な場合もあります。

コードスニペットについて

本題とは離れますが、登録しておくと快適にコードが書けるので使ってください
以前にも少し紹介しています。
Git or Perforceで落としてきたエンジンのEngine/Extras/VisualStudioSnippets以下にあります
UE4 Unreal C++を書くための環境構築 - PaperSloth’s diary

f:id:PaperSloth:20180919194545g:plain