Skip to content

[UE 5.8.1] UnLua IntelliSense 为蓝图结构体和枚举生成了包含 GUID 的内部字段名 #773

Description

@0kk470

环境

  • Unreal Engine:5.8.1
  • UnLua:2.3.6
  • 平台:Windows 64-bit

问题描述

UnLua 为 Blueprint User Defined Struct 和 Blueprint User Defined Enum 生成 IntelliSense 定义时,使用了 Unreal 内部反射名称,而不是用户在编辑器中定义的原始名称。

具体表现为:

  • 结构体字段带有数字编号和 GUID 后缀。
  • 枚举项被生成为 NewEnumerator0NewEnumerator1 等内部名称。
  • Blueprint 枚举自动生成的 _MAX 占位项也会出现在 IntelliSense 中。
  • 生成的代码提示与 Lua 运行时实际使用的字段名不一致。

复现示例

创建一个 Blueprint User Defined Struct,字段如下:

CaseId
FamilyName
GivenName
Origin

UnLua 当前生成:

---@class FFTravelerCaseData
---@field public CaseId_2_017948BB457CC28338A868982DA92B21 FGuid
---@field public FamilyName_13_41C655204FB61C895543EE9CC1E14CDD string
---@field public GivenName_14_B6752E0D4806BDBBA0F9E1B88CAF1EE1 string
---@field public Origin_15_429CFC92412CA6D0B32AC1A32B139DF8 string

但 Lua 运行时实际使用用户定义的字段名:

local caseId = CaseData.CaseId
local familyName = CaseData.FamilyName

Blueprint User Defined Enum 也存在相同问题。

假设枚举定义如下:

Waiting
TravelerArriving
Inspecting
AwaitingDecision
Resolving
DayFinished

UnLua 当前生成:

---@class EInspectionState
---@field public NewEnumerator0 integer
---@field public NewEnumerator1 integer
---@field public NewEnumerator2 integer
---@field public NewEnumerator3 integer
---@field public NewEnumerator4 integer
---@field public NewEnumerator5 integer
---@field public EInspectionState_MAX integer

期望结果

结构体应当生成用户定义的字段名:

---@class FFTravelerCaseData
---@field public CaseId FGuid
---@field public FamilyName string
---@field public GivenName string
---@field public Origin string

枚举应当生成用户定义的枚举项名称,并排除自动生成的 _MAX 占位项:

---@class EInspectionState
---@field public Waiting integer
---@field public TravelerArriving integer
---@field public Inspecting integer
---@field public AwaitingDecision integer
---@field public Resolving integer
---@field public DayFinished integer

原因分析

UnLuaIntelliSense.cpp 当前使用以下旧版本接口生成结构体字段名:

Property->GetName()

对于 Blueprint User Defined Struct,GetName() 返回的是 Unreal 内部属性名称,因此会包含字段编号和 GUID。

Unreal 已经提供了对应的新接口:

FField::GetAuthoredName()

对于 User Defined Struct,该接口最终会通过:

UUserDefinedStruct::GetAuthoredNameForField()

返回用户定义的、非本地化的可读字段名。

枚举同样存在此问题。当前生成器使用:

Enum->GetNameStringByIndex(i)

对于 Blueprint User Defined Enum,该接口会返回 NewEnumerator0 等内部名称。

Unreal 提供了以下接口获取用户定义的枚举项名称:

Enum->GetAuthoredNameStringByIndex(i)

这个问题不仅影响显示效果。当前生成的 IntelliSense 注解会提示无法对应 Lua 运行时访问方式的内部名称。

建议修复

diff --git a/Source/UnLuaEditor/Private/UnLuaIntelliSense.cpp b/Source/UnLuaEditor/Private/UnLuaIntelliSense.cpp
--- a/Source/UnLuaEditor/Private/UnLuaIntelliSense.cpp
+++ b/Source/UnLuaEditor/Private/UnLuaIntelliSense.cpp
@@
 #include "Binding.h"
+#include "Engine/UserDefinedEnum.h"
 #include "ObjectEditorUtils.h"
 #include "UnLuaInterface.h"

@@
-    const int32 Num = Enum->NumEnums();
+    // Blueprint User Defined Enum 会在末尾自动添加一个内部 _MAX 项
+    const int32 Num =
+        Enum->NumEnums() - (Enum->IsA<UUserDefinedEnum>() ? 1 : 0);

     for (int32 i = 0; i < Num; ++i)
     {
+        const FString EnumValueName =
+            EscapeSymbolName(*Enum->GetAuthoredNameStringByIndex(i));
+
         Ret += FString::Printf(
             TEXT("\r\n---@field %s %s %s"),
             TEXT("public"),
-            *Enum->GetNameStringByIndex(i),
+            *EnumValueName,
             TEXT("integer")
         );
     }

@@
     FString TypeName = IntelliSense::GetTypeName(Property);
+
+    const FString PropertyName =
+        EscapeSymbolName(*Property->GetAuthoredName());
+
     Ret += FString::Printf(
         TEXT("---@field %s %s %s"),
         *AccessLevel,
-        *Property->GetName(),
+        *PropertyName,
         *TypeName
     );

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions