PaperSloth’s diary

主にゲーム開発関連についての記事を書きます。

UE4 C++とUnreal C++の列挙型の扱い

目次

環境

Visual Studio Community 2015
・Unreal Engine4.16

結果

まず最初に結果を述べます。
Unreal C++では下記のような書き方が良さそうです。

UENUM(BlueprintType)
enum class EMusicType : uint8
{
    MT_Alternative UMETA(DisplayName="Alternative"),
    MT_Classic     UMETA(DisplayName="Classic"),
    MT_Dance       UMETA(DisplayName="Dance"),
    MT_Pop         UMETA(DisplayName="Pop"),
    MT_Rock        UMETA(DisplayName="Rock"),
    Num            UMETA(Hidden)
};

DisplayNameを別途分けるか下記のような記述にするかは好みの問題だと思いますので、どちらでも。
Hiddenを指定するとBlueprint側からは非表示になります。

UENUM(BlueprintType)
enum class EMusicType : uint8
{
    Alternative,
    Classic,
    Dance,
    Pop,
    Rock,
};

では長々と説明していきます。

enumの種類

先ずは通常のC++でのenumについてです。

enum Color
{
    Red,
    Green,
    Blue
};

最もよく見てきた宣言だと思います。

続いてUnreal C++でのenumについてです。
Unreal C++では"UENUM"を使用する必要があります
また、コーディング規約として接頭詞にEを付けます。

UENUM()
enum EColor
{
    Red,
    Green,
    Blue
};

これがUnreal C++での標準的な列挙型になります。
しかし、この場合は下記のようにプロパティ宣言するとエラーになります。
詳細は後ほど。

UENUM(BlueprintType)
enum EColor
{
    Red,
    Green,
    Blue
};

// ~省略~

UPROPERTY(BlueprintReadWrite, Category = Color)
EColor ColorType;

続いてC++ではnamespaceを使用して宣言を行うようになりました。
理由としてはenumの名前をグローバルスコープにしないためです。

namespace Color
{
    enum Type
    {
        Red,
        Green,
        Blue
    };
}

上記の宣言はUnreal C++でも取り入れられました。
"KismetMathLibrary.h"で宣言されているものです。

UENUM(BlueprintType)
namespace EEasingFunc
{
    enum Type
    {
        Linear,
        Step,
        SinusoidalIn,
        SinusoidalOut,
        SinusoidalInOut,
        EaseIn,
        EaseOut,
        EaseInOut,
        ExpoIn,
        ExpoOut,
        ExpoInOut,
        CircularIn,
        CircularOut,
        CircularInOut,
    };
}

しかし、この記述ではローカルで宣言されたenumは、名前空間を使用出来ません。
この場合、ローカル構造体の中にenumを宣言します。

class FontColor
{
    struct Color
    {
        enum Type
        {
            Red,
            Green,
            Blue
        };
    };
}

これに関してはUE4でも同様のようです。
フラグとして使用している部分ですので、参考としてはイマイチですが
"UnrealClient.h"内で宣言されています。

class FViewportClient
{
public:
    struct ESoundShowFlags
    {
        enum Type
        {
            Disabled = 0x00,
            Debug = 0x01,
            Sort_Distance = 0x02,
            Sort_Class = 0x04,
            Sort_Name = 0x08,
            Sort_WavesNum = 0x10,
            Sort_Disabled = 0x20,
            Long_Names = 0x40,
        };
    };
// ~省略~
}


C++11からはenum classを使ってスコープを扱えるようになりました。

enum class Color
{
    Red,
    Green,
    Blue
};

Unreal C++もベースはモダンなC++11, 14のため、早速取り入れられています。
"ReflectionCaptureComponent.h"内で定義されています。

UENUM()
enum class EReflectionSourceType : uint8
{
    CapturedScene,
    SpecifiedCubemap,
};

また、UPROPERTYでBPに公開するenumを持たせたい場合は原則としてモダンな書き方にする必要があります。

UENUM(BlueprintType)
enum class EMusicType : uint8
{
    MT_Alternative UMETA(DisplayName = "Alternative"),
    MT_Classic     UMETA(DisplayName = "Classic"),
    MT_Dance       UMETA(DisplayName = "Dance"),
    MT_Pop         UMETA(DisplayName = "Pop"),
    MT_Rock        UMETA(DisplayName = "Rock"),
};

// ~省略~
UPROPERTY(BlueprintReadWrite, Category = Music)
EMusicType MusicType;


下記の場合は全てUPROPERTYでBPに公開する事ができません。

enum EMusicType 

enum EMusicType : uint8

namespace EColorType {
    enum Type : uint8

enum class EMusicType


無事にBPに公開できれば下記のようにGetして使うことが出来ます。
f:id:PaperSloth:20170707005116p:plain


モダンなC++に対応していますが、エンジン内には一部古い定義も残っています。
それらも関数の引数やプロパティとして扱えるような書き方があります。
下記はSkinnedMeshComponent.hの例です。

UENUM()
namespace EBoneSpaces
{
    enum Type
    {
        WorldSpace     UMETA(DisplayName = "World Space"),
        ComponentSpace UMETA(DisplayName = "Component Space"),
    };
}

上記を使用する例

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Bone)
TEnumAsByte<EBoneSpaces::Type> BoneSpace;

UFUNCTION(BlueprintCallable, Category = Bone)
void UpdateBoneSpace(TEnumAsByte<EBoneSpaces::Type> boneSpace);

まとめ

UE4でもエンジンコード内に旧形式のコードがあります。
徐々にモダンなC++に移行しています。
探せばnullptrでなくNULLも残っています。
理由としては変更に対する費用対効果が薄い。というもののようです。

エラーになる箇所やバグを生む危険性のある箇所はちゃんと修正してくれています。
おとなしく待ちましょう。
そして、見つけたら報告しましょう。
できればUDNで。
https://udn.unrealengine.com/users/login.html

無理ならAnswer Hubで。
Japanese - UE4 AnswerHub

日本語の誤植等はForumで。
日本語ドキュメント 誤植&誤訳 投稿所 - Unreal Engine Forums

そして、我々Engineを使う側の人間はモダンなC++を覚えましょう。