UE 事件分发机制 day9

观察者模式原理

  • 观察者模式通常有观察者与被观察者,当被观察者状态发生改变时,它会通知所有的被观察者对象,使他们能够及时做出响应,所以也被称作“发布-订阅模式”。总得来说就是你关注了一个主播,主播的状态改变会通知这些人,关注主播的这些人都会根据主播的通知改变一些状态

观察者模式游戏工程案例(击杀怪物后的逻辑)

  • 观察者模式定义了对象之间的一对多关系,当主题对象改变状态发出通知的时候,它的所有观察者都会收到提示然后作出自己的响应
    在这里插入图片描述

事件分发机制定义

  • 通过观察者模式的“订阅-发布”机制使用事件传递数据驱动行为的方法
    在这里插入图片描述
  • 优点:
    • 解耦合
    • 可读性强
    • 模块独立化高
    • 可自行测试

虚幻中的内置事件分发机制

纯蓝图广播事件通知

  • 创建一个Pawn蓝图类,开个定时器,让这个Pawn每三秒发送一下事件,添加一个事件调度器,在定时器中进行广播通知
    在这里插入图片描述
    在这里插入图片描述

纯蓝图订阅事件通知

  • 新建一个Actor,然后派生出三个子类去订阅广播的事件进行打印
    在这里插入图片描述
  • 运行结果
    在这里插入图片描述

纯蓝图解绑订阅事件通知

  • 可以在发布者中终止所有订阅通知
    在这里插入图片描述
  • 运行结果,这样就只会输出一次三色打印数字,因为四秒后就结束所有订阅者的订阅
    在这里插入图片描述
  • 也可以订阅者自己解绑
    在这里插入图片描述
  • 运行结果,这样后面就不会有这个订阅者的打印了
    在这里插入图片描述

纯Cpp之多播委托

  • 创建一个新Mode用来使用Cpp,创建一个C++的Pawn类,默认硬编码静态网格与材质
  • 硬编码网格与材质
	StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));RootComponent = StaticMesh;static ConstructorHelpers::FObjectFinder<UStaticMesh> StaticMeshAsset(TEXT("StaticMesh'/Engine/BasicShapes/Sphere.Sphere'"));static ConstructorHelpers::FObjectFinder<UMaterialInterface> MaterialAsset(TEXT("Material'/Engine/BasicShapes/BasicShapeMaterial.BasicShapeMaterial'"));if (StaticMeshAsset.Succeeded() && MaterialAsset.Succeeded()){StaticMesh->SetStaticMesh(StaticMeshAsset.Object);StaticMesh->SetMaterial(0, MaterialAsset.Object);}

在这里插入图片描述
在这里插入图片描述

  • 运行结果
    在这里插入图片描述

纯Cpp之多播委托的广播事件通知

  • DECLARE_MULTICAST_DELEGATE_OneParam:用于声明一个多播委托。多播委托是一种特殊的委托,它可以同时注册多个监听器,当委托被调用时,所有的监听器都会收到通知并执行相关的方法。
    • DECLARE_MULTICAST_DELEGATE_OneParam(FMyDelegate, float);:声明了一个名为 FMyDelegate 的多播委托,它可以接受一个浮点数作为参数。
    • OneParam表示这个多播委托有一个参数,可以传入一个参数给监听器。
    • OnParam这里可以写0-9,表示传入的参数个数,例如TwoParam,就表示传两个参数
  • 注意切换Mode的Default Pawn Class小心莫名报错
  • 声明一个参数的多播委托对象
	//声明一个名为 FCpp_Broadcast 的多播委托,它可以接受一个整数作为参数。DECLARE_MULTICAST_DELEGATE_OneParam(FCpp_Broadcast,int)FCpp_Broadcast Cpp_Broadcast;
  • 编写多播委托广播
// Called when the game starts or when spawned
void ACppSender_Pawn::BeginPlay()
{Super::BeginPlay();FTimerHandle TimerHandle;auto Lambda = [this](FCpp_Broadcast* CB){CB->Broadcast(FMath::RandRange(0, 100));};//开启定时器,每3秒发一次广播GetWorld()->GetTimerManager().SetTimer(TimerHandle, FTimerDelegate::CreateLambda(Lambda, &Cpp_Broadcast), 3.f, true);
}
  • 运行结果,相当与上面的蓝图创建广播事件通知

纯Cpp之多播委托的订阅事件通知

  • 新建一个Actor基类然后派生出三个子类进行订阅事件
  • Actor基类就只需要硬编码静态网格与材质
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Properties")class UStaticMeshComponent* StaticMesh;
//--------------------------------------------------------------------------
ACppReceiveActor::ACppReceiveActor()
{// 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;StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));RootComponent = StaticMesh;ConstructorHelpers::FObjectFinder<UStaticMesh> StaticMeshAsset(TEXT("StaticMesh'/Engine/BasicShapes/Cube.Cube'"));ConstructorHelpers::FObjectFinder<UMaterialInterface> MaterialAsset(TEXT("Material'/Engine/BasicShapes/BasicShapeMaterial.BasicShapeMaterial'"));if (StaticMeshAsset.Succeeded() && MaterialAsset.Succeeded()){StaticMesh->SetStaticMesh(StaticMeshAsset.Object);StaticMesh->SetMaterial(0, MaterialAsset.Object);}}
  • Actor的三个子类去接受广播进行屏幕打印数字,声明一个函数用来打印数字

CppReceiveActor_R.h

// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
#include "UE_Cpp/CppReceiveActor.h"
#include "CppReceiveActor_R.generated.h"/*** */
UCLASS()
class DISTRIBUTE_API ACppReceiveActor_R : public ACppReceiveActor
{GENERATED_BODY()
public:void OnReceive(int Param);
protected:virtual void BeginPlay() override;
};

CppReceiveActor_R.cpp

  • AddOnScreenDebugMessage 是虚幻中的一种功能,它可以在屏幕上显示一条调试消息。这对于开发人员在调试过程中非常有用,可以帮助他们快速了解当前程序的状态和进度。
    具体来说,AddOnScreenDebugMessage 函数的使用方式如下:
    GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("This is a debug message"));
    
    这个函数的第一个参数表示消息 ID,用于区分不同的消息。第二个参数表示 消息的显示时间,单位是秒。第三个参数表示消息的颜色,第四个参数表示消息的内容。需要注意的是,AddOnScreenDebugMessage 函数并不是一个标准库函数,而是 Unreal Engine 中的一个全局函数,所以使用前需要先引入相关的头文件:#include "Engine/Engine.h"
// Fill out your copyright notice in the Description page of Project Settings.#include "CppReceiveActor_R.h"
#include "Kismet/GameplayStatics.h"
#include "CppSender_Pawn.h"
#include "Engine/Engine.h"void ACppReceiveActor_R::BeginPlay()
{Super::BeginPlay();//获取到CppSender_PawnACppSender_Pawn* PlayerPawn = Cast<ACppSender_Pawn>(UGameplayStatics::GetPlayerPawn(this, 0));//订阅事件通知PlayerPawn->Cpp_Broadcast.AddUObject(this, &ACppReceiveActor_R::OnReceive);
}void ACppReceiveActor_R::OnReceive(int Param)
{//打印到屏幕GEngine->AddOnScreenDebugMessage(INDEX_NONE, 10.f, FColor::Red, FString::Printf(TEXT("%i"), Param));
}

纯Cpp之多播委托的解绑订阅事件通知

  • Cpp中订阅事件通知,会返回一个FDelegate句柄,我们接受这个句柄然后调用Remove删除即可,也可以使用RemoveAll也是一样的效果,但是RemoveAll使用方法不一样
void ACppReceiveActor_R::BeginPlay()
{Super::BeginPlay();//获取到CppSender_PawnACppSender_Pawn* PlayerPawn = Cast<ACppSender_Pawn>(UGameplayStatics::GetPlayerPawn(this, 0));//订阅事件通知FDelegateHandle DelegateHandle = PlayerPawn->Cpp_Broadcast.AddUObject(this, &ACppReceiveActor_R::OnReceive);FTimerHandle TimerHandle;auto Lambda = [=](){PlayerPawn->Cpp_Broadcast.Remove(DelegateHandle);//删除所有订阅者,一般在发布者使用//PlayerPawn->Cpp_Broadcast.Clear();};GetWorld()->GetTimerManager().SetTimer(TimerHandle, FTimerDelegate::CreateLambda(Lambda), 4.f, false);
}
  • 运行结果
    在这里插入图片描述
  • 删除所有订阅者
    在这里插入图片描述

蓝图与Cpp混合多播动态委托的广播事件通知

  • 多播委托可以蓝图与Cpp混合使用,新建一个Pawn类来创建广播事件
  • DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam:使用这个宏就可以定义一个可以在蓝图中调用的多播委托,多加了一个DYNAMIC就可以被蓝图去识别到了
  • 创建多播委托代理,要加上反射,参数为BlueprintAssignable这样就可以被蓝图调用
public:// Sets default values for this pawn's propertiesABPAndCpp_Sender();
//注意这里要加分号,上个没有加DYNAMIC的不用加分号DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FBPAndCpp_Broadcast, int, Param);UPROPERTY(BlueprintAssignable)FBPAndCpp_Broadcast BPAndCpp_Broadcast;UPROPERTY(VisibleAnywhere,BlueprintReadOnly,Category="Properties")class UStaticMeshComponent* StaticMesh;
void ABPAndCpp_Sender::BeginPlay()
{Super::BeginPlay();FTimerHandle TimerHandle;auto Lambda = [](FBPAndCpp_Broadcast* BPAC){BPAC->Broadcast(FMath::RandRange(0, 100));};GetWorld()->GetTimerManager().SetTimer(TimerHandle, FTimerDelegate::CreateLambda(Lambda,&BPAndCpp_Broadcast), 3.f, true);}

蓝图与Cpp混合多播动态委托的订阅事件通知

  • 创建一个基类Actor派生出三个子类进行订阅事件
  • 注意这里的接收函数需要添加反射,反射可以无参数
  • 注意这里的绑定使用的是AddDynamic而不是AddUObject
void ABPAndCpp_Receive_R::BeginPlay()
{Super::BeginPlay();ABPAndCpp_Sender* MainPlayer = Cast<ABPAndCpp_Sender>(UGameplayStatics::GetPlayerPawn(this, 0));//绑定订阅事件通知MainPlayer->BPAndCpp_Broadcast.AddDynamic(this, &ABPAndCpp_Receive_R::OnReceived);
}void ABPAndCpp_Receive_R::OnReceived(int Param)
{GEngine->AddOnScreenDebugMessage(INDEX_NONE, 10.f, FColor::Red, FString::Printf(TEXT("%i"), Param));
}
  • 运行结果,此时C++拉入场景中也可以调用通知
    在这里插入图片描述

蓝图与Cpp混合多播动态委托的蓝图多播动态委托订阅

  • 新建一个Actor蓝图,派生三个蓝图,在蓝图中就可以调用多播委托,因为有反射,会出现一个委托
    在这里插入图片描述
    在这里插入图片描述
  • 运行结果
    在这里插入图片描述
  • 蓝图中的解绑和之前纯蓝图解绑事件还是一样的
  • C++中解绑使用RemoveDynamic就行
    在这里插入图片描述
  • 运行结果
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/179228.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Fabric:搭建自定义网络

Hyperledger Fabric: V2.5.4 写在最前 从本篇博客开始&#xff0c;将陆续介绍使用Fabric搭建自定义网络及部署执行链码的过程。本篇主要介绍如何搭建网络。   由于前文在安装Fabric的时候&#xff0c;已经将目录fabric-samples/bin加入到了环境变量PATH中&#xff0c;所以正文…

数据结构 / day01 作业

1.定义结构体数组存储5个学生的信息&#xff1a;姓名&#xff0c;年龄&#xff0c;性别 定义函数实现输入&#xff0c;要求形参使用结构体指针接收 函数实现5个学生年龄排序(注意对年龄排序时&#xff0c;交换的是所有信息) 定义函数实现输出&#xff0c;要求形参使用结构体…

(5h)Unity3D快速入门之Roll-A-Ball游戏开发

DAY1&#xff1a;Unity3D安装 链接 DAY2&#xff1a;构建场景&#xff0c;编写代码 链接 内容&#xff1a;WASD前后左右移动、摄像机跟随 DAY3&#xff1a;待更新 DAY4&#xff1a;待更新 DAY5&#xff1a;待更新

jekins CVE-2018-1000861 漏洞复现

jekins CVE-2018-1000861 漏洞复现 ‍ 名称: jenkins 命令执行 &#xff08;CVE-2018-1000861&#xff09; 描述: ​Jenkins 可以通过其网页界面轻松设置和配置,其中包括即时错误检查和内置帮助。 插件 通过更新中心中的 1000 多个插件,Jenkins 集成了持续集成和持续交付工具…

INFINI Gateway 与华为鲲鹏完成产品兼容互认证

何为华为鲲鹏认证 华为鲲鹏认证是华为云围绕鲲鹏云服务&#xff08;含公有云、私有云、混合云、桌面云&#xff09;推出的一项合作伙伴计划&#xff0c;旨在为构建持续发展、合作共赢的鲲鹏生态圈&#xff0c;通过整合华为的技术、品牌资源&#xff0c;与合作伙伴共享商机和利…

AI大模型相关产品的数据飞轮如何建设?

1、背景 数据飞轮&#xff0c;是今年大模型带火的一个典型词汇&#xff0c;通过客户在应用程序中输入的提示词这样的数据反馈&#xff0c;使大模型快速迭代。简单说&#xff1a;好的产品 -> 更多的用户数据 -> 更好的模型质量 -> 更好的产品就进入了一个正向循环。一…

【Apifox】测试工具自动编写接口文档

在开发过程中&#xff0c;我们总是避免不了进行接口的测试&#xff0c; 而相比手动敲测试代码&#xff0c;使用测试工具进行测试更为便捷&#xff0c;高效 今天发现了一个非常好用的接口测试工具Apifox 相比于Postman&#xff0c;他还拥有一个非常nb的功能&#xff0c; 在接…

小白备战蓝桥杯:Java基础语法

一、注释 IDEA注释快捷键&#xff1a;Ctrl / 单行注释&#xff1a; //注释信息 多行注释&#xff1a; /* 注释信息 */ 二、字面量 常用数据&#xff1a;整数、小数、字符串&#xff08;双引号&#xff09;、字符&#xff08;单引号&#xff09;、布尔值&#xff08;tr…

JavaScript 的 DOM 知识点有哪些?

文档对象模型&#xff08;Document Object Model&#xff0c;简称 DOM&#xff09;&#xff0c;是一种与平台和语言无关的模型&#xff0c;用来表示 HTML 或 XML 文档。文档对象模型中定义了文档的逻辑结构&#xff0c;以及程序访问和操作文档的方式。 当网页加载时&#xff0…

unity3d 旋转cube时变形

将cube移到父路径同级&#xff0c;重置再&#xff0c;更改角度&#xff0c;或者将父路径先重置&#xff0c;再将cube移动到父节点下面

Corel产品注册机Corel Products KeyGen 2023 – XFORCE解决会声会影2023试用30天

CorelDRAW注册机2023支持全系列产品_Corel Products KeyGen 2023 X-FORCE v8 CorelDRAW注册机2023支持全系列产品_Corel Products KeyGen 2023 X-FORCE v8&#xff0c;Corel产品注册机&#xff08;Corel Products KeyGen 2023 – XFORCE&#xff09;&#xff0c;支持Corel旗下所…

Django请求生命周期流程

浏览器发起请求。 先经过网关接口&#xff0c;Django自带的是wsgiref&#xff0c;请求来的时候解析封装&#xff0c;响应走的时候打包处理&#xff0c;这个wsgiref模块本身能够支持的并发量很少&#xff0c;最多1000左右&#xff0c;上线之后会换成uwsgi&#xff0c;并且还会加…

人工智能技术发展漫谈

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 人工智能发展历程 人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;的发展历史可以追溯到20世纪中叶。以下是一些关键时刻和阶段&#xff1a; 起…

MySQL--日志

日志 错误日志 错误日志是MySQL中最重要的日志之一&#xff0c;它记录了当mysqld启动和停止时&#xff0c;以及服务器在运行过程中发生任何严重错误时的相关信息 当数据库出现任何故障导致无法正常使用时&#xff0c;建议首先查看此日志。 该日志是默认开启的&#xff0c;默认…

Java变量理解

成员变量VS局部变量的区别 语法形式&#xff1a;从语法形式上看&#xff0c;成员变量是属于类的&#xff0c;而局部变量是在代码块或方法中定义的变量或是方法的参数&#xff1b;成员变量可以被 public,private,static 等修饰符所修饰&#xff0c;而局部变量不能被访问控制修饰…

C++进阶篇5---番外-位图和布隆过滤器

哈希的应用 一、位图 情景&#xff1a;给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一个数是否在这40亿个数中&#xff1f;&#xff1f;&#xff1f; 看到查找元素的范围&#xff0c;暴力肯定是过不了的&#xff0c;我们要么…

自学成为android framework工程师需要准备哪些装备-千里马车载车机系统开发学习

背景 hi&#xff0c;粉丝朋友们&#xff1a; 大家好&#xff01;经常有很多学员买课同学都会问到需要准备哪些装备&#xff0c;我也回答了很多学员了&#xff0c;今天就搞一篇文章来统一说明一下&#xff0c;告诉一下大家如果你想从一个framework新手变成一个framework开发的高…

sprintboot快速初始化【Springboot】

1.首先选择创建项目 2.填写对应的项目信息 一定要勾选maven&#xff0c;否则没有pom文件&#xff0c;选择next 3.选择应用场景 点击 create&#xff0c;DIEA就会根据你的选择自动创建项目骨架&#xff1b; 4.创建一个控制层 随便创建一个控制层&#xff0c;测试一下项目是否…

链接1:编译器驱动程序

文章目录 GNU编译器示例编译 GNU编译器 GNU编译器&#xff08;GNU Compiler&#xff09;是由自由软件基金会&#xff08;Free Software Foundation&#xff0c;FSF&#xff09;开发和维护的一套编译器集合。这些编译器主要用于编译各种编程语言的源代码&#xff0c;将其转换为…

深度盘点:100 个 Python 数据分析函数总结

经过一段时间的整理&#xff0c;本期将分享我认为比较常用的100个实用函数&#xff0c;这些函数大致可以分为六类&#xff0c;分别是统计汇总函数、数据清洗函数、数据筛选、绘图与元素级运算函数、时间序列函数和其他函数。 技术交流 技术要学会交流、分享&#xff0c;不建议…