网站pc客户端制作,wordpress的cms插件,网页设计需要学什么编程语言,做封面的网站在哪里观察者模式原理
观察者模式通常有观察者与被观察者#xff0c;当被观察者状态发生改变时#xff0c;它会通知所有的被观察者对象#xff0c;使他们能够及时做出响应#xff0c;所以也被称作“发布-订阅模式”。总得来说就是你关注了一个主播#xff0c;主播的状态改变会通…观察者模式原理
观察者模式通常有观察者与被观察者当被观察者状态发生改变时它会通知所有的被观察者对象使他们能够及时做出响应所以也被称作“发布-订阅模式”。总得来说就是你关注了一个主播主播的状态改变会通知这些人关注主播的这些人都会根据主播的通知改变一些状态
观察者模式游戏工程案例(击杀怪物后的逻辑)
观察者模式定义了对象之间的一对多关系当主题对象改变状态发出通知的时候它的所有观察者都会收到提示然后作出自己的响应
事件分发机制定义
通过观察者模式的“订阅-发布”机制使用事件传递数据与驱动行为的方法 优点 解耦合可读性强模块独立化高可自行测试
虚幻中的内置事件分发机制
纯蓝图广播事件通知
创建一个Pawn蓝图类开个定时器让这个Pawn每三秒发送一下事件添加一个事件调度器在定时器中进行广播通知
纯蓝图订阅事件通知
新建一个Actor然后派生出三个子类去订阅广播的事件进行打印 运行结果
纯蓝图解绑订阅事件通知
可以在发布者中终止所有订阅通知 运行结果这样就只会输出一次三色打印数字因为四秒后就结束所有订阅者的订阅 也可以订阅者自己解绑 运行结果这样后面就不会有这个订阅者的打印了
纯Cpp之多播委托
创建一个新Mode用来使用Cpp创建一个C的Pawn类默认硬编码静态网格与材质硬编码网格与材质 StaticMesh CreateDefaultSubobjectUStaticMeshComponent(TEXT(StaticMesh));RootComponent StaticMesh;static ConstructorHelpers::FObjectFinderUStaticMesh StaticMeshAsset(TEXT(StaticMesh/Engine/BasicShapes/Sphere.Sphere));static ConstructorHelpers::FObjectFinderUMaterialInterface 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 dont need it.PrimaryActorTick.bCanEverTick true;StaticMesh CreateDefaultSubobjectUStaticMeshComponent(TEXT(StaticMesh));RootComponent StaticMesh;ConstructorHelpers::FObjectFinderUStaticMesh StaticMeshAsset(TEXT(StaticMesh/Engine/BasicShapes/Cube.Cube));ConstructorHelpers::FObjectFinderUMaterialInterface 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.hvoid ACppReceiveActor_R::BeginPlay()
{Super::BeginPlay();//获取到CppSender_PawnACppSender_Pawn* PlayerPawn CastACppSender_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 CastACppSender_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 pawns propertiesABPAndCpp_Sender();
//注意这里要加分号上个没有加DYNAMIC的不用加分号DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FBPAndCpp_Broadcast, int, Param);UPROPERTY(BlueprintAssignable)FBPAndCpp_Broadcast BPAndCpp_Broadcast;UPROPERTY(VisibleAnywhere,BlueprintReadOnly,CategoryProperties)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 CastABPAndCpp_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就行 运行结果