Description

For many years there has been a static function on UEnum called GetValueAsString which would convert an enum like EAttachmentRule::KeepWorld to the string "KeepWorld", if you passed in the explicit path to the Enum. This behavior differed from GetValueAsName which has always returned "EAttachmentRule::KeepWorld", which is the internal name. This behavior was somewhat weird, but in practice you want "KeepWorld" 99% of the time, and the parsing code will accept both variants. But if you want the string, you're going to display it somewhere like a log and you don't want to waste space on the prefix

In 4.22, a new templated helper version of GetValueAsString was added that doesn't require you to pass in the path. Unfortunately, the behavior of this function is different than the other function of the same name, and now it will always return "EAttachmentRule::KeepWorld". So, now the "new" version of the function returns the string that programmers don't want and converting to the safer same-named function will break code.

It might not make sense to just change the behavior because theoretically code written between 4.22 and 4.25 could be depending on the new behavior, and also the functions on UEnum are pretty confusing. There's also GetAuthoredNameStringByValue() which will handle user enums correctly as well, but was not switched to by default for backward compatibility concerns. There is a related but different issue in blueprints [Link Removed] where the string version actually gives you the translated string in editor builds, but the internal one in cooked builds.

All of this is a mess, so I would lean towards deprecating all of the existing enum functions that return FStrings, and change to one that always uses GetAuthoredNameStringByValue (and possibly changing that function name, I couldn't think of a good one), which is the string that programmers want 99% of the time. You can see this in practice because all of the various LexToString(EEnum) overrides always return the short name and not EEnum::ShortName. Additionally, there's really no reason to use EEnum::ShortName for the internal representation, it was just done due to backward compat concerns during the enum class conversion. As mentioned above, all of the parsing code will handle all possible variants of the enum value strings

Steps to Reproduce

Find a piece of game code that will be executed and add the following line of code:

UE_LOG(LogTemp, Log, TEXT("Enum = %s %s"), 
*UEnum::GetValueAsString(TEXT("/Script/Engine.EAttachmentRule"), EAttachmentRule::KeepWorld),
*UEnum::GetValueAsString(EAttachmentRule::KeepWorld)
);

As of 4.26, the output will be "LogTemp: Enum = KeepWorld EAttachmentRule::KeepWorld" which is not what programmers expect. Gameplay programmers would expect to get just "KeepWorld" for both

Have Comments or More Details?

There's no existing public thread on this issue, so head over to AnswerHub just mention UE-97243 in the post.

2
Login to Vote

Unresolved
ComponentCore
Affects Versions4.224.26
CreatedAug 19, 2020
UpdatedSep 8, 2020