实践 - Unreal Engine 4 Blueprint and C++ Programming 引擎框架(1)

C++ and Blueprints

Actor 基本函数

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

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

public:
    // Sets default values for this actor's properties
    AMyActor();

    // Called every frame
    virtual void Tick( float DeltaSeconds ) override;

protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;
};

The class wizard generates your class with BeginPlay() and Tick() specified as overloads.

这个类向导程序使用被指定为重载函数的 BeginPlay() 和 Tick() 生成你的类。


Tick() is called once per frame with the amount of elapsed time since the last call passed in.There you can do any recurring logic.

Tick() 每一帧被调用一次。这里你可编写任何需要重复调用的逻辑代码。

However if you do not need that functionality, it is best to remove it to save yourself a small amount of performance.

但是如果你不需要这个功能,最好把这个函数删除以节省性能。

If you remove it, make sure to remove the line in the constructor that indicated ticking should occur.

如果你移除该函数,必须同时要移除构造函数中的这一行(PrimaryActorTick.bCanEverTick = true;)

The constructor above contains the line in question.

下面的构造函数包含了上述问题的这一行代码。

AMyActor::AMyActor()

{

    // Set this actor to call Tick() every frame.  
    //You can turn this off to improve performance if you do not need it.

    PrimaryActorTick.bCanEverTick = true;

}

BeginPlay() is an event that lets you know the Actor has entered the game in a playable state.

BeginPlay()执行完成,表明Actor已经进入游戏并且处于一个可操作状态。

This is a good place to initiate gameplay logic for your class.

这个函数内部是启动(初始化)该类的游戏逻辑的较好的场所。

 

Actor 基本功能宏

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

    UPROPERTY(EditAnywhere)
    int32 TotalDamage;

    ...
};

TotalDamage 属性暴露给UE4编辑器。


UPROPERTY(EditAnywhere, Category="Damage")
int32 TotalDamage;

TotalDamage 属性暴露给UE4编辑器,并且让该变量显示在一个名为“Damage”的分类中。


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

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Damage")
    int32 TotalDamage;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Damage")
    float DamageTimeInSeconds;

    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Transient, Category="Damage")
    float DamagePerSecond;

    ...
};

TotalDamage, DamageTimeInSeconds, DamagePerSecond

三个属性暴露给UE4编辑器,并且三个属性在一个名为“Damage”的分类中。

针对 DamagePerSecond:

The VisibleAnywhere flag marks that property as viewable, but not editable in the Unreal Editor.

VisibleAnywhere 标志标记该属性为可查看的,但是在UE4编辑器中不可编辑。

BlueprintReadOnly 

The Transient flag means that it won't be saved or loaded from disk; it is meant to be a derived, non-persistent value. 

Transient 标志标记该属性为瞬态的,意味着该属性不会被保存到磁盘或从磁盘加载,它是一个派生的,非持久的值。

其他宏属性


Actor构造函数中为属性设置默认值(两种皆可,个人倾向后者)

AMyActor::AMyActor()
{
    TotalDamage = 200;
    DamageTimeInSeconds = 1.f;
}

AMyActor::AMyActor() :
    TotalDamage(200),
    DamageTimeInSeconds(1.f)
{
}

UE4编辑器效果图:

我们发现 DamageTimeInSeconds 即使没有在构造函数中设置默认值,它也显示除了一个值0。

If you do not provide a default value for a property,

the engine will automatically set that property to zero or nullptr in the case of pointer types.


添加一个 PostInitProperties() 函数

In order to support per instance designer set properties, values are also loaded from the instance data for a given object.

为了支持实例设计器设置属性,这些值可以从   中被加载。

This data is applied after the constructor.

这些数据在构造器执行之后再被应用。

You can create default values based off of designer set values by hooking into the PostInitProperties() call chain.

你可以通过使用 PostInitProperties() 调用链来创建默认值

Here is an example of that process where TotalDamage and DamageTimeInSeconds are designer specified values. 

 

UE4编辑器效果图:

 


Hot Reloading 热编译

 

Extending a C++ Class via Blueprints 通过蓝图扩展C++类

创建蓝图的时候可以选择父类,我们可以再搜索栏中找到自己编写的类,搜索栏中的类名与代码中的不同,将前缀去除更易于理解。

 

 

 

修改新蓝图类Damage分类中的默认值,发现无法动态计算。

Runtime changes in the Unreal Editor are not accounted for.

There is a simple solution to this problem because the engine notifies the target object when it has been changed in the editor.

The code below shows the added hooks needed to calculate the derived value as it changes in the editor.

添加一个 PostEditChangeProperty(FPropertyChangedEvent & PropertyChangedEvent) 函数,现在发现可以运行时计算了

还需要加上预编译命令 指明该函数在编辑器编译时被编译,以免损失性能

void AMyActor::PostInitProperties()
{
    Super::PostInitProperties();

    CalculateValues();
}

void AMyActor::CalculateValues()
{
    DamagePerSecond = TotalDamage / DamageTimeInSeconds;
}

#if WITH_EDITOR
void AMyActor::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
    CalculateValues();

    Super::PostEditChangeProperty(PropertyChangedEvent);
}
#endif

 

Calling Functions across the C++ and Blueprint Boundary

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值