博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[UE4]事件处理(Handling Events)和委托(Delegate)代码示例(一)
阅读量:4954 次
发布时间:2019-06-12

本文共 5404 字,大约阅读时间需要 18 分钟。

1. 通过重写虚函数来处理事件

MyTriggerVolume.h

自定义一个Actor类,添加一个 Box 组件作为触发区域,然后通过重写虚函数——NotifyActorBeginOverlap, NotifyActorEndOverlap来响应事件
#pragma once    #include "GameFramework/Actor.h"  #include "MyTriggerVolume.generated.h"    UCLASS()  class TEST_API AMyTriggerVolume : public AActor  {      GENERATED_BODY()        public:       // Sets default values for this actor's properties      AMyTriggerVolume();        // Called when the game starts or when spawned      virtual void BeginPlay() override;            // Called every frame      virtual void Tick( float DeltaSeconds ) override;        UPROPERTY()      UBoxComponent* TriggerZone;            UFUNCTION()      virtual void NotifyActorBeginOverlap(AActor* OtherActor) override;      UFUNCTION()      virtual void NotifyActorEndOverlap(AActor* OtherActor) override;  };

MyTriggerVolume.cpp

#include "Test.h"  #include "UE4TestGameMode.h"  #include "MyTriggerVolume.h"      // Sets default values  AMyTriggerVolume::AMyTriggerVolume()  {      // 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;      TriggerZone = CreateDefaultSubobject
("TriggerZone"); TriggerZone->SetBoxExtent(FVector(200, 200, 100));// 设置触发区域的范围 } // Called when the game starts or when spawned void AMyTriggerVolume::BeginPlay() { Super::BeginPlay(); } // Called every frame void AMyTriggerVolume::Tick( float DeltaTime ) { Super::Tick( DeltaTime ); } // 重写虚函数来响应事件 void AMyTriggerVolume::NotifyActorBeginOverlap(AActor* OtherActor) { GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Red, FString::Printf(TEXT("%s entered me"), *(OtherActor->GetName())));// 注意FString::Format需要解引用 } // 重写虚函数来响应事件 void AMyTriggerVolume::NotifyActorEndOverlap(AActor* OtherActor) { GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Red, FString::Printf(TEXT("%s left me"), *(OtherActor->GetName()))); }

2. 绑定在 UFUNCTION 函数上的委托(不带参数)

委托的好处在于,我们不用知道当前指派的函数的细节就可以调用它,它是一种安全版本的函数指针。

 

以下代码将展示如何关联 UFUNCTION 到一个委托上,即委托执行时,UFUNCTION 将被调用。

(效果为 当玩家进入触发区域,点光源亮)

 

首先在 UE4TestGameMode.h 中添加一个委托声明(在 UCLASS 之前),如下:

DECLARE_DELEGATE(FStandardDelegateSignature)

然后,为 UE4TestGameMode 类添加一个新成员

FStandardDelegateSignature MyStandardDelegate;

接着,我们新建一个 Actor 类——DelegateListener,主要实现具体方法,以及负责委托的绑定和解绑 

DelegateListener.h

UCLASS()  class TEST_API ADelegateListener : public AActor  {      GENERATED_BODY()        public:       // Sets default values for this actor's properties      ADelegateListener();        // Called when the game starts or when spawned      virtual void BeginPlay() override;            // Called every frame      virtual void Tick( float DeltaSeconds ) override;            UFUNCTION()      void EnableLight();        UFUNCTION()      virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;        UPROPERTY()      UPointLightComponent* PointLight;        };

DelegateListener.cpp

#include "Test.h"  #include "UE4TestGameMode.h" // 注意 include 的位置  #include "DelegateListener.h"      // Sets default values  ADelegateListener::ADelegateListener()  {      // 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;      PointLight = CreateDefaultSubobject
("PointLight"); RootComponent = PointLight; PointLight->SetVisibility(false); } // Called when the game starts or when spawned void ADelegateListener::BeginPlay() { Super::BeginPlay(); UWorld* TheWorld = GetWorld(); if (TheWorld != nullptr) { AGameMode* GameMode = Cast
(UGameplayStatics::GetGameMode(TheWorld)); AUE4TestGameMode * MyGameMode = Cast
(GameMode); if (MyGameMode != nullptr) { // ❤ 绑定一个基于 UObject 的成员函数的委托。UObject 委托保留了一个弱引用在你的对象上,可以通过.ExecuteIfBound() 来调用委托的函数 MyGameMode->MyStandardDelegate.BindUObject(this, &ADelegateListener::EnableLight);// 其实就是将 EnableLight 函数绑定在了委托上。 } } } // Called every frame void ADelegateListener::Tick( float DeltaTime ) { Super::Tick( DeltaTime ); } void ADelegateListener::EnableLight() { PointLight->SetVisibility(true); } void ADelegateListener::EndPlay(const EEndPlayReason::Type EndPlayReason) { Super::EndPlay(EndPlayReason); UWorld* TheWorld = GetWorld(); if (TheWorld != nullptr) { AGameMode* GameMode = Cast
(UGameplayStatics::GetGameMode(TheWorld)); AUE4TestGameMode * MyGameMode = Cast
(GameMode); if (MyGameMode != nullptr) { // 解绑委托 MyGameMode->MyStandardDelegate.Unbind(); } } }

值得注意的是,如果我们绑定的是普通的C++函数,那么就应该将 BindUObject 改为 BindRaw,如果是静态方法,那就改为 BindStatic。

 

最后,回到我们之前的 MyTriggerVolume.cpp, 利用 GameMode(我们之前声明委托和定义委托成员的地方) 执行委托,

在 NotifyActorBeginOverlap 方法中添加以下代码:

UWorld* TheWorld = GetWorld();  if (TheWorld != nullptr)  {      AGameMode* GameMode = Cast
(UGameplayStatics::GetGameMode(TheWorld)); AUE4TestGameMode * MyGameMode = Cast
(GameMode); // ❤ 执行委托的函数 MyGameMode->MyStandardDelegate.ExecuteIfBound(); }

 

转载于:https://www.cnblogs.com/timy/p/8682719.html

你可能感兴趣的文章
Linux环境下SolrCloud集群环境搭建关键步骤
查看>>
P3565 [POI2014]HOT-Hotels
查看>>
MongoDB的简单使用
查看>>
hdfs 命令使用
查看>>
prometheus配置
查看>>
定宽320 缩放适配手机屏幕
查看>>
BZOJ 2120 数颜色 【带修改莫队】
查看>>
【noip2004】虫食算——剪枝DFS
查看>>
Codeforces 40 E. Number Table
查看>>
CLR via C#(第3 版)
查看>>
java语法之final
查看>>
关于响应式布局
查看>>
详解ASP.Net 4中的aspnet_regsql.exe
查看>>
python 多进程和多线程的区别
查看>>
hdu1398
查看>>
[android] 网络断开的监听
查看>>
156.Binary Tree Upside Down
查看>>
MongoDB在windows下安装配置
查看>>
Upselling promotion stored procedure
查看>>
sigar
查看>>