淘先锋技术网

首页 1 2 3 4 5 6 7

翻译自Udemy的视频课程introduction-to-unreal-engine-4-ability-system

设置UI图标,通过代码来获取与设置UI信息(冷却,Cost等)

 1、首先创建一个材质,用于技能的图标,然后基于该图标创建一个Slot

2、设置PrimaryUI

3、代码中需要能够获取技能相关的信息

01、创建一个用于表示技能信息的结构体,具体方式为:创建一个C++actor,命名为AbilityTypes,把它修改成Struct,这种方式比自己手动编码添加Struct要方便(Enum亦然)

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "AbilityTypes.generated.h"

//表示当前能力的消耗类型
UENUM(BlueprintType)
enum class EAbilityCostType :uint8 {
    Health,
    Mana,
    Strength
};

USTRUCT(BlueprintType)
struct FGameplayAbilityInfo {
    GENERATED_BODY()

    
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AbilityInfo")
        float CooldownDuration;
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AbilityInfo")
        float Cost;    
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AbilityInfo")
        EAbilityCostType CostType;
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AbilityInfo")
        UMaterialInstance* UIMat; //slot图标
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AbilityInfo")
        TSubclassOf<class UBaseGameplayAbility>AbilityClass; //对应的AbilityClass类
    //两个构造函数
    FGameplayAbilityInfo();
    FGameplayAbilityInfo(float InCooldownDuration,float InCost, EAbilityCostType InCostType, UMaterialInstance* InUIMat, TSubclassOf<class UBaseGameplayAbility>InAbilityClass);
};

.cpp文件中需要完成两个构造函数 


#include "AbilityTypes.h"

FGameplayAbilityInfo::FGameplayAbilityInfo()
:CooldownDuration(0.f),
Cost(0),
CostType(EAbilityCostType::Mana),
UIMat(nullptr),
AbilityClass(nullptr)
{
}

FGameplayAbilityInfo::FGameplayAbilityInfo(float InCooldownDuration, float InCost, EAbilityCostType InCostType, UMaterialInstance* InUIMat, TSubclassOf<class UBaseGameplayAbility> InAbilityClass)
:CooldownDuration(InCooldownDuration),
Cost(InCost),
CostType(InCostType),
UIMat(InUIMat),
AbilityClass(InAbilityClass)
{
}

 02、创建一个C++GameplayAbility类,命名为BaseGameplayAbility,提供所创建的结构体信息的访问方式(GetAbilityInfo),方便程序调用

#pragma once

#include "CoreMinimal.h"
#include "Abilities/GameplayAbility.h"
#include "AbilityTypes.h"
#include "BaseGameplayAbility.generated.h"


UCLASS()
class ABILITYSYSTEM_API UBaseGameplayAbility : public UGameplayAbility
{
    GENERATED_BODY()
public:
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AbilityBase")
        UMaterialInstance* UIMaterial;
    UFUNCTION(BlueprintCallable)
        FGameplayAbilityInfo GetAbilityInfo();
};

对应CPP文件

#include "BaseGameplayAbility.h"

FGameplayAbilityInfo UBaseGameplayAbility::GetAbilityInfo()
{
    UGameplayEffect* CoolDownEffect = GetCooldownGameplayEffect();
    UGameplayEffect* CostEffect = GetCostGameplayEffect();
    if (CoolDownEffect && CostEffect) {    
        float CoolDownDuration = 0;
        float Cost = 0;
        EAbilityCostType CostType;
        CoolDownEffect->DurationMagnitude.GetStaticMagnitudeIfPossible(1, CoolDownDuration);        
        if (CostEffect->Modifiers.Num() > 0)
        {
            FGameplayModifierInfo EffectInfo = CostEffect->Modifiers[0];
            EffectInfo.ModifierMagnitude.GetStaticMagnitudeIfPossible(1, Cost);
            FGameplayAttribute CostAttr = EffectInfo.Attribute;
                FString AttributeName = CostAttr.AttributeName;
                if (AttributeName == "Health")
                {
                    CostType = EAbilityCostType::Health;
                }
                else if (AttributeName == "Mana")
                {
                    CostType = EAbilityCostType::Mana;
                }
                else if (AttributeName == "Strength")
                {
                    CostType = EAbilityCostType::Strength;
                }
                //确保获取了所有的信息
                return FGameplayAbilityInfo(CoolDownDuration, Cost, CostType, UIMaterial, GetClass());
        }
    }
    return  FGameplayAbilityInfo();
}
 

 

03、在BasePlayerController中添加AddAbilityToUI方法(使用蓝图继承重写),用于对每个技能设置图标

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "AbilityTypes.h"
#include "BasePlayerController.generated.h"


UCLASS()
class ABILITYSYSTEM_API ABasePlayerController : public APlayerController
{
    GENERATED_BODY()
public:
    UFUNCTION(BlueprintImplementableEvent, Category = "PlayControllerBase")
        void AddAbilityToUI(FGameplayAbilityInfo AbilityInfo);
};

 

04、在BaseCharacter中同样添加AddAbilityToUI,用于调用PlayerController的AddAbilityToUI方法,同样提供获取一堆技能的方法

    UFUNCTION(BlueprintCallable, Category = BaseCharacter)
    //用于获取一堆技能
        void AquireAbilities(TArray<TSubclassOf<UGameplayAbility>>AbilitiesToAquire);

private:

void AddAbilityToUI(TSubclassOf<class UBaseGameplayAbility>AbilityToAdd);

对应的CPP文件中,实现添加的方法(注意添加头文件)

#include "BaseGameplayAbility.h"
#include "AbilityTypes.h"

void ABaseCharacter::AquireAbilities(TArray<TSubclassOf<UGameplayAbility>> AbilitiesToAquire)
{
    for (TSubclassOf<UGameplayAbility> AbilityItem:AbilitiesToAquire)
    {
        AquireAbility(AbilityItem);
        //如果是UBaseGameplayAbility的子类,说明可以添加UI
        if (AbilityItem->IsChildOf(UBaseGameplayAbility::StaticClass()))
        {
            //这里加*与不加的区别?
            TSubclassOf<UBaseGameplayAbility>AbilityBaseClass = *AbilityItem;
            if (AbilityBaseClass != nullptr)
            {
                AddAbilityToUI(AbilityBaseClass);
            }
        }
    }
}

void ABaseCharacter::AddAbilityToUI(TSubclassOf<class UBaseGameplayAbility> AbilityToAdd)
{
    ABasePlayerController* PlayerControllerBase = Cast<ABasePlayerController>(GetController());
    if (PlayerControllerBase)
    {
        UBaseGameplayAbility* AbilityInstance = AbilityToAdd.Get()->GetDefaultObject<UBaseGameplayAbility>();
        if (AbilityInstance)
        {
            FGameplayAbilityInfo AbilityInfo = AbilityInstance->GetAbilityInfo();
            PlayerControllerBase->AddAbilityToUI(AbilityInfo);//最终实现是在蓝图中
        }
    }
}
 

 4、蓝图中实际设置,和UI紧密相关(要是教程的话必须把UI那块也细讲,个人参考时主要理清做了什么,以及之间的联系)

01、首先是Slot:可以根据AbilityInfo来更新图标和Cost信息,可以自定义StartCoolDown事件,在EventTick中更新CoolDown的图标信息

02、PrimaryUI:自定义AddAbilityToSlot函数来添加技能图标,自定义GetSlotAbilityClass函数来获取技能槽中的技能类,EventConstruct里面用于设置图标

03、PlayerController中自定义TryActiveAbilityInSlot函数,设置按键输入绑定,调用各个槽的技能

04、创建BP_BaseGameplayAbility,是C++BaseGameplayAbility的子类,在里面添加一个DoUICoolDown方法,用于调用Slot的StartCoolDown事件

05、将HealthRegen和Dash技能的父类设置为BP_BaseGameplayerAbility。并且为每个技能的CommitAbility后调用DoUICoolDown方法

最终的效果为:调用技能,技能显示冷却(当然也可以优化,当Cost为0的时候,就不显示Cost的值等等)