UnrealEngineのc++チュートリアルを自分なりに日本語翻訳して理解する

UnrealEngineの公式c++導入チュートリアルの4.9versionを自分なりに翻訳したものです。

c++とBluePrint

UnrealEngineでは、c++とBlueprintを使って実装ができます。
ゲームを作るためのapiやフレームワークはc++・Blueprints共にアクセスすることができます。
ここでは、c++で作成したUnrealEngineのAPIクラスを継承したものにBlueprintsからアクセス
する方法をチェックします。

c++ファイルを作る

コンテンツブラウザー(画面下部のアセット参照できる項目)で右クリックし、 新規c++クラスを選択し、c++ファイルを作成します。
または、上部のメニューからファイルをクリックし、新規c++ファイルの作成を選択します。
すると、以下の画面が表れるれるので、親クラスにActorを選択します。

ファイルネームは以下のようにします。

すると、MyActorクラスが作成されます。
プロジェクトをc++で実行できるように設定しておくと、macの場合
Xcodeが開かれ、自動で以下のようなMyActorのcppとheaderファイルが作成されます。


  #pragma once

  #include "CoreMinimal.h"
  #include "GameFramework/Actor.h"
  #include "MyActor.generated.h"

  UCLASS()
  class DOCAN_API AMyActor : public AActor
  {
  	GENERATED_BODY()

  public:
  	// Sets default values for this actor's properties
  	AMyActor();

  protected:
  	// Called when the game starts or when spawned
  	virtual void BeginPlay() override;

  public:
  	// Called every frame
  	virtual void Tick(float DeltaTime) override;
  };
  		

overlode関数BeginPlay()とTick(float DeltaTime)が自動で定義されます。
BeginPlay()はAMyActorクラスが実行可能になった際に実行される関数で
Tick()はフレーム毎に呼び出されます。

Tick()関数が不要な場合コードを削除し、constructorで呼び出されている
以下のコードを変更します。


// Sets default values
AMyActor::AMyActor()
{
 	// performanceを向上させたい場合は、falseに設定する
	PrimaryActorTick.bCanEverTick = true;

}
      

C++で設定したPropertyをEditorでアクセスする

UnrealEditorでプロパティを設定したい場合は、変数名の上に以下のように
UPROPERTY(EditAnywhere)マクロを宣言します。


UCLASS()
class AMyActor : public AActor
{
    GENERATED_BODY()
public:

    UPROPERTY(EditAnywhere)
    int32 TotalDamage;

    ...
};
      

設定したプロパティに表題(例:Damage)を与えたい場合は以下のように書きます。


UPROPERTY(EditAnywhere, Category="Damage")
int32 TotalDamage;
      

表題を与えることによって、値の管理がしやすくなります。

また、BluePrints上でプロパティを表示したい場合は以下のように書きます。


UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Damage")
int32 TotalDamage;
      

今回は、BlueprintReadWriteを選択しましたが、読み込み専用のBlueprintReadOnly
などのプロパティもあります。
Blueprintのプロパティに関しては、こちらを参照してください。

ここで、ダメージに関する以下のプロパティを追加します。


UCLASS()
class AMyActor : public AActor
{
    GENERATED_BODY()
public:

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Damage")
    int32 TotalDamage;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Damage")
    float DamageTimeInSeconds;

    UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Transient, Category="Damage")
    float DamagePerSecond;

    ...
};
      

DamageTimeInSecondsはデザイナーが変更できるプロパティです。
DamagePerSecondは計算結果を格納をするプロパティです。
Transient flagは固定値でないことを示すためのプロパティです。
これらのプロパティはUnrealEditorで以下のように表示されます。

constructorでdefault値をセットする

コンストラクタでプロパティのDefault値をセットしてみます。


AMyActor::AMyActor()
{
    TotalDamage = 200;
    DamageTimeInSeconds = 1.f;
}

AMyActor::AMyActor() :
    TotalDamage(200),
    DamageTimeInSeconds(1.f)
{
}
      

上下のコンストラクタ共に以下のようにUnrealEditorに反映されます。

Transient flagをセットしたDamagePerSecondプロパティの値をセットするためには、
PostInitProperties()をよびます。


void AMyActor::PostInitProperties()
{
    Super::PostInitProperties();
    DamagePerSecond = TotalDamage / DamageTimeInSeconds;
}
      

UnrealEditorには、以下のように表示されます。

c++のクラスをBlueprintsで拡張する

ここまで、デザイナーが変更できるようなプロパティを追加したシンプルなAMyActorクラスを作りましたが、
このクラスから新しいBlueprintクラスを作成してみます。

Selectボタンをクリックし、名前にCustomActor1と入力します。
するとContent Browserに以下のように作成されます。

ここで、UnrealEditorからTotalDamageとDamageTimeinSecondsプロパティを
変更すると、DamagePerSecondには次の表示されます。

150と表示されるべきところが200と表示されてしまっています。
下記のようなコードを書くことで、UnrealEditorで変更した値を反映することができます。


void AMyActor::PostInitProperties()
{
    Super::PostInitProperties();

    CalculateValues();
}

void AMyActor::CalculateValues()
{
    DamagePerSecond = TotalDamage / DamageTimeInSeconds;
}

#if WITH_EDITOR
void AMyActor::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
    CalculateValues();

    Super::PostEditChangeProperty(PropertyChangedEvent);
}
#endif
      

PostEditChangeProperty()を#if WITH_EDITORと#endif内に定義します。
こうすることで、余計なコードをコンパイルに加えないことで、容量を減らすことができるようです。
実行結果は以下のようになります。


void AMyActor::PostInitProperties()
{
    Super::PostInitProperties();

    CalculateValues();
}

void AMyActor::CalculateValues()
{
    DamagePerSecond = TotalDamage / DamageTimeInSeconds;
}

#if WITH_EDITOR
void AMyActor::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
    CalculateValues();

    Super::PostEditChangeProperty(PropertyChangedEvent);
}
#endif
      

C++とBlueprint間で関数を呼ぶ

ここまで、Blueprintsで、プロパティにアクセスする方法を見てきましたが、
Blueprintとc++間でお互いの関数を呼ぶ方法を見ていきます。

まず、CalculateValues()をBlueprints側から呼び出す方法です。
c++で定義したCalculateValues()の上に以下のようにマクロを定義します。


UFUNCTION(BlueprintCallable, Category="Damage")
void CalculateValues();
      

UFUNCTIONマクロはにより、リフレクションシステムにc++の関数が公開されます。
また、BlueprintCallableオプションにより、Blueprint仮装マシンに公開されます。 このように定義することで、以下のようにBlueprint内に表示されます。

上部の図のようにDamegeカテゴリ内に表示されます。
Blueprint code内では、CalculateValues()で計算されたTotalDamageが表示されています。

続いて、c++で定義されBlueprints内で実装される関数の例を見ていきます。


UFUNCTION(BlueprintImplementableEvent, Category="Damage")
void CalledFromCpp();
      

もしBlueprint内で何も実装されなかった場合、空の中身の関数が実装されますが、
以下のようにBlueprintNativeEventオプションをつけることで、
Blueprint内で実装されていない場合、c++で書かれた内容を実行させる方法があります。


UFUNCTION(BlueprintNativeEvent, Category="Damage")
void CalledFromCpp();
      

実装する中身は以下のように_Implementation().
形式で書きます。


void AMyActor::CalledFromCpp_Implementation()
{
    // Do something cool here
}
      
このエントリーをはてなブックマークに追加