UE5之实现技能冷却效果

1.材质

  创建一个新材质M_ColdDown,蓝图节点:

   然后将细节面板的材质域修改为用户界面,将节点连到最终颜色用做UI显示:

 2.控件

  右键 用户界面---控件蓝图 创建一个蓝图控件用做UI显示,注意这里变量的名字:

   创建一个C++类继承自 UUserWidget,这里是实际逻辑实现的地方。创建完成之后,将控件蓝图的父类指定为刚刚创建的C++类(图表---类设置---父类):

 

  OK,现在新创建的类中什么也没有,先添加一个构造函数,注意这个函数只有在控件被添加到视口的时候才会调用:

public: 
    virtual void NativeConstruct() override;

  这里因为刚刚已经设置好了父类,因此可以使用 BindWidget 绑定蓝图控件中的变量,注意变量名必须于蓝图控件中的变量名一致。同时创建一个动态材质实例用于图像的材质:

    UPROPERTY(meta = (BindWidget))
    UImage* FireImage;
    UPROPERTY(meta = (BindWidget))
    UButton* FireButton;        

    UPROPERTY()
    UMaterialInstanceDynamic* DynamicMaterial;  // 动态材质实例

  然后在构造函数中进行初始化,同时绑定Button的点击事件:

void UBoilerWidget::NativeConstruct()
{
    Super::NativeConstruct();
// 绑定点击事件
    FireButton->OnClicked.AddDynamic(this, &UBoilerWidget::OnFireImageClicked);

    // 加载材质        
    UMaterialInterface* BaseMaterial = LoadObject<UMaterialInterface>(nullptr,TEXT("/Game/_project/Materials/M_ColdDown"));
    DynamicMaterial = UMaterialInstanceDynamic::Create(BaseMaterial, this);
    DynamicMaterial->SetScalarParameterValue("color", 0.05f);
    DynamicMaterial->SetScalarParameterValue("percentage", 0.0f);
    FireImage->SetBrushFromMaterial(DynamicMaterial);
}

3.冷却效果的实现

  这里我们需要一个 Timer 计时器用来实现冷却的效果,比如在5秒内不断让进度条更新。C++中实现定时器首先我们需要一个计时器句柄 TimerHandle 用来进行管理:

    float CurrentPercentage;
    
    FTimerHandle TimerHandle; // 计时器句柄

  然后在 button 的点击函数中启动计时器:

void UBoilerWidget::OnFireImageClicked()
{
    CurrentPercentage = 1.0f;

    // 启动插值计时器
    GetWorld()->GetTimerManager().ClearTimer(TimerHandle);
    GetWorld()->GetTimerManager().SetTimer(TimerHandle, this, &UBoilerWidget::UpdateMaterialPercentage, 0.05f,true);
}

void UBoilerWidget::UpdateMaterialPercentage()
{
    if (CurrentPercentage > 0.0f)
    {
        // 计算插值(5秒内从 1 → 0)
        CurrentPercentage = FMath::FInterpConstantTo(CurrentPercentage, 0.0f, 0.05f, 1.0f / 5.0f);
        DynamicMaterial->SetScalarParameterValue("percentage", CurrentPercentage);
        FireImage->SetBrushFromMaterial(DynamicMaterial);
    }
    else
    {
        //  停止计时器
        GetWorld()->GetTimerManager().SetTimer(TimerHandle,[this]() { GetWorld()->GetTimerManager().ClearTimer(TimerHandle); },5.0f,false);
    }
}

  注意这里 UpdateMaterialPercentage() 是一个C++的委托,也就是说不能带任何参数。并且由于控件是继承自UUserWidget,属于UI系统,因此不能直接使用GetWorldTimerManager()设置计时器。

4.添加到视口

  在需要使用的地方,比如某个Actor中,创建该控件类的对象:

    UPROPERTY(EditAnywhere)
    TSubclassOf<UUserWidget> TestClass;

    UPROPERTY()
    UBoilerWidget* BoilWidget;

  并在构造函数中初始化控件蓝图的类:

    static ConstructorHelpers::FClassFinder<UBoilerWidget> WidgetClass(TEXT("/Game/_project/Materials/Boiler/NewWidgetBlueprint"));
    if (WidgetClass.Succeeded())
    {
        TestClass = WidgetClass.Class;
    }

  最后显示即可:

BoilWidget = CreateWidget<UBoilerWidget>(GetWorld(), TestClass);
BoilWidget->AddToViewport();

 5.效果

 

 

posted @ 2025-04-10 00:04  zxc0210  阅读(174)  评论(0)    收藏  举报