【UE5】配列の基本【BP & C++】

学んだこと、試したこと、気づいたことなどをまとめています。
主にC++について書いていますが、BPのノードについても少し説明をしています。

基本操作

Add

Addノードを自作する。変数のタイプはベクトルにした。

コードの型

配列.Add(要素);

配列の最後尾に要素を追加。

MyActor.h

UFUNCTION(BlueprintCallable, Category = "Actor Functions", meta = (HideSelfPin = "true"))
void VecArrayAdd(UPARAM(ref) TArray<FVector>& InVecArray, FVector AddVec);

MyActor.cpp

void AMyActor::VecArrayAdd(UPARAM(ref) TArray<FVector>& InVecArray, FVector AddVec)
{
InVecArray.Add(AddVec);
}

LENGTHは要素数を出力してくれる。Addによって要素数が1増えるのを確認できる。

実行ピンないのは役立ちそう。

MyActor.h

UFUNCTION(BlueprintPure, Category = "Actor Functions")
TArray<FVector> VecArrayAddPure(UPARAM(ref) TArray<FVector>& InVecArray, FVector AddVec);

MyActor.cpp

TArray<FVector> AMyActor::VecArrayAddPure(TArray<FVector>& InVecArray, FVector AddVec)
{
InVecArray.Add(AddVec);
return InVecArray;
}

Insert

使い方

指定した場所に要素を追加。
挿入する場所はインデックスで指定。0から数えることに注意。
挿入した分、それ以降の要素は一つずつ後ろにずれる。
インデックスを0にしたら、配列の1番はじめに追加。

インデックスとは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
「インデックス」の意味を何となく説明しています。

Insertノードを自作。

コードの型

配列.Insert(要素, インデックス);

配列のインデックスの位置に要素を挿入する。

MyActor.h

UFUNCTION(BlueprintCallable, Category = "Actor Functions", meta = (HideSelfPin = "true"))
void VecArrayInsert(UPARAM(ref) TArray<FVector>& InVecArray, FVector InsertVec, int32 InsertIndex);

MyActor.cpp

void AMyActor::VecArrayInsert(TArray<FVector>& InVecArray, FVector InsertVec, int32 InsertIndex)
{
InVecArray.Insert(InsertVec, InsertIndex);
}

MyActor.h

UFUNCTION(BlueprintPure, Category = "Actor Functions")
TArray<FVector> VecArrayInsertPure(UPARAM(ref) TArray<FVector>& InVecArray, FVector InsertVec, int32 InsertIndex);

MyActor.cpp

TArray<FVector> AMyActor::VecArrayInsertPure(TArray<FVector>& InVecArray, FVector InsertVec, int32 InsertIndex)
{
InVecArray.Insert(InsertVec, InsertIndex);
return InVecArray;
}

Append

使い方

配列に配列を追加する。
上に入力した配列の最後尾に、下に入力した配列を追加する。

Appendノードを自作。

コードの型

配列1.Append(配列2);

配列1の最後尾に配列2を追加。

MyActor.h

UFUNCTION(BlueprintCallable, Category = "Actor Functions", meta = (HideSelfPin = "true"))
void VecArrayAppend(UPARAM(ref) TArray<FVector>& InVecArray, TArray<FVector> AppendVecArray);

MyActor.cpp

void AMyActor::VecArrayAppend(TArray<FVector>& InVecArray, TArray<FVector> AppendVecArray)
{
InVecArray.Append(AppendVecArray);
}

要素数5の配列Vec Arrayに、要素数3のVec Array 2をAppendしたので、要素数は8になった。

MyActor.h

UFUNCTION(BlueprintPure, Category = "Actor Functions")
TArray<FVector> VecArrayAppendPure(UPARAM(ref) TArray<FVector>& InVecArray, TArray<FVector> AppendVecArray);

MyActor.cpp

TArray<FVector> AMyActor::VecArrayAppendPure(TArray<FVector>& InVecArray, TArray<FVector> AppendVecArray)
{
InVecArray.Append(AppendVecArray);
return InVecArray;
}

Length

使い方

入力した配列の要素の数を出力。

コードの型

配列.Num()

配列の要素数を返す。

MyActor.h

UFUNCTION(BlueprintPure, Category = "Actor Functions")
int32 VecArrayLength(UPARAM(ref) TArray<FVector>& InVecArray);

MyActor.cpp

int32 AMyActor::VecArrayLength(TArray<FVector>& InVecArray)
{
return InVecArray.Num();
}

Last Index

最後のインデックスを出力する。Lengthから1を引いた数になる。
要素数が3のときのインデックスは、
(0, 1, 2)となり、最後のインデックスの数は2になる。
0から数え始めることに起因する。

MyActor.h

UFUNCTION(BlueprintPure, Category = "Actor Functions")
int32 VecArrayLastIndex(UPARAM(ref) TArray<FVector>& InVecArray);

MyActor.cpp

int32 AMyActor::VecArrayLastIndex(TArray<FVector>& InVecArray)
{
return InVecArray.Num() - 1;
}

Get

選択したインデックスの要素を取り出すことができる。
値渡し(copy)とリファレンス渡し(ref)がある。

👇値渡し

https://wa3.i-3-i.info/word16069.html

👇リファレンス(参照)渡し

https://wa3.i-3-i.info/word16070.html

コードの型

配列[インデックス]

配列のインデックスの位置の要素を返す。

MyActor.h

UFUNCTION(BlueprintPure, Category = "Actor Functions")
FVector VecArrayGetCopy(TArray<FVector> InVecArray, int32 GetIndex);

MyActor.cpp

FVector AMyActor::VecArrayGetCopy(TArray<FVector> InVecArray, int32 GetIndex)
{
return InVecArray[GetIndex];
}

・ピンを分解すると、UE純正のものでも参照渡しにならない。

参照渡しなので、値は変化する。

参照渡しにならず、値が変化しない。Breakノードで分解しても同じ。

C++で参照渡しのGetを作りたかったが、できなかった。

ピンの形は参照渡しになっているが、値は変えられない。

👇Get(Ref)作成の失敗例。参照渡しになっていない。

MyActor.h

UFUNCTION(BlueprintPure, Category = "Actor Functions")
UPARAM(ref) FVector& VecArrayGetCopy(UPARAM(ref) TArray<FVector>& InVecArray, int32 GetIndex);

MyActor.cpp

FVector& AMyActor::VecArrayGetCopy(TArray<FVector>& InVecArray, int32 GetIndex)
{
return InVecArray[GetIndex];
}

Getノードに入れるときに、参照渡しになっていないのかもしれない。参照渡しになっているのは配列で、中身のベクトルは参照渡しをされていないのかも。
いろいろ試してもダメだったので、今回はあきらめる。もう少し学習をすすめてから再挑戦。

Contains

配列の中に、特定の要素が含まれているかをチェックする。
含まれていたらtrue、含まれていなければfalseを返す。

コードの型

配列.Contains(要素)

要素が含まれていればtrueを返す。
要素が含まれていなければ、falseを返す。

MyActor.h

UFUNCTION(BlueprintPure, Category = "Actor Functions")
bool VecArrayContain(UPARAM(ref) TArray<FVector>& InVecArray, FVector CheckVec);

MyActor.cpp

bool AMyActor::VecArrayContain(TArray<FVector>& InVecArray, FVector CheckVec)
{
	if (InVecArray.Contains(CheckVec))
	{
		return true;
	}
	else
	{
		return false;
	}
}

Find

配列の中に特定の要素を含んでいたら、そのインデックスを返す。
複数含んでいたら、1番値の小さなインデックスを返す。
含んでいなかったら-1(INDEX_NONE)を返す。

INDEX_NONEは-1と同じ。

コードの型

配列.Find(要素)

要素が含まれているインデックス(整数)を返す。
要素が含まれていなければ、INDEX_NONE(-1)を返す。

MyActor.h

UFUNCTION(BlueprintPure, Category = "Actor Functions")
	int32 VecArrayFind1(UPARAM(ref) TArray<FVector>& InVecArray, FVector CheckVec);

MyActor.cpp

int32 AMyActor::VecArrayFind1(TArray<FVector>& InVecArray, FVector CheckVec)
{
	const int32 Index = InVecArray.Find(CheckVec);
	if (Index != INDEX_NONE)
	{
		return Index;
	}
	else
	{
		return Index;
	}
}

コードの型

配列.Find(要素, 整数型変数)

要素が含まれていたら、trueを返し、整数型変数にインデックスを代入する。
要素が含まれていなければ、falseを返し、整数型変数にINDEX_NONEを代入する。

MyActor.h

UFUNCTION(BlueprintPure, Category = "Actor Functions")
	int32 VecArrayFind2(UPARAM(ref) TArray<FVector>& InVecArray, FVector CheckVec);

MyActor.cpp

int32 AMyActor::VecArrayFind2(TArray<FVector>& InVecArray, FVector CheckVec)
{
	int32 Index;
	if (InVecArray.Find(CheckVec, Index))
	{
		return Index;
	}
	else
	{
		return INDEX_NONE;
	}
}

INDEX_NONEを返したが、ここをIndexにしても同じ。

Remove

配列から要素を取り除く。
複数同じ要素が含まれていても、全て取り除く。
取り除いたらtrueを返す。
取り除いていなければfalseを返す。

コードの型

配列.Remove(要素);

配列から、指定した要素を取り除く。(同じ要素が複数あれば全て取り除く。)

MyActor.h

UFUNCTION(BlueprintCallable, Category = "Actor Functions", meta=(HideSelfPin="true"))
	bool VecArrayRemove(UPARAM(ref) TArray<FVector>& InVecArray, FVector CheckVec);

MyActor.cpp

bool AMyActor::VecArrayRemove(TArray<FVector>& InVecArray, FVector CheckVec)
{
	if (InVecArray.Contains(CheckVec))
	{
		InVecArray.Remove(CheckVec);
		return true;
	}
	else
	{
		return false;
	}
}

Remove Index

配列から、指定したインデックスの要素を取り除く。

コードの型

配列.RemoveAt(インデックス);

配列から指定したインデックスの要素を取り除く。

MyActor.h

UFUNCTION(BlueprintCallable, Category = "Actor Functions", meta = (HideSelfPin = "true"))
	void VecArrayRemoveIndex(UPARAM(ref) TArray<FVector>& InVecArray, int32 Index);

MyActor.cpp

void AMyActor::VecArrayRemoveIndex(TArray<FVector>& InVecArray, int32 Index)
{
	InVecArray.RemoveAt(Index);
}

Clear

配列から全ての要素を取り除く。

コードの型

配列.Empty();

配列から全ての要素を取り除く。

MyActor.h

UFUNCTION(BlueprintCallable, Category = "Actor Functions", meta = (HideSelfPin = "true"))
	void VecArrayClear(UPARAM(ref) TArray<FVector>& InVecArray);

MyActor.cpp

void AMyActor::VecArrayClear(TArray<FVector>& InVecArray)
{
	InVecArray.Empty();
}

イテレーション

英語:iteration

意味:反復

配列の各要素をつかって、反復処理をすることが多い。

https://wa3.i-3-i.info/word15412.html

for loop

要素数を使用

MyActor.h

UFUNCTION(BlueprintCallable, Category = "Actor Functions", meta = (HideSelfPin = "true"))
	FVector VecArraySum1(UPARAM(ref) TArray<FVector>& InVecArray);

MyActor.cpp

FVector AMyActor::VecArraySum1(TArray<FVector>& InVecArray)
{
	const int32 Num = InVecArray.Num();
	FVector Vec = FVector::ZeroVector;

	for (int32 i = 0; i < Num; i++)
	{
		Vec += VecArray[i];
	}
	return Vec;
}

Last Index を使用

MyActor.h

UFUNCTION(BlueprintCallable, Category = "Actor Functions", meta = (HideSelfPin = "true"))
	FVector VecArraySum2(UPARAM(ref) TArray<FVector>& InVecArray);

MyActor.cpp

FVector AMyActor::VecArraySum2(TArray<FVector>& InVecArray)
{
	const int32 LastIndex = InVecArray.Num() - 1;
	FVector Vec = FVector::ZeroVector;

	for (int32 i = 0; i <= LastIndex; i++)
	{
		Vec += VecArray[i];
	}
	return Vec;
}

for each loop

型を指定

MyActor.h

UFUNCTION(BlueprintCallable, Category = "Actor Functions", meta = (HideSelfPin = "true"))
	FVector VecArraySum3(UPARAM(ref) TArray<FVector>& InVecArray);

MyActor.cpp

FVector AMyActor::VecArraySum3(TArray<FVector>& InVecArray)
{
	FVector SumVec = FVector::ZeroVector;
	for (FVector Vec : InVecArray)
	{
		SumVec += Vec;
	}
	return SumVec;
}

auto

Sum3のfor文において、FVectorがautoに変わっただけ。

MyActor.h

UFUNCTION(BlueprintCallable, Category = "Actor Functions", meta = (HideSelfPin = "true"))
	FVector VecArraySum4(UPARAM(ref) TArray<FVector>& InVecArray);

MyActor.cpp

FVector AMyActor::VecArraySum4(TArray<FVector>& InVecArray)
{
	FVector SumVec = FVector::ZeroVector;
	for (auto Vec : InVecArray)
	{
		SumVec += Vec;
	}
	return SumVec;
}

Iteratorの使用

MyActor.h

UFUNCTION(BlueprintCallable, Category = "Actor Functions", meta = (HideSelfPin = "true"))
	FVector VecArraySum5(UPARAM(ref) TArray<FVector>& InVecArray);

MyActor.cpp

FVector AMyActor::VecArraySum5(TArray<FVector>& InVecArray)
{
	FVector SumVec = FVector::ZeroVector;
	for (auto It = InVecArray.CreateIterator(); It; ++It)
	{
		FVector Vec = *It;
		SumVec += Vec;
	}
	return SumVec;
}

その他

変数を選択して、Shift + Alt + R(右クリックから選択でもあり)

変数の名前を変えたいときに便利。
ヘッダファイルと、ソースファイルの両方に実行する必要あり。

変数の名前を変えたときなどにWARNINGになったときの対処法。
ノードの上で右クリック>Refresh Nodes を選択するだけ。

👇参考動画

UE4 – Blueprints to C++ Episode 5 – TArray Basics

Twitterしてます

ブログの更新をお知らせ

コメント

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