【UE4C++-ActionRougelike-25】Buff状态栏


【UE4C++-ActionRougelike-25】Buff状态栏

一、Buff状态栏

Buff状态栏实现流程:

  • 获得Buff(MyActionEffect开始)
  • 通过多播委托告知UI创建Buff图标Widget
  • 获取Buff图标和Buff剩余时间
  • 实时更新UI

1、创建Action状态改变多播委托

在MyActionComponent中增加一个带有两个参数的动态多播委托,两个参数类型为MyActionComponent和MyAction。用于当某个MyActionComponent上的MyAction状态发生变化时触发委托。

// MyActionComponent.h
// 定义一个带有两个参数的动态多播委托。当Action状态改变时触发
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnActionStateChanged, UMyActionComponent*, OwningComp, UMyAction*, Action);
class ACTIONROGUELIKE_API UMyActionComponent : public UActorComponent
{
	// 声明一个可以在蓝图中分配的多播委托,当动作开始时触发。
	UPROPERTY(BlueprintAssignable)
	FOnActionStateChanged OnActionStarted;
	// 声明一个可以在蓝图中分配的多播委托,当动作停止时触发。
	UPROPERTY(BlueprintAssignable)
	FOnActionStateChanged OnActionStopped;
}
// MyAction.cpp
void UMyAction::StartAction_Implementation(AActor* Instigator)
{
	// ...
	// 当动作开始时,广播OnActionStarted事件
	// GetOwningComponent()获取当前动作所属的组件,this代表当前动作实例
	GetOwningComponent()->OnActionStarted.Broadcast(GetOwningComponent(), this);
}
void UMyAction::StopAction_Implementation(AActor* Instigator)
{
    // ...
	// 当动作停止时,广播OnActionStopped事件
	GetOwningComponent()->OnActionStopped.Broadcast(GetOwningComponent(), this);
}

2、记录Buff持续时间

在MyAction中增加两个属性:

  • Icon,用来表示不同种类Buff的图标
  • TimeStarted,之后用于计算Buff剩余时间
// MyAction.h
class ACTIONROGUELIKE_API UMyAction : public UObject
{
protected:
	// 定义一个可在编辑器中修改的只读属性,它是一个UI类别下的图标。表示Buff图标
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI")
	UTexture2D* Icon;
	// 定义一个在网络中复制的属性,表示动作开始的时间。之后用于计算Buff剩余时间
	UPROPERTY(Replicated)
	float TimeStarted;
}
// MyAction.cpp
void UMyAction::StartAction_Implementation(AActor* Instigator)
{
	// ...
    // 如果当前动作所属的组件的拥有者处于服务器角色(ROLE_Authority),防止客户端后加入时,获取的TimeSeconds与服务器不同导致错误
	if (GetOwningComponent()->GetOwnerRole() == ROLE_Authority)
	{
		// 记录动作开始的时间为当前世界的时间
		TimeStarted = GetWorld()->TimeSeconds;
	}
	GetOwningComponent()->OnActionStarted.Broadcast(GetOwningComponent(), this);
}
// 复制 TimeStarted
void UMyAction::GetLifetimeReplicatedProps(TArray<class FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);
	DOREPLIFETIME(UMyAction, TimeStarted);
}

在MyActionEffect添加方法GetTimeRemaining来获取剩余时间。

class ACTIONROGUELIKE_API UMyActionEffect : public UMyAction
{
public:		
	// 获取ActionEffect剩余时间
	UFUNCTION(BlueprintCallable, Category = "Action")
	float GetTimeRemaining() const;
}
// 用(TimeStarted + Duration - 当前时间)来获取Buff剩余时间
float UMyActionEffect::GetTimeRemaining() const
{
	// 获取当前世界的游戏状态
	AGameStateBase* GS = GetWorld()->GetGameState<AGameStateBase>();
	if (GS)
	{
		// 计算动作结束的时间(动作开始的时间加上动作的持续时间)
		float EndTime = TimeStarted + Duration;
		// 返回动作结束时间和当前服务器时间的差值,这就是动作的剩余时间
		return EndTime - GS->GetServerWorldTimeSeconds();
	}
	// 如果没有有效的游戏状态,那么就返回动作的持续时间,作为动作的剩余时间
	return Duration;
}

3、创建Buff图标材质

通过M_HealthBar复制得到M_Bufficon,并作以下修改:

  • 修改Linear Gradient,以由上到下的方向更新
  • 添加Icon变量来作为材质Opacity节点的输入,并设置BlendMode为半透明Translucent
BuffIcon材质

4、创建Buff图标Widget

创建Buff图标Widget,控件布局如下:

状态效果图标控件设置

在EventGraph中对Widget编写使用逻辑

状态效果图标蓝图设置

5、创建Buff状态栏

创建Buff状态栏Widget,控件布局如下:

状态效果栏控件设置

在EventGraph中对Widget编写使用逻辑

状态效果栏蓝图设置

6、调用Buff状态栏

在MinionHealth_Widget上调用Buff状态栏,首先添加Buff状态栏Widget,布局如下:

血量条控件设置

在蓝图中,设置Buff状态栏所属的ActionComponent

血量条蓝图设置

7、效果演示

Buff状态栏效果演示

二、一些优化


文章作者: Woilin
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Woilin !
评论
  目录