【UE4】入门级,游戏角色的生命,蓝条,盾值等属性动态多播代理的实现方法

1 篇文章 0 订阅
1 篇文章 0 订阅

【UE4】入门级,游戏角色的生命,蓝条,盾值等属性动态多播代理的实现方法

动态多播代理(结合UMG蓝图)

动态多播代理允许被序列化的数据结构,这将使得代理可以被数据化提供给蓝图进行使用,达到在CPP中调用代理广播,事件通知到蓝图中。

用一个Demo里面角色的生命等属性的动态改变做案例介绍

一:声明宏

在角色得类上面,空间域里声明的

//动态代理,当角色3个状态改变时候的广播(生命值,物理盾,魔法盾)
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FNotifyPawnChange, float, PawnHpPercent,float,PawnPhysicalShieldPercent,float, PawnMageShieldPercent);

UCLASS()
class SWORDARTONLINE_API ACharacter_MainRole : public ACharacter
{
	GENERATED_BODY()
}

我需要传入三个属性,所以用了含三个参数的声明宏;

声明宏的传参
声明时第一个传入的是个代理名称,需要F打头,别和其他的代理名字重复即可,是声明调度器所用类型名;
依次后面第二个传入,需要参数的类型,比如我第一个是生命值,是浮点型,就传入了float型,第三个传入参数的名称,尽量起一个自己认识的就好;
以此类推,第二个参数物理盾值,第三个参数魔法盾值得传入。

二:声明调度器

接下来需要声明调度器
在角色的类里面,我放在protected,保护域里面了;

UCLASS()
class SWORDARTONLINE_API ACharacter_MainRole : public ACharacter
{
	GENERATED_BODY()
protected//角色三个状态调度器
	UPROPERTY(BlueprintAssignable)
	FNotifyPawnChange NotifyPawnChange;
	
}

BlueprintAssignable 修饰符
用于动态代理的,为了在蓝图中分配;

FNotifyPawnChange
调度器类型就是前面你命名的,在声明宏中第一个传入的Name;

NotifyPawnChange
调度器变量名称;

三:代理调用

我把绑定用一个函数封装了
声明了一个void函数

UCLASS()
class SWORDARTONLINE_API ACharacter_MainRole : public ACharacter
{
	GENERATED_BODY()
protected:
	virtual void BeginPlay() override;
public:
	//广播人物血量,物理盾,魔法盾的函数
	void BroadcastPawnState();
	
protected:
	//角色三个状态调度器
	UPROPERTY(BlueprintAssignable)
	FNotifyPawnChange NotifyPawnChange;
	
}

定义

void ACharacter_MainRole::BroadcastPawnState()
{
	//检查当前是否存在有效代理绑定
	if (NotifyPawnChange.IsBound())
	{
		float PawnHpPercent = (float)GetCurrentHP() / GetTotalMaxHP();
		float PawnPhysicalShieldPercent = (float)GetCurrentPhysicalShieldValue() / GetTotalPhysicalShieldValue();
		float PawnMageShieldPercent = (float)GetCurrentMageShieldValue() / GetTotalMageShieldValue();
		NotifyPawnChange.Broadcast(PawnHpPercent, PawnPhysicalShieldPercent, PawnMageShieldPercent);
	}
}

因为各种状态UMG的显示都是百分比,比如当前血量HP是50,满血HP是100,则50/100,UMG血条应显示0.5;

NotifyPawnChange.IsBound() 函数
检查是否有函数被绑定到这个委托上,如果有返回True;

NotifyPawnChange.Broadcast() 函数
执行调用代理,传入参数的类型及个数,是声明宏三个参数类型;

1、函数先在BeginPlay()里面调用,防止初始化的时候生命值等属性于UMG上不统一;

void ACharacter_MainRole::BeginPlay()
{
	Super::BeginPlay();
    BroadcastPawnState();
}

2、函数在受伤函数里调用


void ACharacter_MainRole::ApplyDamage(int32 HurtValue, EDamageType DamageType, ACharacter* DamageSourceActor, FVector DamageVector)
{

//广播角色三个状态
	BroadcastPawnState();
	
}

受伤函数的编写逻辑,可以用受伤接口去实现,之后文章会解释。

四:在UMG蓝图中绑定

我的UMG有一个共有的UUserWidget的C++类
这样做,既可以在C++中调用,也可以在蓝图中调用;

UCLASS()
class SWORDARTONLINE_API UUMG_MainInterface : public UUserWidget
{
	GENERATED_BODY()
public:
	//广播人物的三个状态(血量,物理盾,魔法盾)的函数
	UFUNCTION(BlueprintImplementableEvent)
		void ChangePawnState();
	//角色
	UPROPERTY(BlueprintReadOnly)
		ACharacter_MainRole* Pawn;
		
}
	

UFUNCTION(BlueprintImplementableEvent)
标记的函数只能在c++中调用,在蓝图中无法调用
用此标记可以在C++中构建函数声明,但是定义由蓝图完成,从而达到C++向蓝图进行调用的目的,在CPP无需定义

注意如果函数没有返回类型,则在蓝图中当作事件Event使用
如果函数存在返回类型,则在蓝图中当作函数使用(需要在函数的overlap中寻找)
如果带有参数
•没有返回值,参数是基本数据类型,则当作普通事件输入参数使用
•没有返回值,参数是基本数据类型引用,则当作函数看待,在函数表中寻找
•没有返回值,参数是自定义数据类型(如Fstring),则编译不过
•没有返回值,参数是自定义数据类型引用,则当作普通函数看待,在函数表中寻找
•如果有返回值,则当作函数使用

在蓝图中

动态代理
Pawn是在C++中声明的;

PawnHp_Sphere控件,是血条及其他的进度条全部用一个UMG控件;

各个属性条都是用UE自带的控件Progress Bar做的;

五:结,扩展一下

创建一个动态代理。

DECLARE_DYNAMIC_DELEGATE( DelegateName )

创建一个动态的多播代理。

DECLARE_DYNAMIC_MULTICAST_DELEGATE( DelegateName )

操作函数
BindDynamic( UserObject, FuncName )
在动态代理上调用BindDynamic()的辅助宏。
AddDynamic( UserObject, FuncName )
在动态多播代理上调用AddDynamic()的辅助宏。
RemoveDynamic( UserObject, FuncName )
在动态多播代理上调用RemoveDynamic()的辅助宏。
与单播多播区别
•动态代理构建类型名称需要用F开头(动态代理实现机制构建了类)
•动态代理对象类型可以使用UPROPERTY标记,其他代理均无法使用(不加编译可过,调用出错)
•动态代理绑定对象的函数需要使用UFUNCTION进行描述(因为需要跟随代理被序列化)

BindDynamic( UserObject, FuncName )
在动态单播代理上调用BindDynamic()的辅助宏。
AddDynamic( UserObject, FuncName )
在动态多播代理上调用AddDynamic()的辅助宏。

RemoveDynamic( UserObject, FuncName )
在动态多播代理上调用RemoveDynamic()的辅助宏。

在这里插入图片描述
零散的东西,随便看看吧。。。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值