LoginSignup
7
7

More than 5 years have passed since last update.

[UE4] C++ で enum の foreach を行う方法

Last updated at Posted at 2018-09-12

概要

Blueprint では enum のタイプ指定で foreach をするノードがありますが、同様のことを c++ で行う方法です。

※BPでの例
スクリーンショット 2018-09-13 01.45.31.png

サンプルコード

testenum.h
UENUM(BlueprintType)
enum class ETestType1 : uint8
{
    TypeA,
    TypeB,
    TypeC,
    TypeD,
};

UENUM()
enum class ETestType2 : uint8
{
    Type1,
    Type2,
    Type3,
    Type4,

    TypeX100 = 100,
    TypeX120 = 120,
    TypeX121,
    TypeX122,

    TypeZero = 0,
    TypeOne,
    TypeTwo,
    TypeThree,
};
foreach_sample.cpp

// for ループで enum の値を LOG 出力する例.

// ETestType1.
{
    const UEnum* enumPtr = FindObject<UEnum>(ANY_PACKAGE, TEXT("ETestType1"), true);
    if (enumPtr != nullptr)
    {
        UE_LOG(LogTemp, Log, TEXT("ETestType1 num = %d"), enumPtr->NumEnums());
        for (int i = 0; i < enumPtr->NumEnums(); i++)
        {
            ETestType1 enumValue = (ETestType1)(enumPtr->GetValueByIndex(i));
            UE_LOG(LogTemp, Log, TEXT("%s = %d"), *enumPtr->GetNameByIndex(i).ToString(), (int)enumValue);
        }
    }
}

// ETestType2. // コード的には ↑ の ETestType1 とほぼ同じです.
{
    const UEnum* enumPtr = FindObject<UEnum>(ANY_PACKAGE, TEXT("ETestType2"), true);
    if (enumPtr != nullptr)
    {
        UE_LOG(LogTemp, Log, TEXT("ETestType2 num = %d"), enumPtr->NumEnums());
        for (int i = 0; i < enumPtr->NumEnums(); i++)
        {
            ETestType2 enumValue = (ETestType2)(enumPtr->GetValueByIndex(i));
            UE_LOG(LogTemp, Log, TEXT("%s = %d"), *enumPtr->GetNameByIndex(i).ToString(), (int)enumValue);
        }
    }
}

/* output result.
    LogTemp: ETestType1 num = 5
    LogTemp: ETestType1::TypeA = 0
    LogTemp: ETestType1::TypeB = 1
    LogTemp: ETestType1::TypeC = 2
    LogTemp: ETestType1::TypeD = 3
    LogTemp: ETestType1::ETestType1_MAX = 4

    LogTemp: ETestType2 num = 13
    LogTemp: ETestType2::Type1 = 0
    LogTemp: ETestType2::Type2 = 1
    LogTemp: ETestType2::Type3 = 2
    LogTemp: ETestType2::Type4 = 3
    LogTemp: ETestType2::TypeX100 = 100
    LogTemp: ETestType2::TypeX120 = 120
    LogTemp: ETestType2::TypeX121 = 121
    LogTemp: ETestType2::TypeX122 = 122
    LogTemp: ETestType2::TypeZero = 0
    LogTemp: ETestType2::TypeOne = 1
    LogTemp: ETestType2::TypeTwo = 2
    LogTemp: ETestType2::TypeThree = 3
    LogTemp: ETestType2::ETestType2_MAX = 123
*/

説明

c++ で enum to string をする手法がこちらで説明されています。
https://wiki.unrealengine.com/Enums_For_Both_C%2B%2B_and_BP

enum のタイプ名から FindObject で UEnum 型のObjetを取得し、そこから情報を取っているようで、これを参考にしました。

UEnum 型は、以下のような関数が使えます。
http://api.unrealengine.com/INT/API/Runtime/CoreUObject/UObject/UEnum/

また、ソースコードを見てみると、UEnum オブジェクトは enum の定義名の FName が Key で、int64 の値を Value として持っていることがわかります。

Engine\Source\Runtime\CoreUObject\Public\UObject\Class.h
class COREUOBJECT_API UEnum : public UField
{
        /*略*/
protected:
    /** List of pairs of all enum names and values. */
    TArray<TPair<FName, int64>> Names;

UEnum には GetValueByIndex() や GetNameByIndex() などがあるので、これらを使ってforeachを実現しています。

注意

  • UEnum オブジェクトから情報を取るには、enum に UENUM() をつけて、エンジンに対して明示する必要があります。UENUM() をつけていないと FindObject で nullptr が返ってきます。
  • UEnum 内の情報には、定義したもの以外に、最後に _MAX が自動的に追加されます。ETestType2 のログを見てもらえればわかりますが、最後の定義 +1 がMaxになるわけではないようです。

動作確認環境

UnrealEngine 4.20.2
Visual Studio Community 2015

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7