UE4初学笔记

开放参数至蓝图

C++中常常使用UE4中的一些宏来设置想要暴露于蓝图的类、属性、方法等。

暴露类

使用UCLASS([specifiers])暴露类至蓝图,其中的specifiers在暴露类的时候并不常用,并在第一行使用GENERATED_BODY(),添加头文件#include "XXX.generated.h",如:

#include "GameFramework/Actor.h"
#include "MyActor.generated.h"

UCLASS()
class AMyActor : public AActor
{
    GENERATED_BODY()

public:
    // 设置该Actor属性的默认值
    AMyActor();

    // 每一帧都调用
    virtual void Tick( float DeltaSeconds ) override;

protected:
    // 游戏开始或产生时调用
    virtual void BeginPlay() override;
};

往往通过在编辑器中“文件 -> 添加C++类 -> 使用类引导选择父类创建类”的方式直接生成对应的模板。

暴露属性

使用UPROPERTY([specifiers])宏暴露属性至蓝图,如:

UPROPERTY([specifier, specifier, ...], [meta(key=value, key=value, ...)])
Type VariableName;

其中常用的specifier如下:

  • EditAnywhere:可通过“属性”窗口在原型和实例上进行编辑;
  • VisibleAnywhere:该属性在“属性”窗口中可见,但无法编辑,与EditAnywhere不兼容;
  • BlueprintReadWrite:可从蓝图读取或写入此属性;
  • BlueprintReadOnly:此属性在蓝图中只读,表示希望该属性作为常量出现在蓝图中;
  • Category=“XXX”:给该属性分类以便在虚幻编辑器中查询;

此处注意EditAnyWhere和BlueprintReadWrite的区别,前者表示在虚幻编辑器中可以在“属性”窗口中对该属性值进行编辑。然而若需要在蓝图脚本编辑器中设置该属性,则需要使用BlueprintReadWrite,相当于为该属性自动添加了get和set方法。

暴露函数

使用UPROPERTY([specifiers])宏暴露属性至蓝图,如:

UFUNCTION([specifier, specifier, ...], [meta(key=value, key=value, ...)])
ReturnType FunctionName([Parameter, Parameter, ...])

其中常用的specifier如下:

  • BlueprintCallable:表示此函数可以直接在蓝图中执行,函数的实现只能在C++中进行;
  • BlueprintImplementableEvent:该函数的具体实现只能在蓝图中进行。对于没有返回值的函数,可以当做一种事件来处理,不必有具体的实现。而对于有返回值的函数,则需要在蓝图编辑器中的左边栏查找该函数并进行覆写。其调用还只能在C++原生代码中进行;
  • BlueprintNativeEvent:蓝图可以调用该函数,该函数的默认实现在C++中已经完成了,但是蓝图可以对该函数进行覆盖重写。这个参数可以实现最灵活的函数调用;

注意:对于BlueprintNativeEvent函数,需要一些特殊处理:

  • 首先,要声明一个新的虚函数,函数名为 FunctionName_Implementation;
  • 其次,对该函数的C++实现要转而对该虚函数进行;
  • 最终,无论C++或者蓝图调用该函数时,都是直接使用函数的原名。

Example:

// header file
UFUNCTION(BlueprintNativeEvent)
void CountdownHasFinished();
virtual void CountdownHasFinished_Implementation();

// cpp source file
void ACountdown::CountdownHasFinished_Implementation()
{
    CountdownText->SetText(TEXT(“Go!));
}

void ACountdown::BeginPlay()
{
    Super::BeginPlay();
    CountdownHasFinished();
}

暴露结构体

游戏性类中的UStruct可包含变量,包括UProperty变量、函数和运算符。结构体的声明发生在类的声明之前。使用UStruct,不必继承自任何特定类,只需用USTRUCT(specifiers)标记该结构体,如:

USTRUCT([Specifier, Specifier, ...])
struct StructName
{
    GENERATED_USTRUCT_BODY()

    UPROPERTY([specifier, specifier, ...], [meta(key=value, key=value, ...)])
        Type VariableName;

    UFUNCTION([specifier, specifier, ...], [meta(key=value, key=value, ...)])
    ReturnType FunctionName([Parameter, Parameter, ...])
};

其中Specifier往往也就只用BlueprintType,表示结构体可以在蓝图中使用。

与UObject不同的是,UStruct不会被垃圾回收,必须自行管理其生命周期。UStruct应该是纯传统数据类型,包含UObject反射支持,可以在虚幻编辑器、蓝图操控、序列化、联网等中编辑。

代理

使用代理类似函数指针,可以以通用的但类型安全的方式调用成员函数。通过使用代理,并将其动态地绑定到任何对象的成员函数上,然后在该对象上调用函数,即使调用者不知道该对象的类型也没关系。

与标记为BlueprintImplementableEvent的UFUNCTION类似,但是UFUNCTION仅仅能在蓝图中覆写,却无法在蓝图中调用。即无法通过蓝图中的某些事件去触发。而代理则可以绑定至不同类型的事件/流程,并实现不同的流程。

单播代理和多播代理区别

单播代理仅仅能绑定一个函数,而多播代理却可以绑定多个函数。单播代理可以代理有返回值的函数,而多播代理不可以代理有返回值的函数。

绑定时单播代理使用BindXXX()等方法。根据要绑定的函数类型的不同使用不同的方法,如绑定全局函数使用BindRaw(),绑定静态函数使用BindStatic()等等。由于是单播代理,故仅能绑定一个函数,以最后绑定的函数为准。详见官方文档。常用绑定UObject方法,如:

this->StringDelegateWithoutPar.BindUObject(this, &AActorPluginDemo::FuncForDelegateNoPar);

多播代理进行绑定时则采用AddXXX()等方法。与单播代理类似。

单播代理最终使用Execute()ExecuteIfBound()执行,其中后者更安全。但要注意若有返回值,则只能使用Execute()来获取返回值。最好之前使用IsBound()确认是否已经绑定有函数。多播代理则使用Broadcast()广播所有的参数。

动态代理和非动态代理的区别

动态代理可以用于Blueprint中,而非动态代理仅能在C++中进行绑定。注意声明方式的区别!

// 声明非动态代理不需要添加参数名称
DECLARE_DELEGATE_TwoParams(DelegateName, Param1Type, Param2Type);

// 声明动态代理则需要添加参数名称
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(DynamicDelegateName, Param1Type, Param1Name, Param1Type, Param2Name);

为了动态代理能够在Blueprint中使用,则自然需要在声明对应的变量的时候添加UPROPERTY([specifiers])。其中可用于多播代理的Specifier有BlueprintAssignable、BlueprintAuthorityOnly、BlueprintAuthorityOnly、
BlueprintCallable几种,详见官方文档

之后就可以在蓝图中对该动态代理变量进行绑定,并对其实现不同的业务流程。

使用代理多播TArray

若想使用代理多播TArray到蓝图中,则参数类型必须为TArray的引用,而且要加上const关键字,否则蓝图中会报错,如:

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(DynamicDelegateName, const TArray<FSelfDefinedStruct>&, StructArray);

同样地,蓝图可调用函数中的参数若为TArray,也需要使用TArray的const引用,如:

UFUNCTION(BlueprintCallable)
void function(int32 par1, const TArray<FString>& strArr);

参考资料

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值