生成兼容 UHT 的头文件
支持的版本
UHT 头文件生成器仅正式支持 4.25+,但也曾在较旧的游戏版本上成功使用(已测试 4.18.3 和 4.17;后者存在一些默认属性问题,原文表示计划尽快修复)。它也支持 5.0+。
使用方法
生成头文件的默认快捷键为 CTRL + Numpad 9,可以在 Mods/Keybinds/Scripts/main.lua 中修改。
要充分利用生成的头文件,请参阅 Archengius 开发的 UE4GameProjectGenerator(链接指向 Buck 的分支,因为其中有几项 Arch 尚未合并的修复)。
项目生成器仅能在 UE
4.22及以上版本中编译。游戏开发者对引擎的定制可能产生意外结果。 如果要为低于4.22的引擎版本生成项目,先用4.22或更高版本编译项目生成器,再执行生成。
编译 projectgencommandlet 之前,打开 GameProjectGenerator.uproject 和游戏的 pluginmanifest 或 .uproject,把游戏使用的默认引擎插件,以及已找到开源版本或已购买的其他游戏插件,添加到 commandlet 的 uproject 文件中(不建议在公开 uproject 中包含购买的插件)。
编译 commandlet 并对游戏文件运行后,只需将生成的 .uproject 中的引擎版本改为游戏实际使用的版本。
这个 commandlet(Spuds 开发)会代你输入项目生成器的 CLI 命令,并创建一个批处理文件,方便日后使用相同设置重新生成(例如游戏大更新之后)。
可能出现的不准确生成结果
UE4SS 有两种不同的生成器:兼容 UHT 的生成器和 CXX 生成器。
使用 UE4GameProjectGenerator 创建 .uproject 时用到的是兼容 UHT 的生成器。CXX 生成器的实现则比较粗糙,不生成 UHT 宏或正确的 #include,但它能生成 UHT 生成器没有覆盖的核心 UE 类头文件。
原文指出,UE4SS CXX 转储当时没有准确的填充。如果其他来源生成的 SDK 转储具有正确填充,它可能更适合用于判断下述修正,尤其是位域检查。此为原文所述生成器的限制,不应与较新的 SDK 生成器功能混为一谈。
在较旧引擎版本中,某些默认属性可能生成不正确。例如,在低于 4.17 的版本中,SoftObjectProperty 名为 AssetObjectProperty,SoftClassProperty 名为 AssetClassProperty。建议同时生成 SDK/CXX 转储,以检查这些属性并在项目中修正。
位域始终生成成 uint8,但原始源码可能将其声明为 uint32。可以尝试根据 CXX/SDK 转储确定实际大小并修正。在 CXX 转储中,这些位域会显示相同的偏移。如果多个位域位于同一偏移,并且下一个属性位于该偏移之后 4 字节处,则应将位域改为 uint32。
常见错误处理说明
以下提供生成项目的一般说明,以及可能遇到的一些错误。错误与解决方案来自为多款游戏生成项目的实际经验。即使你的游戏不在列表中,也可以在此查找相似问题。错误列表由 Buckminsterfullerene、CheatingMuppet、Narknon 和 Blubb 整理。
继承的虚函数
如果继承的虚函数未被反射,UE4SS 就无法生成它们。这经常导致 LNK2001: unresolved external symbol 错误,尤其是在类继承接口时。构建日志通常无法直接帮助判断应在哪个文件中补充这些虚函数。
要确定应修改的文件,可以在引擎中搜索报错列出的虚函数或所属类。例如遇到 Module.AkAudio.cpp.obj : error LNK2001: unresolved external symbol "public: virtual class FString const __cdecl UInterpTrack::GetEdHelperClassName(void)const,可以搜索 GetEdHelperClassName 或 UInterpTrack。找到父类函数,再找出项目中继承该父类的类。最好在引擎中寻找另一个继承了这些虚函数的类作为修复范例,将实现复制到项目中受影响的文件,并把类名改为项目中的对应类名。
通常还应删除实现中的实际逻辑,使其仅返回正确类型的数据或“null”,而不真正执行任何逻辑。
生成游戏目标
项目生成 commandlet 不会生成游戏目标文件。在原位置复制 GameNameEditor.target.cs,从新文件名中删除 Editor。打开文件,在下图红叉位置删除 Editor,并将高亮位置的 Editor 替换为 Game。
Deep Rock Galactic
以下先保留原文的完整错误、代码和操作记录,中文操作说明紧随其后,以便查找英文错误和复制代码。
========================== First do: ==========================
Generate project using commandlet
Then open it in Rider/VS.
========================== Then do, in no particular order: ==========================
Find out what version of mod.io game currently uses. At time of writing it is https://github.com/modio/modio-ue4/releases/tag/v2.16.1792. Delete the existing 'Modio' folder first. Paste the 'Modio', 'ModioTests' and 'ThirdParty' folders from this into Plugins/Modio/Source, replacing the existing 'Modio' folder. Do not replace the .uplugin file. Delete the ModioEx section form the .uplugin file instead.
In:
- CharacterSightSensor.h, FCharacterSightSensorDelegates
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FCharacterSightSensorDelegate);
- FSDProjectileMovementComponent.h top delegates
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnProjectilePenetrateDelegate);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnProjectileOutOfPropulsion);
Add the macro DECLARE_DYNAMIC_MULTICAST_DELEGATE(<\DelegateName>); above the UCLASS
In:
- SubHealthComponent.h, line 56
- HealthComponentBase.h, line 117
- HealthComponent.h, line 98
- EnemyHealthComponent.h, line 39
- FriendlyHealthComponent.h, line 33
Comment out UFUNCTION
Errors that look like this: "ActorFunctionLibrary.gen.cpp(153): [C2664] 'void UActorFunctionLibrary::DissolveMaterials(UObject *,const UMeshComponent *&,float)': cannot convert argument 2 from 'UMeshComponent *' to 'const UMeshComponent *&'":
Remove the const before the arguments that have the error (remember to also remove them in the definition stub too)
OR use this regex string (const) ((\w+)\*\&) and replace with $2
In "ShowroomStage.cpp" inside of the implementation of the constructor, comment out "this->SceneCapture = CreateDefaultSubobject<\USceneCaptureComponent2D>(TEXT("SceneCapture"));"
Set supported platforms to windows
中文操作说明:
- 首先使用 commandlet 生成项目,再在 Rider/VS 中打开。
- 以下操作不分先后顺序。
- 查明游戏当前使用的 mod.io 版本。原文写作时为 https://github.com/modio/modio-ue4/releases/tag/v2.16.1792 。先删除现有的
Modio文件夹,然后把该版本的Modio、ModioTests和ThirdParty文件夹复制到Plugins/Modio/Source,替换原有Modio文件夹。不要替换.uplugin文件,而应删除其中的 ModioEx 部分。 - 在
CharacterSightSensor.h的FCharacterSightSensorDelegates附近,添加DECLARE_DYNAMIC_MULTICAST_DELEGATE(FCharacterSightSensorDelegate);。 - 在
FSDProjectileMovementComponent.h顶部的委托区域,添加DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnProjectilePenetrateDelegate);和DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnProjectileOutOfPropulsion);。这些DECLARE_DYNAMIC_MULTICAST_DELEGATE(<\DelegateName>);宏放在 UCLASS 上方。 - 注释掉以下位置的 UFUNCTION:
SubHealthComponent.h第 56 行、HealthComponentBase.h第 117 行、HealthComponent.h第 98 行、EnemyHealthComponent.h第 39 行、FriendlyHealthComponent.h第 33 行。 - 如果出现
ActorFunctionLibrary.gen.cpp(153): [C2664] ... cannot convert argument 2 from 'UMeshComponent *' to 'const UMeshComponent *&'一类错误,删除报错参数前面的 const,并记得在定义桩中也删除。也可使用正则(const) ((\w+)\*\&),替换为$2。 - 在
ShowroomStage.cpp的构造函数实现中,注释掉this->SceneCapture = CreateDefaultSubobject<\USceneCaptureComponent2D>(TEXT("SceneCapture"));。 - 将支持平台设为 Windows。
cyubeVR
Add the following 4 lines in the "Plugins" section in the generated "cyubeVR.uproject":
{
"Name": "ChaosEditor",
"Enabled": false
}
Copy and paste the cyubeVREditor.Target.cs file (inside Source folder) and name it cyubeVRGame.Target.cs. Then replace any mentions of "editor" and replace with "game" inside of this new file
Right click generated project and open with IDE (e.g. Rider)
Comment out UFUNCTION() in ReceiveLightActor.h
- UseActorCustomLocation
- GetActorCustomLocation
Set the "_MAX UMETA(Hidden)," to "_MAX = 0xFF UMETA(Hidden)," in:
- EUGCMatchingUGCTypeBP.h
- EItemPreviewTypeBP.h
Remove the constructor from IpNetDriverUWorks.h and cpp files.
Remove TEnumAsByte<> (but not the type inside of it) in:
- OnInput inside VRGripInterface.h
- OnEndPlay inside VRGripScriptBase.h and its _Implementation version in the .cpp file
- SetMobilityAllEvent inside DeerCPP.h and its _Implementation version in the .cpp file
Then right click the .uproject and hit "regenerate solution files".
If you get the "failed to create version memory for PCH" errors when trying to build or pack, do it again.
中文操作说明:
- 在生成的
cyubeVR.uproject的Plugins部分添加原文所示的四行,将ChaosEditor的Enabled设为false。 - 复制
Source文件夹中的cyubeVREditor.Target.cs,命名为cyubeVRGame.Target.cs,并将新文件中出现的editor替换为game。 - 右键点击生成的项目,使用 IDE(例如 Rider)打开。
- 在
ReceiveLightActor.h中,注释掉UseActorCustomLocation和GetActorCustomLocation对应的UFUNCTION()。 - 在
EUGCMatchingUGCTypeBP.h和EItemPreviewTypeBP.h中,将_MAX UMETA(Hidden),改为_MAX = 0xFF UMETA(Hidden),。 - 删除
IpNetDriverUWorks.h及其 cpp 文件中的构造函数。 - 删除以下位置的
TEnumAsByte<>包装,但保留其中的类型:VRGripInterface.h的OnInput;VRGripScriptBase.h的OnEndPlay及 cpp 中对应的_Implementation;DeerCPP.h的SetMobilityAllEvent及 cpp 中对应的_Implementation。 - 右键点击
.uproject,选择regenerate solution files重新生成解决方案。 - 如果构建或打包时出现
failed to create version memory for PCH,再执行一次。
Game 3
Error 1
In an Enum class:
System.ArgumentException - String cannot contain a minus sign if the base is not 10.
Fix:
Remove the BlueprintType meta tag and the uint8 override on the enum ': uint8'.
Error 2
Unable to find 'class', 'delegate', 'enum', or 'struct' with name 'XYZ', where XYZ is an FStruct used within a class with no separate UStruct declaration.
Fix:
DECLARE_DYNAMIC_MULTICAST_DELEGATE(XYZ); , close to the Top of header Files.
Error 3
"is not supported by blueprint."
Fix:
-> Remove BlueprintReadWrite
-> or Remove BlueprintCallable
Error 4
cannot instantiate abstract class
fix:
cpp looks like:
UAbilitySystemComponent* AActorWithGAS::GetAbilitySystemComponent() const {
return nullptr;
}
Go to Header File and add:
UAbilitySystemComponent* GetAbilitySystemComponent() const override;
Error 5
modifiers not allowed on static member functions
Fix:
Remove the modifier, like "const"
Example:
static TSoftObjectPtr<Test> SomeFunction(some args) const; <- remove const
In both h and cpp File.
Error 6
'AAkAMbientSound' no appropriate default consturctor available.
Fix:
-------
Header File
-------
AkAmbientSound();
->
AkAmbientSound(const class FObjectInitializer& ObjectInitializer);
-------
CPP File
-------
AkAmbientSound::AkAmbientSound() {
this->AkEvent = NULL;
}
->
AkAmbientSound::AkAmbientSound(const class FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) {
this->AkEvent = NULL;
}
中文错误与修复说明:
- 枚举类出现
System.ArgumentException - String cannot contain a minus sign if the base is not 10.:删除枚举的BlueprintType元数据标记,以及: uint8底层类型覆盖。 - 出现
Unable to find 'class', 'delegate', 'enum', or 'struct' with name 'XYZ',其中 XYZ 是类内部使用但没有单独 UStruct 声明的 FStruct:在头文件靠近顶部的位置添加DECLARE_DYNAMIC_MULTICAST_DELEGATE(XYZ);。 - 出现
is not supported by blueprint.:删除BlueprintReadWrite或BlueprintCallable。 - 出现
cannot instantiate abstract class:如果 cpp 中已有UAbilitySystemComponent* AActorWithGAS::GetAbilitySystemComponent() const { return nullptr; },则在头文件添加UAbilitySystemComponent* GetAbilitySystemComponent() const override;。 - 出现
modifiers not allowed on static member functions:删除 const 等修饰符。例如将static TSoftObjectPtr<Test> SomeFunction(some args) const;末尾的 const 删除,h 和 cpp 中都要修改。 - 出现
'AAkAMbientSound' no appropriate default consturctor available.:按原文示例将头文件中的AkAmbientSound();改为接收const class FObjectInitializer& ObjectInitializer,并把 cpp 构造函数改为接收该参数、通过Super(ObjectInitializer)初始化父类,保留将AkEvent设为 NULL 的代码。
Astro Colony
========================== First do: ==========================
Generate project using commandlet
Then open it in Rider/VS.
========================== Then do, in no particular order: ==========================
Copy the EditorTarget file, rename it to AstroColonyGame.Target, and inside of it change target type to Game
In:
- VoxelPhysicsPartSpawner_VoxelWorlds.h, FConfigureVoxelWorld;
- TGNamedSlot.h, FOnNamedSlotAdded/Removed
- EHLogicObject.h, FOnSelectedResourcesChanged
- EHSignalObject.h, FOnResourcesSignalOutChanged/FOnSelectedDeviceChanged
- EHInteractableServiceObject, FOnAIInsideChanged
- EHModsBrowsedOptionViewModel, FOnInstalProgressChanged/FOnInstalCompleted
- EHSaveLoadListViewModel, FOnScenarioDetailsUpdated
- EHTrainingObject, FOnTrainedChanged
- EHSchoolObject, FOnAwaitingSpecialistTrainingsChange
- EHSignalReceiver, FOnSignalSendChanged
- EHModsListViewModel, FOnModsOptionSelected
- EHSignalNetwork, FOnSignalChanged
- AbilityAsync_WaitGameplayTagAdded, FAsyncWaitGameplayTagDelegate (put it inside of AbilityAsync_WaitGameplayTag)
Add the macro DECLARE_DYNAMIC_MULTICAST_DELEGATE(<\DelegateName>); above the UCLASS
In:
- AbilityAsync_WaitGameplayTagRemoved.h
- AbilityAsync_WaitGameplayTagAdded.h
Remove the UAbilityAsync_WaitGameplayTag:: from the front of each member
In EHSummaryViewModel.h add #include "EHSaveLoadListViewModel.h"
In:
- MaterialExpressionBlendMaterialAttributesBarycentric.h (every property)
- MaterialExpressionUnpack.h (FExpressionInput Input)
- GameplayCueInterface.h (ForwardGameplayCueToParent)
remove BlueprintReadWrite/BlueprintCallable (where appropriate) flag from the 'UPROPERTY' macro.
In MaterialPackInput.h, add #include "MaterialExpressionIO.h" and remove BlueprintReadWrite flag from the 'UPROPERTY' macro for FExpressionInput Input;
In EAbilityTaskWaitState.h, add None = 0 to the enum
In:
- AbilityTask.h/.cpp
- UMovieSceneGameplayCueTriggerSection
- UMovieSceneGameplayCueSection
comment out the constructor/definition
In AbilitySystemComponent.h/.cpp, comment out:
- The constructor
- ServerSetReplicatedEventWithPayload
- ServerSetReplicatedEvent
- ClientSetReplicatedEvent
In EHBaseButtonWidget.h, add:
#include "Components/HorizontalBox.h"
#include "Components/BackgroundBlur.h"
#include "Components/SizeBox.h"
then remove the forward declarations for UHorizontalBox, UBackgroundBlur, USizeBox.
Then comment out
UFUNCTION(BlueprintImplementableEvent)
void OnInputControllerChanged(TEnumAsByte<ETGInputControllerType> InputControllerType);
In:
- EHPlanetoidDestructibleItem.h
- EHPlanetoidVisualItem.h (also remove array from SpawnDensity)
- EHGridComponent.h, BillboardTextures
- EHHUDGame.h, PopMenuClasses/HUDMenuClasses (also change GetPopMenuClass return type)
- EHScenarioParams.h, TerrainTypeSpawnChances/ShapeTypeSpawnChances
- EHDataProvider.h, every array
replace the array decleration with TArray<> and add BlueprintReadWrite+other normal flags to the 'UPROPERTY' macro. Then update the .cpp constructor.
In VoxelProceduralMeshComponent.h/.cpp, add the UPrimitiveComponent interface, i.e. like this:
VoxelProceduralMeshComponent.h:
#pragma once
#include "CoreMinimal.h"
#include "Components/ModelComponent.h"
#include "VoxelIntBox.h"
#include "VoxelProceduralMeshComponent.generated.h"
class UBodySetup;
class UStaticMeshComponent;
class AVoxelWorld;
class UModelComponent;
UCLASS(Blueprintable, ClassGroup=Custom, meta=(BlueprintSpawnableComponent))
class VOXEL_API UVoxelProceduralMeshComponent : public UModelComponent {
GENERATED_BODY()
public:
private:
UPROPERTY(BlueprintReadWrite, EditAnywhere, Transient, meta=(AllowPrivateAccess=true))
UBodySetup* BodySetup;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Transient, meta=(AllowPrivateAccess=true))
UBodySetup* BodySetupBeingCooked;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Export, Transient, meta=(AllowPrivateAccess=true))
UStaticMeshComponent* StaticMeshComponent;
public:
UVoxelProceduralMeshComponent(const FObjectInitializer& ObjectInitializer);
UFUNCTION(BlueprintCallable)
static void SetVoxelCollisionsFrozen(const AVoxelWorld* VoxelWorld, bool bFrozen);
UFUNCTION(BlueprintImplementableEvent)
void InitChunk(uint8 ChunkLOD, FVoxelIntBox ChunkBounds);
UFUNCTION(BlueprintCallable, BlueprintPure)
static bool AreVoxelCollisionsFrozen(const AVoxelWorld* VoxelWorld);
//~ Begin UPrimitiveComponent Interface.
virtual void CreateRenderState_Concurrent(FRegisterComponentContext* Context) override;
virtual void DestroyRenderState_Concurrent() override;
virtual bool GetLightMapResolution( int32& Width, int32& Height ) const override;
virtual int32 GetStaticLightMapResolution() const override;
virtual void GetLightAndShadowMapMemoryUsage( int32& LightMapMemoryUsage, int32& ShadowMapMemoryUsage ) const override;
virtual FBoxSphereBounds CalcBounds(const FTransform& LocalToWorld) const override;
virtual FPrimitiveSceneProxy* CreateSceneProxy() override;
virtual bool ShouldRecreateProxyOnUpdateTransform() const override;
#if WITH_EDITOR
virtual void GetStaticLightingInfo(FStaticLightingPrimitiveInfo& OutPrimitiveInfo,const TArray<ULightComponent*>& InRelevantLights,const FLightingBuildOptions& Options) override;
virtual void AddMapBuildDataGUIDs(TSet<FGuid>& InGUIDs) const override;
#endif
virtual ELightMapInteractionType GetStaticLightingType() const override { return LMIT_Texture; }
virtual void GetStreamingRenderAssetInfo(FStreamingTextureLevelContext& LevelContext, TArray<FStreamingRenderAssetPrimitiveInfo>& OutStreamingRenderAssets) const override;
virtual void GetUsedMaterials(TArray<UMaterialInterface*>& OutMaterials, bool bGetDebugMaterials = false) const override;
virtual class UBodySetup* GetBodySetup() override { return ModelBodySetup; };
virtual int32 GetNumMaterials() const override;
virtual UMaterialInterface* GetMaterial(int32 MaterialIndex) const override;
virtual UMaterialInterface* GetMaterialFromCollisionFaceIndex(int32 FaceIndex, int32& SectionIndex) const override;
virtual bool IsPrecomputedLightingValid() const override;
//~ End UPrimitiveComponent Interface.
//~ Begin UActorComponent Interface.
virtual void InvalidateLightingCacheDetailed(bool bInvalidateBuildEnqueuedLighting, bool bTranslationOnly) override;
virtual void PropagateLightingScenarioChange() override;
//~ End UActorComponent Interface.
//~ Begin UObject Interface.
virtual void Serialize(FArchive& Ar) override;
virtual void PostLoad() override;
virtual bool IsNameStableForNetworking() const override;
#if WITH_EDITOR
virtual void PostEditUndo() override;
#endif // WITH_EDITOR
static void AddReferencedObjects(UObject* InThis, FReferenceCollector& Collector);
//~ End UObject Interface.
//~ Begin Interface_CollisionDataProvider Interface
virtual bool GetPhysicsTriMeshData(struct FTriMeshCollisionData* CollisionData, bool InUseAllTriData) override;
virtual bool ContainsPhysicsTriMeshData(bool InUseAllTriData) const override;
virtual bool WantsNegXTriMesh() override { return false; }
//~ End Interface_CollisionDataProvider Interface
//#if WITH_EDITOR
/**
* Generate the Elements array.
*
* @param bBuildRenderData If true, build render data after generating the elements.
*
* @return bool true if successful, false if not.
*/
virtual bool GenerateElements(bool bBuildRenderData);
//#endif // WITH_EDITOR
};
VoxelProceduralMeshComponent.cpp:
#include "VoxelProceduralMeshComponent.h"
class AVoxelWorld;
void UVoxelProceduralMeshComponent::SetVoxelCollisionsFrozen(const AVoxelWorld* VoxelWorld, bool bFrozen) {
}
bool UVoxelProceduralMeshComponent::AreVoxelCollisionsFrozen(const AVoxelWorld* VoxelWorld) {
return false;
}
UVoxelProceduralMeshComponent::UVoxelProceduralMeshComponent(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
this->BodySetup = NULL;
this->BodySetupBeingCooked = NULL;
this->StaticMeshComponent = NULL;
}
void UVoxelProceduralMeshComponent::AddReferencedObjects(UObject* InThis, FReferenceCollector& Collector)
{
/*UVoxelProceduralMeshComponent* This = CastChecked<UVoxelProceduralMeshComponent>(InThis);
Collector.AddReferencedObject( This->StaticMeshComponent, This );
AddReferencedObjects( This, Collector );*/
}
void UVoxelProceduralMeshComponent::Serialize(FArchive& Ar)
{
/*Serialize(Ar);
Ar << StaticMeshComponent;*/
}
void UVoxelProceduralMeshComponent::PostLoad()
{
/*PostLoad();
// Fix for old StaticMeshComponent components which weren't created with transactional flag.
SetFlags( RF_Transactional );
// BuildRenderData relies on the StaticMeshComponent having been post-loaded, so we ensure this by calling ConditionalPostLoad.
check(StaticMeshComponent);
StaticMeshComponent->ConditionalPostLoad();*/
}
bool UVoxelProceduralMeshComponent::IsNameStableForNetworking() const
{
// UVoxelProceduralMeshComponent is always persistent for the duration of a game session, and so can be considered to have a stable name
return true;
}
void UVoxelProceduralMeshComponent::GetUsedMaterials(TArray<UMaterialInterface*>& OutMaterials, bool bGetDebugMaterials) const
{
}
int32 UVoxelProceduralMeshComponent::GetNumMaterials() const
{
return 0;
}
UMaterialInterface* UVoxelProceduralMeshComponent::GetMaterial(int32 MaterialIndex) const
{
UMaterialInterface* Material = nullptr;
return Material;
}
UMaterialInterface* UVoxelProceduralMeshComponent::GetMaterialFromCollisionFaceIndex(int32 FaceIndex, int32& SectionIndex) const
{
UMaterialInterface* Result = nullptr;
SectionIndex = 0;
return Result;
}
bool UVoxelProceduralMeshComponent::IsPrecomputedLightingValid() const
{
return false;
}
void UVoxelProceduralMeshComponent::GetStreamingRenderAssetInfo(FStreamingTextureLevelContext& LevelContext, TArray<FStreamingRenderAssetPrimitiveInfo>& OutStreamingRenderAssets) const
{
}
void UVoxelProceduralMeshComponent::CreateRenderState_Concurrent(FRegisterComponentContext* Context)
{
}
void UVoxelProceduralMeshComponent::DestroyRenderState_Concurrent()
{
}
FPrimitiveSceneProxy* UVoxelProceduralMeshComponent::CreateSceneProxy()
{
return NULL;
}
bool UVoxelProceduralMeshComponent::ShouldRecreateProxyOnUpdateTransform() const
{
return true;
}
FBoxSphereBounds UVoxelProceduralMeshComponent::CalcBounds(const FTransform& LocalToWorld) const
{
return FBoxSphereBounds(LocalToWorld.GetLocation(), FVector::ZeroVector, 0.f);
}
void UVoxelProceduralMeshComponent::InvalidateLightingCacheDetailed(bool bInvalidateBuildEnqueuedLighting, bool bTranslationOnly)
{
}
void UVoxelProceduralMeshComponent::PropagateLightingScenarioChange()
{
}
bool UVoxelProceduralMeshComponent::GetLightMapResolution( int32& Width, int32& Height ) const
{
return false;
}
int32 UVoxelProceduralMeshComponent::GetStaticLightMapResolution() const
{
/*int32 Width;
int32 Height;
GetLightMapResolution(Width, Height);
return FMath::Max<int32>(Width, Height);*/
return NULL;
}
void UVoxelProceduralMeshComponent::GetLightAndShadowMapMemoryUsage( int32& LightMapMemoryUsage, int32& ShadowMapMemoryUsage ) const
{
/*return;*/
}
#if WITH_EDITOR
void UVoxelProceduralMeshComponent::GetStaticLightingInfo(FStaticLightingPrimitiveInfo& OutPrimitiveInfo,const TArray<ULightComponent*>& InRelevantLights,const FLightingBuildOptions& Options)
{
/*check(0);*/
}
void UVoxelProceduralMeshComponent::AddMapBuildDataGUIDs(TSet<FGuid>& InGUIDs) const
{
}
void UVoxelProceduralMeshComponent::PostEditUndo()
{
/*PostEditUndo();*/
}
#endif // WITH_EDITOR
bool UVoxelProceduralMeshComponent::GetPhysicsTriMeshData(struct FTriMeshCollisionData* CollisionData, bool InUseAllTriData)
{
return false;
}
bool UVoxelProceduralMeshComponent::ContainsPhysicsTriMeshData(bool InUseAllTriData) const
{
return false;
}
bool UVoxelProceduralMeshComponent::GenerateElements(bool bBuildRenderData)
{
return false;
}
Set supported platforms to windows
中文操作说明:
- 首先使用 commandlet 生成项目,再在 Rider/VS 中打开。以下操作不分先后顺序。
- 复制 EditorTarget 文件,重命名为
AstroColonyGame.Target,并在其中将目标类型改为Game。 - 为以下委托在 UCLASS 上方添加
DECLARE_DYNAMIC_MULTICAST_DELEGATE(<\DelegateName>);:VoxelPhysicsPartSpawner_VoxelWorlds.h:FConfigureVoxelWorld。TGNamedSlot.h:FOnNamedSlotAdded/Removed。EHLogicObject.h:FOnSelectedResourcesChanged。EHSignalObject.h:FOnResourcesSignalOutChanged/FOnSelectedDeviceChanged。EHInteractableServiceObject:FOnAIInsideChanged。EHModsBrowsedOptionViewModel:FOnInstalProgressChanged/FOnInstalCompleted。EHSaveLoadListViewModel:FOnScenarioDetailsUpdated。EHTrainingObject:FOnTrainedChanged。EHSchoolObject:FOnAwaitingSpecialistTrainingsChange。EHSignalReceiver:FOnSignalSendChanged。EHModsListViewModel:FOnModsOptionSelected。EHSignalNetwork:FOnSignalChanged。AbilityAsync_WaitGameplayTagAdded:FAsyncWaitGameplayTagDelegate,放在AbilityAsync_WaitGameplayTag内部。
- 在
AbilityAsync_WaitGameplayTagRemoved.h和AbilityAsync_WaitGameplayTagAdded.h中,删除每个成员前面的UAbilityAsync_WaitGameplayTag::。 - 在
EHSummaryViewModel.h中添加#include "EHSaveLoadListViewModel.h"。 - 对以下项目,从 UPROPERTY 宏中删除
BlueprintReadWrite/BlueprintCallable标志,视具体情况选择:MaterialExpressionBlendMaterialAttributesBarycentric.h的每个属性、MaterialExpressionUnpack.h的FExpressionInput Input、GameplayCueInterface.h的ForwardGameplayCueToParent。 - 在
MaterialPackInput.h中添加#include "MaterialExpressionIO.h",并删除FExpressionInput Input;的 UPROPERTY 宏中的BlueprintReadWrite。 - 在
EAbilityTaskWaitState.h的枚举中添加None = 0。 - 在
AbilityTask.h/.cpp、UMovieSceneGameplayCueTriggerSection、UMovieSceneGameplayCueSection中,注释掉构造函数/定义。 - 在
AbilitySystemComponent.h/.cpp中,注释掉构造函数、ServerSetReplicatedEventWithPayload、ServerSetReplicatedEvent和ClientSetReplicatedEvent。 - 在
EHBaseButtonWidget.h中添加#include "Components/HorizontalBox.h"、#include "Components/BackgroundBlur.h"、#include "Components/SizeBox.h";删除UHorizontalBox、UBackgroundBlur、USizeBox的前置声明;随后注释掉UFUNCTION(BlueprintImplementableEvent)及void OnInputControllerChanged(TEnumAsByte<ETGInputControllerType> InputControllerType);。 - 在以下位置将数组声明替换为
TArray<>,为 UPROPERTY 添加BlueprintReadWrite和其他常规标志,再更新 cpp 构造函数:EHPlanetoidDestructibleItem.h;EHPlanetoidVisualItem.h(还应从 SpawnDensity 删除数组);EHGridComponent.h的BillboardTextures;EHHUDGame.h的PopMenuClasses/HUDMenuClasses(同时修改 GetPopMenuClass 返回类型);EHScenarioParams.h的TerrainTypeSpawnChances/ShapeTypeSpawnChances;EHDataProvider.h的所有数组。 - 在
VoxelProceduralMeshComponent.h/.cpp中添加 UPrimitiveComponent 接口,采用原文完整代码示例所示的声明及定义。代码依次标明 UPrimitiveComponent、UActorComponent、UObject、Interface_CollisionDataProvider 接口的开始与结束。 - 代码中的
GenerateElements注释译文:生成 Elements 数组;参数bBuildRenderData为 true 时,在生成元素后构建渲染数据;返回 bool,成功时为 true,失败为 false。 PostLoad中被注释的说明译文:修复旧的、创建时没有 transactional 标志的 StaticMeshComponent 组件;BuildRenderData 依赖 StaticMeshComponent 已完成 PostLoad,因此通过调用 ConditionalPostLoad 保证这一点。IsNameStableForNetworking中的说明译文:UVoxelProceduralMeshComponent 在整个游戏会话中始终持久存在,因此可以视为具有稳定名称。- 将支持平台设为 Windows。
原文:docs/guides/generating-uht-compatible-headers.md · 固定提交 560411f18512 · 来源与 MIT 许可