# 蓝图函数库

此文为AssertionsBlueprint Function Libraries (opens new window)的原创翻译,本文内容版权归原文所有,仅供学习,如需转载望注本文地址,翻译不易,谢谢理解

我们在开发中经常发现需要一系列工具函数来让开发更简单。这些函数经常是无状态的,并且在各种gameplay框架代码中重复使用,在使用蓝图构建时也有同样的需求。在这个手册的之前部分里,你知道了如何将你游戏对象里的函数暴露给蓝图。但是如果你想公开工具函数,你不必将它们绑定到某个gameplay游戏对象,在这种场景里,我们使用Blueprint Function Libraries(蓝图函数库)。

蓝图函数库时一系列静态函数的集合,它们提供工具函数并且不绑定到一个特定gameplay对象上。这些库可以分组成各种逻辑函数集合,比如AI蓝图库,或者提供到不同功能区域入口的工具函数,比如系统蓝图库。

创建一个蓝图函数库和使用UFUNCTION()宏将一个函数暴露给蓝图是比较相似的。所有的蓝图函数库继承自UBlueprintFunctionLibrary而不是Actor或者UObject,它们应该只包含静态方法。下面的代码是摘自Analytics Blueprint Library的代码片段,展示了如何安装类库。

UCLASS()
class UAnalyticsBlueprintLibrary :
    public UBlueprintFunctionLibrary
{
    GENERATED_UCLASS_BODY()
    /** Starts an analytics session without any custom attributes specified */
    UFUNCTION(BlueprintCallable, Category="Analytics")
    static bool StartSession();
1
2
3
4
5
6
7
8

正如你在上面看到的,一个蓝图函数库并不直接继承自UObject,所以它需要UCLASS()和GENERATED_UCLASS_BODY()宏,它还使用UFUNCTION()宏装饰在蓝图中调用的函数。蓝图函数库中的函数可被指定为BlueprintCallable或者BlueprintPure,这取决于调用是否其他作用。你可以查看/UE4/Engine/Plugins/Runtime/Analytics/AnalyticsBlueprintLibrary文件,下面是StartSession()函数的实现:

bool UAnalyticsBlueprintLibrary::StartSession()
{
    TSharedPtr<IAnalyticsProvider> Provider = FAnalytics::Get().GetDefaultConfiguredProvider();
    if (Provider.IsValid())
    {
        return Provider->StartSession();
    }
    else
    {
        UE_LOG(LogAnalyticsBPLib, Warning, TEXT("StartSession: Failed to get the default analytics provider. Double check your [Analytics] configuration in your INI"));
    }
    return false;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

注意上面的实现会和一个不是继承UObject的单例类交互,这是一个很好的方法来将第三方类库函数暴露给蓝图或者和并不需要UObject支持的C++类交互。下面的代码是一个蓝图函数库方法的例子,它能执行一些通用的工作来为一个被控制的Actor寻找AIController:

AAIController* UAIBlueprintHelperLibrary::GetAIController(AActor* ControlledActor)
{
    APawn* AsPawn = Cast<APawn>(ControlledActor);
    if (AsPawn != nullptr)
    {
        return Cast<AAIController>(AsPawn->GetController());
    }
    return Cast<AAIController>(ControlledActor);
}
1
2
3
4
5
6
7
8
9

这个函数可看成将多个蓝图节点弄成一个节点。当然,你可以在蓝图中做一个这样的函数,但是如果它经常被调用,最好用C++来实现,这样能提升性能。