本文目的是将在Unreal Engine 4開發中遇到的一些問題及解決方案記錄下來,友善以後查找。
版本:4.18
問題一:
在編譯如下代碼時:
UWidgetComponent* WidgetComponent = Cast<UWidgetComponent>(this->GetComponentByClass(UWidgetComponent::StaticClass()));
報如下錯誤:
error LNK2019: unresolved external symbol
"__declspec(dllimport) private: static class UClass * __cdecl UWidgetComponent::GetPrivateStaticClass(void)"
([email protected]@@[email protected]@XZ)
referenced in function "protected: virtual void __cdecl ATankModel::BeginPlay(void)" ([email protected]@@MEAAXXZ)
從錯誤資訊中看,好像是UWidgetComponent::GetPrivateStaticClass(void)方法未找到。但實際上UWidgetComponent中并不存在此方法。而此問題實際上是由于UWidgetComponent所在的子產品UMG,沒有加入到需要編譯的子產品中造成的。修改方式為在工程的.Build.cs檔案的編譯選項中添加此子產品:
using UnrealBuildTool;
public class ClientProj : ModuleRules
{
public ClientProj(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(
new string[] { "Core", "CoreUObject", "Engine", "InputCore", "UMG" });
}
}
問題二:
在編譯如下代碼時:
template<typename T>
ValueBoxImpl<T>& getValueBox(std::shared_ptr<ValueBox> valueBox_ptr) {
return dynamic_cast<ValueBoxImpl<T>&>(*valueBox_ptr);
};
報如下錯誤:
C:\Epic Games\UE_4.18\Engine\Source\Runtime\CoreUObject\Public\Templates/Casts.h(413):
error C4541: 'dynamic_cast' used on polymorphic type 'tanx::ValueBox' with /GR-;
unpredictable behavior may result
錯誤原因是RTTI未啟用,需要在.Build.cs檔案中啟用RTTI功能:
using UnrealBuildTool;
public class ClientProj : ModuleRules
{
public ClientProj(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
bUseRTTI = true;
PublicDependencyModuleNames.AddRange(
new string[] { "Core", "CoreUObject", "Engine", "InputCore", "UMG" });
}
}
問題三:
在編譯如下代碼時:
class GameHome {
private:
AClientProjGameModeBase& gameMode;
}
報如下錯誤:
game_home.h(16): error C2143: syntax error: missing ';' before '&'
game_home.h(16): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
game_home.h(16): error C2238: unexpected token(s) preceding ';'
錯誤原因在于沒有在ATanxClientProjGameModeBase前加上class,修改後編譯通過:
class GameHome {
private:
class AClientProjGameModeBase& gameMode;
}
從這個例子可以看到,從unreal提供的類作為父類衍生出的類,在使用時最好都加上class來修飾。
問題四:
編譯打包時報如下錯誤:
error C4577: 'noexcept' used with no exception handling mode specified; termination on exception is not guaranteed. Specify /EHsc
原因在于C++中使用了exception處理的機制。修改方法是在.Build.cs檔案中打開相關的編譯選項“bEnableExceptions”:
using UnrealBuildTool;
public class ClientProj : ModuleRules
{
public ClientProj(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
bUseRTTI = true;
bEnableExceptions = true;
PublicDependencyModuleNames.AddRange(
new string[] { "Core", "CoreUObject", "Engine", "InputCore", "UMG" });
}
}
問題五:
在新開的線程中調用SpawnActor,應用會崩潰或什麼結果也沒有。
SpawnActor必須在game thread中被調用,如果不在game thread中被調用,可能會導緻系統自動退出。可以通過check(IsInGameThread());來檢測目前線程是否是game thread。
問題六:
在Plugins中設定了
bUseRTTI = true;
bEnableExceptions = true;
結果打包Windows應用時,報如下警告和錯誤:
warning C4652: compiler option 'C++ Exception Handling Unwinding' inconsistent with precompiled header; current command-line option will override that defined in the precompiled header
warning C4651: '/D_HAS_EXCEPTIONS=0' specified for precompiled header but not for current compile
error LNK2019: unresolved external symbol "__declspec(dllimport) public: __cdecl std::bad_cast::bad_cast(char const *)"
造成此問題的原因是
UE_4.18\Engine\Intermediate\Build\Win64\UE4\Development\Engine\SharedPCH.Engine.RTTI.h
在編譯成
UE_4.18\Engine\Intermediate\Build\Win64\UE4\Development\Engine\SharedPCH.Engine.RTTI.h.pch
的過程中沒有設定bEnableExceptions = true;
需要修改UE_4.18\Engine\Source\Programs\UnrealBuildTool\Configuration\UEBuildModuleCPP.cs
// 修改前
public PrecompiledHeaderInstance FindOrCreateSharedPCH(UEToolChain ToolChain, PrecompiledHeaderTemplate Template, bool bOptimizeCode, bool bUseRTTI, ActionGraph ActionGraph)
// 修改後
public PrecompiledHeaderInstance FindOrCreateSharedPCH(UEToolChain ToolChain, PrecompiledHeaderTemplate Template, bool bOptimizeCode, bool bUseRTTI, bool bEnableExceptions, ActionGraph ActionGraph)
并在此函數中添加
CompileEnvironment.bEnableExceptions = bEnableExceptions;
将
// 修改前
PrecompiledHeaderInstance Instance = FindOrCreateSharedPCH(ToolChain, Template, ModuleCompileEnvironment.bOptimizeCode, ModuleCompileEnvironment.bUseRTTI, ActionGraph);
// 修改後
PrecompiledHeaderInstance Instance = FindOrCreateSharedPCH(ToolChain, Template, ModuleCompileEnvironment.bOptimizeCode, ModuleCompileEnvironment.bUseRTTI, ModuleCompileEnvironment.bEnableExceptions, ActionGraph);
再編譯打包Windows應用時就不會報錯了。