UE 事件分发机制 day9

news2024/9/23 7:24:59

观察者模式原理

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

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

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

事件分发机制定义

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

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

纯蓝图广播事件通知

  • 创建一个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_Pawn
	ACppSender_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_Pawn
	ACppSender_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 properties
	ABPAndCpp_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.coloradmin.cn/o/1264104.html

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

相关文章

逆向 wa 发送图片

开发工具 工具名称工具类型说明AndroidStuduo编辑工具开发工具jadxjava工具将apk解成java项目xposed插件工具插件whatsApp版本2.23.16.77 分析源码的点&#xff1a; 发送图片的点 获取SendMedia 回调 实现 public void sendImg(String user, String path) throws Exce…

毫米波雷达DOA角度计算-----MUSIC算法

MUSIC算法如下&#xff1a; txNum &#xff1a;发射天线 2个 &#xff0c;rxNum&#xff1a;接收天线 4 个 。 ant &#xff1a; 为目标点的 天线 接收数据 &#xff0c; 为 8*1矩阵。 A ant;d 0.5;M 1; % # 快拍数ang_ax -90:90; % 角度坐标% 接收信号方向向量for k1:…

04 # 第一个 TypeScript 程序

初始化项目以及安装依赖 新建 ts_in_action 文件夾 npm init -y安装好 typescript&#xff0c;就可以执行下面命令查看帮助信息 npm i typescript -g tsc -h创建配置文件&#xff0c;执行下面命令就会生成一个 tsconfig.json 文件 tsc --init使用 tsc 编译一个 js 文件 新…

PVE中CT容器安装openwrt X86的极简方法

下载推荐&#xff1a;https://openwrt.ai/ 使用环境PVE8.0&#xff0c;openwrt是以上网址的最新版&#xff0c;内涵及其丰富组件。 问题来源&#xff1a; 在PVE虚拟机可以很方便的使用img文件&#xff0c;转换qm 成一个硬盘文件&#xff0c;加入到虚拟机也就完成了&#xff0c…

python基础练习题库实验6

文章目录 题目1代码实验结果题目2代码实验结果题目3代码实验结果题目4代码实验结果题目总结题目1 根据以下规范编写一个函数: 函数名称:triple输入参数:1个输入参数数据类型字符串返回值:函数返回1个字符串值。该字符串由每个字符重复3次的句子构成。例如,如果句子是Uni,…

科学与工程计算基础(数值计算)知识点总结

数值计算 第1章 概论1.2 数值计算中的误差1.2.1 误差的来源和分类1.2.2 误差与有效数字1.2.3 数值运算的误差估计 1.3 误差定性分析和避免误差危害1.3.1 算法的数值稳定性1.3.3 避免误差危害 1.4 数值计算中算法设计的技术1.5 习题1.5.1 判断题1.5.2 计算题 第2章 插值法2.2 拉…

i已学赋能智慧教育时代的幼儿教育

伴随“教育数字化战略行动”的深入开展,智慧教育正式成为国家战略。智慧教育延伸至家校社教育的每个阶段。当前,为适应智慧教育发展趋势,我国制定了《中国教育现代化2035》《教育部关于加强“三个课堂”应用的指导意见》《教育信息化2.0行动计划》等文件。幼儿作为智慧教育、智…

计算机网络408

一&#xff1a;计算机网络体系结构 1.计网的概念&#xff0c;组成&#xff0c;功能和分类 一&#xff1a;计算机网络的发展 (3)从功能组成视觉看&#xff1a;分为资源子网和通信子网 2.计网性能指标

“PredictingChildrenHeight“ app Tech Support(URL)

Using our app, we can predict a childs height through formulas. Because there are many factors that affect a childs height, it is for reference only. ​​​​​​​ If you have any questions, you can either leave a message or send the questions to our em…

Unity-链接MySql5.7

链接MySql5.7 前言&#xff1a; 为什么不选择最新的MySQL8.0或者MySQL8.2呢&#xff0c;实际发现&#xff0c;如果使用这两个版本&#xff0c;虽然能够用同样的方法找到合适的dll&#xff0c;但是在编写代码的过程中往往会卡死&#xff0c;非常的影响效率&#xff0c;因此放弃…

11.28 知识回顾(Web框架、路由控制、视图层)

一、 web 框架 1.1 web框架是什么&#xff1f; 别人帮咱们写了一些基础代码------》我们只需要在固定的位置写固定的代码--》就能实现一个web应用 Web框架&#xff08;Web framework&#xff09;是一种开发框架&#xff0c;用来支持动态网站、网络应用和网络服务的开发。这大多…

模拟实现offsetof宏(详解)

我们在以前学过这个offsetof函数&#xff0c;知道它的功能是求指针相较于起始位置的偏移量&#xff0c;我们今天要来写出一个宏&#xff0c;计算结构体中某成员变量相对于起始位置的偏移。 目录 1.offsetof函数 1.1offsetof函数介绍 1.2offsetof函数代码实现 2.offsetof函数…

20 章 多线程

20.1线程简介. 20.2创建线程 2.1继承Thread类 Thread 类是java.lang包中的一个类&#xff0c;从这个类中实例化的对象代表线程&#xff0c;程序员启动一个新线程需要建立Thread 实例。Thread类中常用的两个构造方法如下: public Thread():创建一个新的线程对象。 public Thre…

JVM 参数介绍

在一些规模稍大的应用中&#xff0c;Java虚拟机&#xff08;JVM&#xff09;的内存设置尤为重要&#xff0c;想在项目中取得好的效率&#xff0c;GC&#xff08;垃圾回收&#xff09;的设置是第一步。 PermGen space&#xff1a;全称是Permanent Generation space.就是说是永久…

MPPT工作流程及算法和硬件的选择

MPPT算法选择 目前&#xff0c;MPPT算法有开路电压比率(离线)、短路电流比率(离线)、观察调节(在线)、极限追踪控制法(在线)。 在光伏控制系统中&#xff0c;因为日照、温度等条件的变化&#xff0c;光伏电池的输出功率也是在不断变化的&#xff0c;为保证使得光伏电池的输出功…

单片机BootLoader是咋回事?

BootLoader的定义&#xff1a; CPU进入APP之前运行的一小段程序代码就叫做BootLoader。它是由程序员编写的&#xff0c;作用是更新应用程序。这也就说明了只有BootLoader的单片机才可以升级。有的产品有升级的需要就需要BootLoader了。 单片机的启动过程可以这么叙述&#xff…

AI Agent应用落地前半场,属于企服软件厂商推出的平台级AI智能体

GPTs大受欢迎但问题多&#xff0c;企服厂商的AI Agent更被B端客户器重 比尔盖茨预言智能体是下个平台&#xff0c;超自动化平台的AI Agent更靠谱&#xff1f; 以GPTs为代表的AI Agent只是玩具&#xff1f;揭秘真实可用AI智能体长什么样 AI Agent应用落地前半场&#xff0c;属…

建议收藏:华为海思IC设计笔试题,含解析(附下载)

华为海思一直以来是从业者想要进入的热门公司。但是岗位就那么多&#xff0c;在面试的时候&#xff0c;很多同学因为准备不充分&#xff0c;与岗位失之交臂&#xff0c;无缘进入该公司。今天为大家带来华为海思芯片岗的真题解析&#xff0c;如有错漏&#xff0c;欢迎指正哈。 今…

机器学习常用距离度量方法

机器学习常用距离度量方法 前言一、前期准备二、距离度量方法1. 欧氏距离2.曼哈顿距离3.切比雪夫距离4. 闵可夫斯基距离 总结 前言 机器学习中往往通过度量来研究不同样本或数据集之间的差异性&#xff0c;合适的度量方式可以显著提高算法的准确率&#xff0c;因此在接下来的内…

数据结构 / day01 作业

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