考点: .uplugin、Build.cs、模块依赖、API 暴露、循环依赖解决方案
参考答案:
- 插件结构:
MyPlugin.uplugin(描述)+ Source/MyPluginRuntime(运行时模块)+ Source/MyPluginEditor(编辑器模块)+ Content/(资产)。
- .uplugin:声明
Modules(Name/Type/LoadingPhase)、Plugins(依赖的引擎/第三方插件)、CanContainContent。
{
"FileVersion": 3,
"FriendlyName": "My Plugin",
"CanContainContent": true,
"Modules": [
{ "Name": "MyPluginRuntime", "Type": "Runtime", "LoadingPhase": "Default" },
{ "Name": "MyPluginEditor", "Type": "Editor", "LoadingPhase": "PostEngineInit" }
],
"Plugins": [ { "Name": "GameplayAbilities", "Enabled": true } ]
}
- Build.cs:
PublicDependencyModuleNames(头文件可见)与 PrivateDependencyModuleNames(仅实现可见)分离,减少重编译范围;编辑器模块用 if (Target.bBuildEditor) 条件依赖 UnrealEd。
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "GameplayAbilities", "GameplayTags" });
PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore", "UMG" });
if (Target.bBuildEditor) { PrivateDependencyModuleNames.Add("UnrealEd"); }
- API 暴露:导出宏
XXX_API;通过 IModuleInterface 的 StartupModule/ShutdownModule 初始化,FModuleManager::LoadModuleChecked<T>() 获取模块单例;更推荐用 UGameInstanceSubsystem 承载插件业务(自动生命周期管理)。
- 循环依赖:A 依赖 B、B 依赖 A 会编译失败,三种解法:
- 提取公共接口到第三个模块(PluginInterface),双方只依赖接口;
- 模块接口模式:
FModuleManager::GetModulePtr<IPluginAService>("PluginA") 动态获取;
- 事件/委托解耦:A 声明多播委托,B 通过 Subsystem 监听而不直接依赖 A。
- LoadingPhase 控制加载时机(
PostEngineInit、Default 等),注意编辑器模块必须在引擎初始化后加载。