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_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就行
    在这里插入图片描述
  • 运行结果
    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

西南科技大学C++程序设计实验二(类与对象一)

C++最大的特点就是面向对象,掌握它的几种基本性质还是好理解的,可以看我C++专栏的期末速成,希望对你们学习C++有帮助。 一、实验目的 1.理解简单类的定义、说明与使用 2.理解类中不同属性数据成员的访问特点 3.理解构造函数、析构函数的作用 重点:掌握类的定义与实现,…

成为AI产品经理——模型评估指标

目录 一、模型评估分类 1.在线评估 2.离线评估 二、离线模型评估 1.特征评估 ① 特征自身稳定性 ② 特征来源稳定性 ③ 特征成本 2.模型评估 ① 统计性评估 覆盖度 最大值、最小值 分布形态 ② 模型性能指标 分类问题 回归问题 ③ 模型的稳定性 模型评估指标分…

Java高级技术(反射:获取类)

一&#xff0c;认识反射 二&#xff0c; 反射第一步 三&#xff0c;案例

数据库的增删查改(CRUD)基础版

CRUD: create增加、retrieve查询、update更新、delete删除 注意一点&#xff1a;MySQL对大小写是不敏感的 目录 新增&#xff08;create&#xff09; 全列插入 指定列插入 多行插入 查询&#xff08;Retrieve&#xff09; 列查询 全列查询 指定列查询 表达式查询 …

【问题解决!】OSError: [WinError 1455] 页面文件太小,无法完成操作。Error loading “c:\Anaconda3\lib

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 问题描述问题原因二、解决方法 问题描述 在使用pytorch跑深度学习的时候报错OSError: [WinError 1455] 页面文件太小&#xff0c;无法完成操作。Error loading “c…

vivado产生报告阅读分析27

1、设计 QoR 汇总 命令行选项 -qor_summary 可用于为流程中每个步骤生成 QoR 汇总信息。该选项只能从 Tcl 控制台使用。该选项可按两种格式生成&#xff1a; 基于文本的报告或 JSON 格式。 要生成基于文本的格式 &#xff0c; 请运行以下命令 &#xff1a; report_des…

0005Java程序设计-ssm基于微信小程序的校园求职系统

文章目录 摘 要目 录系统设计开发环境 编程技术交流、源码分享、模板分享、网课分享 企鹅&#x1f427;裙&#xff1a;776871563 摘 要 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据…

小白必知:AIGC 和 ChatGPT 的区别

原文 &#xff1a; https://openaigptguide.com/chatgpt-aigc-difference/ AIGC 和 ChatGPT 都是人工智能技术&#xff0c;但它们的功能和应用场景不同。 AIGC&#xff08;AI-GeneratedContent&#xff0c;人工智能自动生成内容&#xff09;是人工智能、计算机图形学和深度学…

dbvisual editor 显示中文乱码

打开如下的页面就可以选择中文相关的字体就可以正常显示中文了。

spring-boot对rabbitMQ的操作

一、安装rabbitMQ 1、直接使用docker拉取镜像 docker pull rabbitmq:3.82、启动容器 docker run \-e RABBITMQ_DEFAULT_USERadmin \-e RABBITMQ_DEFAULT_PASS123456 \-v mq-plugins:/plugins \--name rabbit01 \--hostname rabbit01 --restartalways \-p 15672:15672 \-p 5672:…

11-28渗透

用nmap扫描靶机1进行主机发现 已知靶机1的主机在172.16.17.0/24下 扫描结果如下 根据扫描结果看开启的服务怀疑172.16.17.177是靶机1 浏览器访问172.16.17.177页面得到如下 我们知道织梦cms系统默认管理路径是dede&#xff0c;登陆管理后台可以通过地址172.16.17.177/dede/i…

第六节HarmonyOS UIAbility内页面的跳转和数据传递

一、页面跳转 在一个应用包含一个UIAbility的场景下&#xff0c;可以通过新建多个页面来实现和丰富应用的内容。这会涉及到UIAbility内页面的新建以及UIAbility内页面的跳转和数据传递。 打开DevEco Studio&#xff0c;选择一个Empty Ability工程模板&#xff0c;创建一个工程&…

深入了解Java8新特性-日期时间API:OffsetDateTime类

阅读建议 嗨&#xff0c;伙计&#xff01;刷到这篇文章咱们就是有缘人&#xff0c;在阅读这篇文章前我有一些建议&#xff1a; 本篇文章大概24000多字&#xff0c;预计阅读时间长需要20分钟。本篇文章的实战性、理论性较强&#xff0c;是一篇质量分数较高的技术干货文章&…

pandas教程:US Baby Names 1880–2010 1880年至2010年美国婴儿姓名

文章目录 14.3 US Baby Names 1880–2010&#xff08;1880年至2010年美国婴儿姓名&#xff09;1 Analyzing Naming Trends&#xff08;分析命名趋势&#xff09;评价命名多样性的增长“最后一个字母”的变革变成女孩名字的男孩名字&#xff08;以及相反的情况&#xff09; 14.3…

电荷泵升压/降压电路

一、升压\降压电路原理分析 1、升压电路 电荷泵升压电路 VoutVa5V 5V_PLUS0V时&#xff0c;Va给C2充电&#xff0c;C2上节点电压比C2下节点电压高Va&#xff1b; 5V_PLUS5V时&#xff0c;C2电压不能突变&#xff0c;C2上节点电压依然比C2下节点电压高Va&#xff0c;但C2下节点…

Redis 主从架构,Redis 分区,Redis哈希槽的概念,为什么要做Redis分区

文章目录 Redis 主从架构redis replication 的核心机制redis 主从复制的核心原理过程原理Redis集群的主从复制模型是怎样的&#xff1f;生产环境中的 redis 是怎么部署的&#xff1f;机器是什么配置&#xff1f;你往内存里写的是什么数据&#xff1f;说说Redis哈希槽的概念&…

智安网络|探索云安全合规要求:等保2.0时代的新趋势解析

随着信息技术的不断发展和应用的广泛普及&#xff0c;信息安全问题日益凸显&#xff0c;特别是在云计算时代&#xff0c;企业对于云平台的安全保障需求更为迫切。等级保护&#xff08;等保&#xff09;作为我国信息安全的基本要求&#xff0c;已经进入了2.0时代&#xff0c;对于…

ArkTS-共享元素转场动画

共享元素转场动画 在不同页面间&#xff0c;有使用相同的元素&#xff08;例如同一幅图&#xff09;的场景&#xff0c;可以使用共享元素转场动画衔接。为了突出不同页面间相同元素的关联性&#xff0c;可为它们添加共享元素转场动画。如果相同元素在不同页面间的大小有明显差异…

有没有不含亚硫酸盐的葡萄酒?

没有完全不含亚硫酸盐的葡萄酒&#xff0c;有机葡萄酒和生物动力葡萄酒中也会含有少量天然 亚硫酸盐。因为它是在发酵过程中产生的一种化合物&#xff0c;所以不可能酿造无亚硫酸盐的葡萄酒。 在大多数葡萄酒国家都有葡萄酒法律规定&#xff0c;如果葡萄酒超过特定的亚硫酸盐水…