【UE】Unreal C++ の学習メモ(随時更新)

Unreal Engine

プリプロセッサディレクティブ

プリプロセッサは、ソースコードをコンパイラーに渡す前に実行される前処理です。

プリプロセッサ ディレクティブ | C言語

pragma once

通常、とあるヘッダーファイルを他の複数のファイルで include すると、それぞれのファイルでヘッダーファイルの内容が複数回展開され、同じ定義が複数見つかる事で重複定義エラーを引き起こす。
それを事前に防ぐするために使用されるのが「#pragma once」である。
ヘッダーファイルに「#pragma once」と記述すると、そのヘッダーファイルが 1 度だけインクルードされるようにコンパイラに指示する事が出来る。
B.h と C.h で「#include “A.h” 」と書く場合、A.h に「#pragma once」と記述すると A.h が複数回展開されなくなる。
(「#pragma once」は C++ 標準の機能ではなく、特定のコンパイラのみがサポートしている機能)

pragma region

以下のように記述する事でソースコード内の任意の範囲を折り畳む事が出来る。

#pragma region {表示名}
	//メンバ変数など
#pragma endregion

依存関係の解決

include

主に他のヘッダーファイルを現在のファイルに読み込み、その場所に展開するために使用する。

#include "{フォルダ名}/{ファイル名}.h"

using

名前空間や型の別名の定義

「using {別名} = {型名};」と記述する事で名前空間や型の別名を定義する事が出来る。
以下のコードでは FString クラスを「str」という別名で使用できるようにしている。

using str = FString;//別名を定義

void ASampleActor::Hoge()
{
	str Message = TEXT("Hello World");

	UE_LOG(LogTemp, Log, TEXT("%s"), *Message);
}

名前空間名の省略

本来なら「{名前空間名}::{関数名}()」と記述しなくてはいけない場合でも「using namespace {名前空間名};」を追加する事で「{関数名}()」のみの記述でもエラーを吐かなくなるが、その名前空間に宣言されている変数や関数と同じ名前のものがスコープ内に存在する場合は注意が必要。

#pragma once

namespace SampleNamespace
{
	void SampleFunction()
	{

        }
}
#include "SampleNamespace.h"// using のみではなく include も必要

using namespace SampleNamespace;// using で名前空間をインポート

void ASampleActor::Hoge()
{
        //本来なら「SampleNamespace::SampleFunction()」と記述しないとエラーを吐くが、using を使用する事で関数名のみの記述でもエラーを吐かなくなる
	SampleFunction();
}

前方宣言

外部のクラスのポインタや参照を使用する際、そのクラスの詳細(メンバ)を知る必要が無い場合に使用する。
include とは異なり、ヘッダーファイルを読み込む訳ではないためコンパイル時間を減らしたり、循環参照を避けたりする事が出来る。

#pragma once

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

//「#include "Camera/CameraComponent.h"」と記述してもエラーを吐かないようにする事は出来るが、依存性が強くなったり、コンパイル時間が長くなったりする恐れがある
class UCameraComponent;

UCLASS()
class SAMPLE_API ASampleActor : public AActor
{
	GENERATED_BODY()

private:
	UCameraComponent* CameraComponent;
};

マクロ

UPROPERTY

ガベージコレクションとの関係

アクセス権(全体)

プロパティ指定子レベルエディタでの閲覧レベルエディタでの編集ブループリントエディタ等での閲覧ブループリントエディタ等での編集
EditAnywhere
VisibleAnywhere不可不可
EditDefaultsOnly不可不可
VisibleDefaultsOnly不可不可不可
EditInstanceOnly不可不可
VisibleInstanceOnly不可不可不可
参考:UE4 よく使うUPROPERTYメモ

アクセス権(ブループリント)

「BlueprintReadWrite」ではブループリントから Get も Set も出来るが、

「BlueprintReadOnly」では Get しか出来なくなる。

private なメンバ変数に対するアクセス権

通常、private なメンバ変数に対して「BlueprintReadWrite」等を付けると「BlueprintReadWrite should not be used on private members」というエラーが発生する。
しかし、以下のように「AllowPrivateAccess」を true に設定する事でエラーが無くなり、ブループリントからでも private なメンバ変数にアクセス出来るようになる。

private:
	UPROPERTY(BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))//「BlueprintReadWrite」のみではエラーが発生する
	int32 Num;

「AllowPrivateAccess」を true に設定した private なメンバ変数に他の C++ クラスからアクセスしようとすると「’ASampleActor::Num’: cannot access private member declared in class ‘ASampleActor’」といったエラーが発生するが、他のクラスが C++ ではなくてブループリントの場合はアクセス出来てしまう。

TitleProperty

構造体を配列などで使用する際に以下のように記述する事で、構造体の特定のメンバの値を配列の要素のタイトルにする事が出来る。

#pragma once

#include "CoreMinimal.h"
#include "SampleStruct.generated.h"

USTRUCT(BlueprintType)
struct FSampleStruct
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere)
	FString Name;
	
	UPROPERTY(EditAnywhere)
	int32 Num;
};
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "SampleStruct.h"
#include "SampleActor.generated.h"

UCLASS()
class SAMPLE_API ASampleActor : public AActor
{
	GENERATED_BODY()

private:
	UPROPERTY(EditAnywhere, meta = (TitleProperty = "Name"))// TitleProperty には構造体のメンバの名前を設定する
	TArray<FSampleStruct> SampleStructs;
};

この例では FSampleStruct 構造体の Name という名前のメンバを配列の要素のタイトルに使用。

FString 型以外にも float 型なども配列の要素のタイトルに使用できる。

正しくないメンバの名前を「TitleProperty」に設定した場合は「Invalid Title Property!」と表示される。

キーワード

関数に対する static と const

static 関数

「UFUNCTION(BlueprintPure)」を付けた static 関数は下画像のような見た目になり、その関数を宣言しているクラスのインスタンスが無くても使用できる。
(クラスのインスタンスに依存しない)

UFUNCTION(BlueprintPure)//当然、BlueprintCallable 等でも OK
static bool StaticFunction();//前方に static を付ける

const メンバ関数

一方、関数名の後ろに const を付けた const メンバ関数は「UFUNCTION(BlueprintCallable)」であってもピュア関数のような見た目になるが、その関数を宣言しているクラスのインスタンスを Target に接続しないとコンパイルエラーが発生する。
(クラスのインスタンスに依存する)

UFUNCTION(BlueprintCallable)
bool ConstFunction() const;//後方に const を付ける

static 関数と const メンバ関数の違い

static 関数ではそのクラスの静的ではないメンバを読み取ろうとしたり、書き込もうとするとコンパイルエラーが発生するが、const メンバ関数ではそのクラスの静的ではないメンバを読み取る事が出来る。

// static 関数
bool ASampleActor::StaticFunction()
{
        // static 関数はそのクラスの静的ではないメンバを参照できないため、コンパイルエラーが発生する
	return MemberVariable;
}

// const メンバ関数
bool ASampleActor::ConstFunction() const
{
        //クラスの静的ではないメンバを読み取る事は出来るが、書き込む事は出来ない
        //MemberVariable = true;

        // static 関数ではないためコンパイルエラーは発生しない
	return MemberVariable;
}

inline

template

最後に

参考記事

プリプロセッサディレクティブ

依存関係の解決

マクロ

お問い合わせ

    タイトルとURLをコピーしました