生成兼容 UHT 的头文件

生成兼容 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

中文操作说明:

  1. 首先使用 commandlet 生成项目,再在 Rider/VS 中打开。
  2. 以下操作不分先后顺序。
  3. 查明游戏当前使用的 mod.io 版本。原文写作时为 https://github.com/modio/modio-ue4/releases/tag/v2.16.1792 。先删除现有的 Modio 文件夹,然后把该版本的 Modio、ModioTests 和 ThirdParty 文件夹复制到 Plugins/Modio/Source,替换原有 Modio 文件夹。不要替换 .uplugin 文件,而应删除其中的 ModioEx 部分。
  4. 在 CharacterSightSensor.h 的 FCharacterSightSensorDelegates 附近,添加 DECLARE_DYNAMIC_MULTICAST_DELEGATE(FCharacterSightSensorDelegate);。
  5. 在 FSDProjectileMovementComponent.h 顶部的委托区域,添加 DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnProjectilePenetrateDelegate); 和 DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnProjectileOutOfPropulsion);。这些 DECLARE_DYNAMIC_MULTICAST_DELEGATE(<\DelegateName>); 宏放在 UCLASS 上方。
  6. 注释掉以下位置的 UFUNCTION:SubHealthComponent.h 第 56 行、HealthComponentBase.h 第 117 行、HealthComponent.h 第 98 行、EnemyHealthComponent.h 第 39 行、FriendlyHealthComponent.h 第 33 行。
  7. 如果出现 ActorFunctionLibrary.gen.cpp(153): [C2664] ... cannot convert argument 2 from 'UMeshComponent *' to 'const UMeshComponent *&' 一类错误,删除报错参数前面的 const,并记得在定义桩中也删除。也可使用正则 (const) ((\w+)\*\&),替换为 $2。
  8. 在 ShowroomStage.cpp 的构造函数实现中,注释掉 this->SceneCapture = CreateDefaultSubobject<\USceneCaptureComponent2D>(TEXT("SceneCapture"));。
  9. 将支持平台设为 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.

中文操作说明:

  1. 在生成的 cyubeVR.uproject 的 Plugins 部分添加原文所示的四行,将 ChaosEditor 的 Enabled 设为 false。
  2. 复制 Source 文件夹中的 cyubeVREditor.Target.cs,命名为 cyubeVRGame.Target.cs,并将新文件中出现的 editor 替换为 game。
  3. 右键点击生成的项目,使用 IDE(例如 Rider)打开。
  4. 在 ReceiveLightActor.h 中,注释掉 UseActorCustomLocation 和 GetActorCustomLocation 对应的 UFUNCTION()。
  5. 在 EUGCMatchingUGCTypeBP.h 和 EItemPreviewTypeBP.h 中,将 _MAX UMETA(Hidden), 改为 _MAX = 0xFF UMETA(Hidden),。
  6. 删除 IpNetDriverUWorks.h 及其 cpp 文件中的构造函数。
  7. 删除以下位置的 TEnumAsByte<> 包装,但保留其中的类型:VRGripInterface.h 的 OnInput;VRGripScriptBase.h 的 OnEndPlay 及 cpp 中对应的 _Implementation;DeerCPP.h 的 SetMobilityAllEvent 及 cpp 中对应的 _Implementation。
  8. 右键点击 .uproject,选择 regenerate solution files 重新生成解决方案。
  9. 如果构建或打包时出现 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;
}

中文错误与修复说明:

  1. 枚举类出现 System.ArgumentException - String cannot contain a minus sign if the base is not 10.:删除枚举的 BlueprintType 元数据标记,以及 : uint8 底层类型覆盖。
  2. 出现 Unable to find 'class', 'delegate', 'enum', or 'struct' with name 'XYZ',其中 XYZ 是类内部使用但没有单独 UStruct 声明的 FStruct:在头文件靠近顶部的位置添加 DECLARE_DYNAMIC_MULTICAST_DELEGATE(XYZ);。
  3. 出现 is not supported by blueprint.:删除 BlueprintReadWrite 或 BlueprintCallable。
  4. 出现 cannot instantiate abstract class:如果 cpp 中已有 UAbilitySystemComponent* AActorWithGAS::GetAbilitySystemComponent() const { return nullptr; },则在头文件添加 UAbilitySystemComponent* GetAbilitySystemComponent() const override;。
  5. 出现 modifiers not allowed on static member functions:删除 const 等修饰符。例如将 static TSoftObjectPtr<Test> SomeFunction(some args) const; 末尾的 const 删除,h 和 cpp 中都要修改。
  6. 出现 '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

中文操作说明:

  1. 首先使用 commandlet 生成项目,再在 Rider/VS 中打开。以下操作不分先后顺序。
  2. 复制 EditorTarget 文件,重命名为 AstroColonyGame.Target,并在其中将目标类型改为 Game。
  3. 为以下委托在 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 内部。
  4. 在 AbilityAsync_WaitGameplayTagRemoved.h 和 AbilityAsync_WaitGameplayTagAdded.h 中,删除每个成员前面的 UAbilityAsync_WaitGameplayTag::。
  5. 在 EHSummaryViewModel.h 中添加 #include "EHSaveLoadListViewModel.h"。
  6. 对以下项目,从 UPROPERTY 宏中删除 BlueprintReadWrite/BlueprintCallable 标志,视具体情况选择:MaterialExpressionBlendMaterialAttributesBarycentric.h 的每个属性、MaterialExpressionUnpack.h 的 FExpressionInput Input、GameplayCueInterface.h 的 ForwardGameplayCueToParent。
  7. 在 MaterialPackInput.h 中添加 #include "MaterialExpressionIO.h",并删除 FExpressionInput Input; 的 UPROPERTY 宏中的 BlueprintReadWrite。
  8. 在 EAbilityTaskWaitState.h 的枚举中添加 None = 0。
  9. 在 AbilityTask.h/.cpp、UMovieSceneGameplayCueTriggerSection、UMovieSceneGameplayCueSection 中,注释掉构造函数/定义。
  10. 在 AbilitySystemComponent.h/.cpp 中,注释掉构造函数、ServerSetReplicatedEventWithPayload、ServerSetReplicatedEvent 和 ClientSetReplicatedEvent。
  11. 在 EHBaseButtonWidget.h 中添加 #include "Components/HorizontalBox.h"、#include "Components/BackgroundBlur.h"、#include "Components/SizeBox.h";删除 UHorizontalBox、UBackgroundBlur、USizeBox 的前置声明;随后注释掉 UFUNCTION(BlueprintImplementableEvent) 及 void OnInputControllerChanged(TEnumAsByte<ETGInputControllerType> InputControllerType);。
  12. 在以下位置将数组声明替换为 TArray<>,为 UPROPERTY 添加 BlueprintReadWrite 和其他常规标志,再更新 cpp 构造函数:EHPlanetoidDestructibleItem.h;EHPlanetoidVisualItem.h(还应从 SpawnDensity 删除数组);EHGridComponent.h 的 BillboardTextures;EHHUDGame.h 的 PopMenuClasses/HUDMenuClasses(同时修改 GetPopMenuClass 返回类型);EHScenarioParams.h 的 TerrainTypeSpawnChances/ShapeTypeSpawnChances;EHDataProvider.h 的所有数组。
  13. 在 VoxelProceduralMeshComponent.h/.cpp 中添加 UPrimitiveComponent 接口,采用原文完整代码示例所示的声明及定义。代码依次标明 UPrimitiveComponent、UActorComponent、UObject、Interface_CollisionDataProvider 接口的开始与结束。
  14. 代码中的 GenerateElements 注释译文:生成 Elements 数组;参数 bBuildRenderData 为 true 时,在生成元素后构建渲染数据;返回 bool,成功时为 true,失败为 false。
  15. PostLoad 中被注释的说明译文:修复旧的、创建时没有 transactional 标志的 StaticMeshComponent 组件;BuildRenderData 依赖 StaticMeshComponent 已完成 PostLoad,因此通过调用 ConditionalPostLoad 保证这一点。
  16. IsNameStableForNetworking 中的说明译文:UVoxelProceduralMeshComponent 在整个游戏会话中始终持久存在,因此可以视为具有稳定名称。
  17. 将支持平台设为 Windows。

原文:docs/guides/generating-uht-compatible-headers.md · 固定提交 560411f18512 · 来源与 MIT 许可