UE4 C++使用蓝图(Blueprint)绑定多播委托(Multicast Delegate)

发表于2018-02-07
评论0 9.2k浏览
本篇文章将以此为案例给大家讲解如何在 C++ 中创建一个多播委托,然后在运行时通知一组的 Actors(即广播事件给监听事件的对象们)。

首先创建一个 继承自 StaticMeshActor 的类,命名为 King
King.h
// the type name of new delegate signature being created  
// the type of the signature's parameter  
// the name of the signature's parameter  
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnKingDeathSignature, AKing*, DeadKing);    // 委托签名;OnKingDeath.Broadcast 和 Peasant::flee(函数指针) 的参数类型;Peasant::flee 参数名  
UCLASS()  
class TEST_API AKing : public AStaticMeshActor  
{  
    GENERATED_BODY()  
public:   
    // Sets default values for this actor's properties  
    AKing();  
    // Called when the game starts or when spawned  
    virtual void BeginPlay() override;  
    // Called every frame  
    virtual void Tick( float DeltaSeconds ) override;  
    UFUNCTION(BlueprintCallable, Category = King)  
    void Die();// 在关卡蓝图中调用,广播委托  
    UPROPERTY(BlueprintAssignable)  //  蓝图可以动态地为委托赋予事件  
    FOnKingDeathSignature OnKingDeath;// 多播委托实例,在Broadcast之后调用该委托上的方法  
};  

注意动态多播委托的定义格式
King.cpp
// Sets default values  
AKing::AKing()  
{  
    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.  
    PrimaryActorTick.bCanEverTick = true;  
    auto MeshAsset = ConstructorHelpers::FObjectFinder<UStaticMesh>(TEXT("StaticMesh'/Engine/BasicShapes/Cone.Cone'"));  
    if (MeshAsset.Object != nullptr)  
    {  
        GetStaticMeshComponent()->SetStaticMesh(MeshAsset.Object);  
        GetStaticMeshComponent()->bGenerateOverlapEvents = true;  
    }  
    GetStaticMeshComponent()->SetMobility(EComponentMobility::Movable);  
}  
// Called when the game starts or when spawned  
void AKing::BeginPlay()  
{  
    Super::BeginPlay();  
}  
// Called every frame  
void AKing::Tick( float DeltaTime )  
{  
    Super::Tick( DeltaTime );  
}  
void AKing::Die()  
{  
    OnKingDeath.Broadcast(this);  
}  

接着,我们再新建一个类——Peasant,同样也是继承自 StaticMeshActor
Peasant.h
UCLASS()  
class TEST_API APeasant : public AStaticMeshActor  
{  
    GENERATED_BODY()  
public:  
    APeasant();  
    UFUNCTION(BlueprintCallable, category = Peasant)  
    void Flee(AKing* DeadKing); // 自定义事件所绑定的函数  
};  

在蓝图中,我们会给委托实例 OnKingDeath 绑定自定义事件(Custom Event),自定义事件绑定着 Peasant 类的 Flee 函数
Peasant.cpp
APeasant::APeasant()  
{  
    auto MeshAsset = ConstructorHelpers::FObjectFinder<UStaticMesh>(TEXT("StaticMesh'/Engine/BasicShapes/Cube.Cube'"));  
    if (MeshAsset.Object != nullptr)  
    {  
        GetStaticMeshComponent()->SetStaticMesh(MeshAsset.Object);  
        GetStaticMeshComponent()->bGenerateOverlapEvents = true;  
    }  
    GetStaticMeshComponent()->SetMobility(EComponentMobility::Movable);  
}  
// 委托上绑定的函数参数为 King 的指针,所以 Broadcast 以该指针为参数  
void APeasant::Flee(AKing* DeadKing)  
{  
    GEngine->AddOnScreenDebugMessage(-1, 2, FColor::Red, TEXT("Waily Waily!"));  
    FVector FleeVector = GetActorLocation() - DeadKing->GetActorLocation();  
    FleeVector.Normalize();  
    FleeVector *= 500;  
    SetActorLocation(GetActorLocation() + FleeVector);  
}  

这里有一个地方要特别注意,由于 Flee 传进来的是一个 King 的指针,所以需要确保调用它的时候 King 指针仍然是有效的,即不能提前调用 King 的 Destroy 方法。

然后,我们基于Peasant 类,创建一个 蓝图,命名为 BPPeasant

编辑蓝图类:

然后,我们就可以将 King 类 和若干 BPPeasant 实例拖动到场景中

编辑关卡蓝图
设定一个延时,来广播委托事件(Die 函数)

最后,我们就可以看到这样一个效果——在5秒之后, King 周围的 Peasant 都同时“远离” King。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引