UE4SS

在运行时把对游戏引擎的访问以可编程、脚本化、以及 C++ 模组化的方式暴露出来。它依赖引擎的反射/元数据(UClass/UProperty/UFunction 等)来安全地读取/修改对象,而不是靠硬编码内存偏移,从而在引擎或游戏更新时更稳定。


查找对象

UClass

CPP
auto* cls = UObjectGlobals::StaticFindObject<UClass*>(nullptr, nullptr, L"/Script/Engine.CameraActor")
点击展开查看更多

各种UObject

CPP
// 单例
UObject* Engine = UObjectGlobals::FindFirstOf(L"Engine");
UObject* GameUserSettings = UObjectGlobals::FindFirstOf(L"GameUserSettings")
// 非单例
std::vector<UObject*> Actors;
UObjectGlobals::FindAllOf(L"Actor", Actors);
std::vector<UObject*> Widgets;
UObjectGlobals::FindAllOf(L"Widget", Widgets);
点击展开查看更多

Actor

可以使用上面的方法UObjectGlobals::FindAllOf 或者使用原生 UE 的 API 封装:

CPP
UGameplayStatics::GetAllActorsOfClass(const UObject* WorldContextObject, class UClass* ActorClass, TArray<AActor*>& OutActors)
点击展开查看更多

查找资产

获取AssetRegistry对象

CPP
UAssetRegistry* const Registry = Cast<UAssetRegistry>(UAssetRegistryHelpers::GetAssetRegistry().ObjectPointer);
点击展开查看更多

查找资产

CPP
TArray<FAssetData> result;
// 获取全部
registry->GetAllAssets(result, true);
// 按类型查找
Registry->GetAssetsByClass(FName(L"/Script/Engine.StaticMesh"), result);
// 按路径查找
FAssetData ad = registry->GetAssetByObjectPath(FName(L"/Game/Folder/AssetName.AssetName"));
点击展开查看更多

UE 5.1+ 的 GetAssetsByClass

截至 UE4SS 3.0.1 尚未实现 UE 5.1+ 的 GetAssetsByClass

该函数的原理是调用UE函数 /Script/AssetRegistry.AssetRegistry:GetAssetsByClass(源码定义在 /Engine/Source/Runtime/AssetRegistry/Private/AssetRegistry.h

CPP
bool GetAssetsByClass(FName ClassName, TArray<FAssetData>& OutAssetData, bool bSearchSubClasses = false)
点击展开查看更多
CPP
bool GetAssetsByClass(FTopLevelAssetPath ClassPathName, TArray<FAssetData>& OutAssetData, bool bSearchSubClasses = false)
点击展开查看更多

可见 UE 5.1 将 FName 类型的参数换成了 FTopLevelAssetPath结构。 故需要手动调用如下

CPP
TArray<FAssetData> result;
if (Version::IsAtLeast(5, 1)) {
    struct GetAssetsByClass_Params
	{
	    FTopLevelAssetPath ClassName;
	    TArray<FAssetData> OutAssetData;
	    bool bSearchSubClasses;
	} params {
	    { ClassNameLeft, ClassNameRight },
	    {},
	    false
	};
    // 检查GetAssetsByClass反射
    if (!UAssetRegistry::Functions::GetAssetsByClass.IsValid()) {
        return result;
    }
    UAssetRegistry::Functions::GetAssetsByClass(registry, params);``
    result.CopyFast(params.OutAssetData);
}
点击展开查看更多

创建Actor

关键API:

CPP
AActor* UGameplayStatics::BeginDeferredActorSpawnFromClass(
	const UObject* WorldContextObject,
	class UClass* ActorClass,
	const FTransform& SpawnTransform,
	ESpawnActorCollisionHandlingMethod CollisionHandlingOverride,
	AActor* Owner
)
AActor* UGameplayStatics::FinishSpawningActor(
	AActor* Actor, 
	const FTransform& SpawnTransform
)
点击展开查看更多

UWorld封装参考:

CPP
AActor* UWorld::SpawnActor(UClass* Class, FTransform const* Transform) {
	AActor* Actor = UGameplayStatics::BeginDeferredActorSpawnFromClass(this, Class, *Transform);
	if (Actor)
	{
		UGameplayStatics::FinishSpawningActor(Actor, *Transform);
	}
	return Actor;
}
点击展开查看更多

调用函数

UFunction法

获取UFunction

CPP
const auto ufunc = (OBJ)->GetFunctionByName(FName(L"Function Name"));
const auto ufunc = (OBJ)->GetFunctionByNameInChain(FName(L"Function Name"));
点击展开查看更多

定义参数并调用

CPP
struct {
	XXX 参数A;
	XXX 参数B;
	XXX ReturnValue; // 返回值固定写法,若无返回值可不写
} params { A, B, {} };
(OBJ)->ProcessEvent(ufunc, &params); // 调用函数
params.ReturnValue // 获取返回值
点击展开查看更多

宏法

参考RE-UE4SS/deps/first/Unreal/src/AActor.cpp


操作Property

CPP
// 获取Property:GetPropertyByName 或 GetPropertyByNameInChain
auto bUnbound_FP = PostProcessVolume->GetPropertyByName(FromCharTypePtr<TCHAR>(L"bUnbound"));
auto bUnbound_FP = PostProcessVolume->GetPropertyByNameInChain(FromCharTypePtr<TCHAR>(L"bUnbound"));
// 转换到具体类型
auto bUnbound_FBP = CastField<FBoolProperty>(bUnbound_FP);
// 操作Property
bUnbound_FBP->SetPropertyValue(PostProcessVolume, true);
点击展开查看更多

注入函数

暂未涉及

版权声明

作者: Cheyne Xie

链接: https://chaim.eu.org/posts/ue4ss-c-%E5%BC%80%E5%8F%91/

许可证: CC BY-NC-SA 4.0

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Please attribute the source, use non-commercially, and maintain the same license.

开始搜索

输入关键词搜索文章内容

↑↓
ESC
⌘K 快捷键