【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
4、创建Buff图标Widget
创建Buff图标Widget,控件布局如下:
在EventGraph中对Widget编写使用逻辑
5、创建Buff状态栏
创建Buff状态栏Widget,控件布局如下:
在EventGraph中对Widget编写使用逻辑
6、调用Buff状态栏
在MinionHealth_Widget上调用Buff状态栏,首先添加Buff状态栏Widget,布局如下:
在蓝图中,设置Buff状态栏所属的ActionComponent
7、效果演示
二、一些优化
略