外部访问私有成员

模板加友元访问未被UPROPERTY标记的私有成员

  //宏定义

  #define ACCESS_MEMBER(ClassName, Member,MemberType) \
  template<auto M>\
  struct Accessor_##ClassName##Member;\
  template<class T, class U, T U::*M>\
  struct Accessor_##ClassName##Member<M> {\
  friend T& Get##Member##From##ClassName(U& u) {\
  return u.*M;\
  }\
  };\
  \
  template struct Accessor_##ClassName##Member<&ClassName::Member>;\
  MemberType& Get##Member##From##ClassName(ClassName&);\

  //在项目的某个地方,我们要取出UGameInstance类的SubsystemCollection成员,它是个private 属性,它的类型是FObjectSubsystemCollection<UGameInstanceSubsystem>

  //直接写这么一行

  ACCESS_MEMBER(UGameInstance,SubsystemCollection,FObjectSubsystemCollection<UGameInstanceSubsystem>)

  //调用,这其实是UGameInstance::Init()的内容,但是我想要自定义初始化,只能这样了

  GetSubsystemCollectionFromUGameInstance(*this).Initialize(this);

消灭编译时的奇怪报错

  • Win标头问题:Unreal重定义了Windows中的各种宏,所以需要检查整个代码项目是否引用了任何Windows头文件,包括项目的第三方库。这些标头文件应按照以下的方式包裹:

    #include "Windows/AllowWindowsPlatformTypes.h"
    THIRD_PARTY_INCLUDES_START
    // Windows + third-party includes
    
    THIRD_PARTY_INCLUDES_END
    #include "Windows/HideWindowsPlatformTypes.h"

在代码中定义GameplayTags

在代码中使用GameplayTags通常是填字符串既不优雅也不便维护,直接在代码中声明GameplayTag才是正解

//比如我们可与在一个插件的某个模块中声明

//.h文件
XXXXXXXXXX_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_Cheat_GodMode)

//.cpp文件
UE_DEFINE_GAMEPLAY_TAG_COMMENT(TAG_Cheat_GodMode, "Cheat.GodMode", "GodMode 作弊功能已在owner身上激活");

//如此一来,不需要在编辑器中设置任何Gameplay Tag,将所有标签定义到代码里,其他地方直接使用TAG_Cheat_GodMode。

引入第三方库

静态库

//xxx.Build.cs
string ThirdPartyPath => Path.GetFullPath(Path.Combine(ModuleDirectory, "../ThirdParty/"));
public XXXXX(ReadOnlyTargetRules Target) : base(Target)
{
	...
	...
	string includePath = Path.Combine(ThirdPartyPath, "include");
	PublicIncludePaths.Add(includePath);
	string libPath = Path.Combine(Path.Combine(ThirdPartyPath, "lib"), "lunasvg.lib");
	PublicAdditionalLibraries.Add(libPath);
}

动态库

//xxx.Build.cs
string ThirdPartyPath => Path.GetFullPath(Path.Combine(ModuleDirectory, "../ThirdParty/"));
public XXXXX(ReadOnlyTargetRules Target) : base(Target)
{
	...
	...

	PublicIncludePaths.Add(Path.Combine(ThirdPartyPath, "include"));
	string dllPath = Path.Combine(Path.Combine(ThirdPartyPath, "lib"), "wgpu_native.dll");
	string libPath = Path.Combine(Path.Combine(ThirdPartyPath, "lib"), "wgpu_native.dll.lib");
	PublicAdditionalLibraries.Add(libPath);

	PublicDelayLoadDLLs.Add(dllPath);
	RuntimeDependencies.Add(dllPath, libPath);
	PublicDefinitions.Add(string.Format("__EMSCRIPTEN__={0}", 0));
}

除此之外,还需要再模块启动时加载dll

void XXXXX::StartupModule()
{
	const FString BasePluginDir = IPluginManager::Get().FindPlugin("XXXXX")->GetBaseDir();
	const FString LibExamplePath = FPaths::Combine(*BasePluginDir,TEXT("Source/ThirdParty/lib/wgpu_native.dll"));
	DynamicLibHandle_WebGPU = FPlatformProcess::GetDllHandle(*LibExamplePath);
}
void XXXXX::ShutdownModule()
{
	if(DynamicLibHandle_WebGPU) FPlatformProcess::FreeDllHandle(DynamicLibHandle_WebGPU);
}

覆盖Actor父类的组件

Character类有一个CharacterMovementComponent组件,可以通过ObjectInitializer使用自己创建的组件,当然必须得是父组件的子类

ACHA_Base::ACHA_Base(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer.SetDefaultSubobjectClass<UMyMovementComponent>(
		ACharacter::CharacterMovementComponentName))
{
	......
}

UBT编译

修改MSVC工具和Windows Kti版本

https://dev.epicgames.com/documentation/zh-cn/unreal-engine/build-configuration-for-unreal-engine#windowsplatform

通过BuildConfiguration.xml可以对UBT的行为做出设置,例如:

  • WindowsSdkVersion:使用特定的Windows Kit版本

  • ToolchainVersion:使用特定的MSVC版本

Windows Kit移动位置导致的报错

别问我为什么会移动Windows Kit的安装位置,问就是VS原地拉屎

修改注册表:

  • HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Microsoft SDKs\Windows\v10.0的InstallationFolder

  • HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows Kits\Installed Roots的KitsRoot10