[UE4] 列挙型の値から表示名を取得するノードの挙動がエディタとパッケージで違うことがある


はじめに

  • 検証環境 は UE4.25.3 です。

列挙型の値から表示名を取得するノードとは…?

これのことです。

例えば、以下のような列挙型の定義があったとします。

c++
UENUM(BlueprintType)
enum class EEnumToStringElements : uint8
{
    Element_0 UMETA(DisplayName = "要素1"),
    Element_1 UMETA(DisplayName = "要素2"),
};

この場合、「要素1」「要素2」が表示名となります。
もし、以下のようにメタデータで「DisplayName」を指定していない場合…

c++
UENUM(BlueprintType)
enum class EEnumToStringElements2 : uint8
{
    Element_0,
    Element_1,
};

この場合は、「Element 1」「Element 2」が表示名となります。
(「アンダーバー」が「半角スペース」 に置き換えられるため。)

ちなみに、これを PrintString で表示するとこのようになります。

これをパッケージで見てみると…?

一見すると何も問題がないように見えますが、これをパッケージで見るとどうでしょうか?

実は、こうなります。

見ての通り、両方ともシンボル名になってました。
なので、必ず表示名が返されると思って処理を組んでいると、パッケージ化したときに痛い目を見ることになるので、気をつける必要があります。

BP で列挙型を定義してみると…?

ただし、これは列挙型が C++ で定義されている場合です。BP で定義された列挙型の場合はまた挙動が違います。

試しに以下のような列挙型を BP で作ってみました。

これを PrintString で表示してみてどうなったかというと、こうなりました。

この通り、こちらの場合はパッケージでも問題なく表示名が取得できていました。

このノードを使いたくなるときは…?

以下のような状況が想定されます。

  • デバッグ表示で列挙型の名前を表示したい。
  • シンボル名を使いたい。

前者に関しては、DisplayName 未使用で、かつ、シンボル名さえわかればいい場合であれば、このノードを使って表示名を取得してもそれほど問題がないように思えます。
逆に DisplayName を使ってる、もしくは DisplayName で指定した別の文字列を使いたい場合は DisplyaName の文字列を使わず、別途用意した文字列を使う仕組みを用意したほうが無難に思えます。

後者に関しては、UEnum::GetNameStringByValue を使った関数やこれを用いた K2_Node を用意することで対応することができそうですが、重たい話になりそうなので別途検証が必要そうです。