事件处理(Handling Events)和委托(Delegate)代码示例(一)【UE4】【C++】
发布日期:2021-07-01 05:53:52
浏览次数:2
分类:技术文章
本文共 4708 字,大约阅读时间需要 15 分钟。
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 valuesAMyTriggerVolume::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 spawnedvoid AMyTriggerVolume::BeginPlay(){ Super::BeginPlay(); }// Called every framevoid 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 valuesADelegateListener::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 spawnedvoid 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 framevoid 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://panda1234lee.blog.csdn.net/article/details/63834770 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
路过按个爪印,很不错,赞一个!
[***.219.124.196]2024年04月22日 09时20分48秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
centos 更改hostname
2019-05-05
ansible 使用when判断命令
2019-05-05
Mysql 查看连接数,状态 最大并发数
2019-05-05
Docker容器安装sshd,更好操作容器
2019-05-05
linux简单部署Glustefs共享存储,防单点故障
2019-05-05
CentOS7永久,临时修改主机名
2019-05-05
配置本地yum仓库
2019-05-05
Linux搭建VNC
2019-05-05
ip与子网掩码的对应关系
2019-05-05
LVS,DR模式+Keepalived部署
2019-05-05
raid0,1,5,10的原理特点,性能区别
2019-05-05
Linux-怎样把文件内容行转为列
2019-05-05
CentOS7上部署keepalived+Haproxy+httpd
2019-05-05
简单KVM安装+桥接模式
2019-05-05
简单搭建FTP
2019-05-05
linux搭建squid正向代理
2019-05-05
Squid配置文件详解
2019-05-05
squid负载
2019-05-05
tomcat部署jenkins
2019-05-05