【UE5】構造体の基本【C++】

学んだこと、試したこと、気づいたことをまとめています。

はじめに

追記(2022/10/17)
下記の「Struct作成」の方法を使ったことが原因かは分かりませんが、プロジェクトを開けなくなりました。BlueprintFunctionLibraryを使えば、EnumやStructだけでなく関数も定義できるので良ければそちらを使ってください。ソースファイルを削除したりしないので、おそらく安全だと思います。記述の仕方はこの記事で書いてあることと同じです。

1.New C++ Class…を選択。

2.C++でNoneのクラスを作成する。(Structのクラスはない。)

3.名前をつけて作成。ここでは名前をGridIndexとしている。ソースファイルは削除する。(エクスプローラーで)。

Visual Studio上で削除しても、エクスプローラー上に残っている。
エクスプローラー上で削除する。

4.ヘッダファイルを書き換える。(ここでは2つの整数を宣言した。)

#pragma once

#include "GridIndex.Generated.h"

USTRUCT(BlueprintType)
struct FGridIndex
{
	GENERATED_BODY()

	UPROPERTY(BlueprintReadWrite)
	int32 X = 0;

	UPROPERTY(BlueprintReadWrite)
	int32 Y = 0;

};

👇UPROPERTYについてはこちらの記事をどうぞ。

調べたこと

Event Graph上で使える。出力ピンはSplitしてる。

イコールピンにつないだりできない。

Detailsパネルで初期値の編集が出来ない。
SpecifierにEditAnywhereを追加したら、編集できた。

参照渡しで値を変えることはできた。

BlueprintReadWriteなので、Setはできる。

値の設定

記述の型

構造体名.変数名 = 値;

FGridIndex Index;
Index.X = 10;
Index.Y = 15;

Structの変数の値を、コンストラクタで変更できるようにする。
ヘッダファイルにおいて、FORCEINLINEを使って記述する。
ここでコンストラクタとは、FGridIndex();というStructと同じ名前の関数のことを指している。

コンストラクタに引数を1つ渡すと、XとYの両方に適用。
コンストラクタに引数を値を2つ渡すと、はじめの値はXに、つぎの値はYに適用。
GridIndex.h

#pragma once

#include "GridIndex.Generated.h"

USTRUCT(BlueprintType)
struct FGridIndex
{
	GENERATED_BODY()

	FORCEINLINE FGridIndex();

	explicit FORCEINLINE FGridIndex(int32 InValue);

	explicit FORCEINLINE FGridIndex(int32 InX, int32 InY);


	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	int32 X = 0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	int32 Y = 0;

};

FORCEINLINE FGridIndex::FGridIndex()
{
}

FORCEINLINE FGridIndex::FGridIndex(const int32 InValue) : X(InValue), Y(InValue)
{
}

FORCEINLINE FGridIndex::FGridIndex(const int32 InX, const int32 InY) : X(InX), Y(InY)
{
}

コンストラクタによる値の設定を使ったBPを作成した。
Structのヘッダファイルのincludeを忘れないように気を付ける。

MyActor.h

#include "GridIndex.h"
UFUNCTION(BlueprintPure, Category = "Actor Functions")
	void OutGridIndices(FGridIndex& Index1, FGridIndex& Index2);

MyActor.cpp

void AMyActor::OutGridIndices(FGridIndex& Index1, FGridIndex& Index2)
{
	Index1 = FGridIndex(3, 4);
	Index2 = FGridIndex(15);
}

3と出力される。

Structを作成するBPを作成した。
MyActor.h

#include "GridIndex.h"
UFUNCTION(BlueprintPure, Category = "Actor Functions")
	FGridIndex MakeGridIndex(int32 InX, int32 InY);

MyActor.cpp

FGridIndex AMyActor::MakeGridIndex(int32 InX, int32 InY)
{
	return FGridIndex(InX, InY);
}

9が出力。

意味:明示的な

発音:eksplísɪt(米国英語)
反意語:implicit 暗黙の
(関連)
explicitな定義

explicit FORCEINLINE FGridIndex(int32 InValue);

implicitな定義

FORCEINLINE FGridIndex(int32 InValue);

implicitではできるが、explicitではできない表現

FGridIndex Index = 4;

上の表現は、次の表現と同じ。

FGridIndex Index = FGridIndex(4);

explicitはコンストラクタを明示的に使う必要がある。
implicitではコンストラクタを省略できる。もちろん省略しなくても大丈夫。

indexの複数形
発音:índəsìːz(米国英語)

2つのStructをOutputするだけのBP。引数2つをimplicitに記述する方法が分からなかった。
GridIndex.h

FORCEINLINE FGridIndex(int32 InValue);
FORCEINLINE FGridIndex(int32 InX, int32 InY);

MyActor.h

#include "GridIndex.h"
UFUNCTION(BlueprintPure, Category = "Actor Functions")
	void OutGridIndices(FGridIndex& Index1, FGridIndex& Index2);

MyActor.cpp(引数2つは諦めた。)

void AMyActor::OutGridIndices(FGridIndex& Index1, FGridIndex& Index2)
{
	Index1 = FGridIndex(3,4);
	Index2 = 15;
}

👇両方とも4が出力。

Index1 = (3,4);

👇両方とも3が出力。

Index1 = 3,4;

演算子の設定

Struct間の演算子を定義する。また、それを用いてBPを作ってみる。

2つの整数が両方とも等しいとき、==だと定義した。

GridIndex.h

struct FGridIndex
{
// 該当箇所以外省略	
	bool operator==(const FGridIndex& V) const;
	
};
FORCEINLINE bool FGridIndex::operator==(const FGridIndex& V) const
{
	return X == V.X && Y == V.Y;
}

MyActor.h

UFUNCTION(BlueprintPure, Category = "Actor Functions")
	bool GridEquals(FGridIndex Index1, FGridIndex Index2);

MyActor.cpp

bool AMyActor::GridEquals(FGridIndex Index1, FGridIndex Index2)
{
	if (Index1 == Index2)
	{
		return true;
	}
	else
	{
		return false;
	}
}

2つの整数のうち少なくとも1つが等しくないとき、!=だと定義した。

GridIndex.h

struct FGridIndex
{
// 該当箇所以外省略	
	bool operator!=(const FGridIndex& V) const;
};
FORCEINLINE bool FGridIndex::operator!=(const FGridIndex& V) const
{
	return X != V.X || Y != V.Y;
}

MyActor.h

UFUNCTION(BlueprintPure, Category = "Actor Functions")
	bool GridNotEquals(FGridIndex Index1, FGridIndex Index2);

MyActor.cpp

bool AMyActor::GridNotEquals(FGridIndex Index1, FGridIndex Index2)
{
	if (Index1 != Index2)
	{
		return true;
	}
	else
	{
		return false;
	}
}

2種類の整数を、それぞれ足し合わせるように定義した。
GridIndex.h

struct FGridIndex
{
// 該当箇所以外省略	
	FGridIndex operator+(const FGridIndex& V) const;
};
FORCEINLINE FGridIndex FGridIndex::operator+(const FGridIndex& V) const
{
	return FGridIndex(X + V.X, Y + V.Y);
}

MyActor.h

UFUNCTION(BlueprintPure, Category = "Actor Functions")
	FGridIndex GridAdd(FGridIndex Index1, FGridIndex Index2);

MyActor.cpp

FGridIndex AMyActor::GridAdd(FGridIndex Index1, FGridIndex Index2)
{
	return Index1 + Index2;
}

コンストラクタとStruct間の演算子をしようせずに、減算のBPを作ってみた。

MyActor.h

UFUNCTION(BlueprintPure, Category = "Actor Functions")
	FGridIndex GridSubtract(FGridIndex Index1, FGridIndex Index2);

MyActor.cpp

FGridIndex AMyActor::GridSubtract(FGridIndex Index1, FGridIndex Index2)
{
	FGridIndex Index;
	Index.X = Index1.X - Index2.X;
	Index.Y = Index1.Y - Index2.Y;
	return Index;
}

このくらい単純な計算の場合、このやり方でも良さそう。
引数の数が増えたり計算量が増えてきたときに、コンストラクタや演算子の設定が役に立つと思う。

その他

Ctrl + F:複数選択。
Esc:選択解除。

自作のStructを使っても、とくに問題なくTMapを作れた。

MyActor.h

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MyActor")
	TMap<AMyActor*, FGridIndex> GridMap;

Wildcardとは繋げた変数に応じて形を変えてくれるピン。自作の構造体はダメみたい。少なくともデフォルトでは。

👇一覧。

👇参考動画

UE4 – Blueprints to C++ Episode 8 – Struct Basics

Twitterしてます

ブログの更新をお知らせ

コメント

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