精华内容
下载资源
问答
  • UE4 技能系统训练教程 // CharacterBase.h // Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/Character.h" #...

    UE4 技能系统训练教程

    // CharacterBase.h
    // Fill out your copyright notice in the Description page of Project Settings.
    
    #pragma once
    
    #include "CoreMinimal.h"
    #include "GameFramework/Character.h"
    #include "AbilitySystemInterface.h"
    #include "AbilitySystemComponent.h"
    #include "Abilities/GameplayAbility.h"
    #include "CharacterBase.generated.h"
    
    class UAttributeSetBase;
    
    UCLASS()
    class ABILITYSYSTEM_API ACharacterBase : public ACharacter, public IAbilitySystemInterface
    {
    	GENERATED_BODY()
    
    public:
    	// Sets default values for this character's properties
    	ACharacterBase();
    
    protected:
    	// Called when the game starts or when spawned
    	virtual void BeginPlay() override;
    
    public:	
    	// Called every frame
    	virtual void Tick(float DeltaTime) override;
    
    	// Called to bind functionality to input
    	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
    
    	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "CharacterBase")
    		UAbilitySystemComponent* AbilitySystemComp;
    	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "CharacterBase")
    	UAttributeSetBase * AttributeSetBaseComp;
    	virtual UAbilitySystemComponent* GetAbilitySystemComponent() const;
    
    	UFUNCTION(BlueprintCallable, Category = "CharacterBase")
    		void AquireAbility(TSubclassOf<UGameplayAbility> AbilityToAquire);
    	UFUNCTION()
    		void OnHealthChanged(float Health, float MaxHealth);
    	UFUNCTION(BlueprintImplementableEvent, Category = "CharacterBase", meta = (DisplayName = "OnHealthChanged"))
    		void BP_OnHealthChanged(float Health, float MaxHealth);
    	UFUNCTION(BlueprintImplementableEvent, Category = "CharacterBase", meta = (DisplayName = "Die"))
    		void BP_Die();
    	UFUNCTION(BlueprintCallable, Category = "CharacterBase")
    		bool IsOtherHostile(ACharacterBase * Other);
    	uint8 GetTeamID() const;
    
    protected:
    	bool bIsDead;
    	uint8 TeamID;
    	void AutoDeterminTeamIDbyControllerType();
    	void Dead();
    };
    
    // CharacterBase.cpp
    // Fill out your copyright notice in the Description page of Project Settings.
    
    #include "CharacterBase.h"
    # include "AttributeSetBase.h"
    # include "GameFramework/PlayerController.h"
    # include "AIController.h"
    # include "BrainComponent.h"
    
    
    
    // Sets default values
    ACharacterBase::ACharacterBase()
    {
     	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    	PrimaryActorTick.bCanEverTick = true;
    	AbilitySystemComp = CreateDefaultSubobject<UAbilitySystemComponent>("AbilitySystemComp");
    	AttributeSetBaseComp = CreateDefaultSubobject<UAttributeSetBase>("AttributeSetBaseComp");
    	bIsDead = false;
    	TeamID = 255;
    
    }
    
    // Called when the game starts or when spawned
    void ACharacterBase::BeginPlay()
    {
    	Super::BeginPlay();
    	AttributeSetBaseComp->OnHealthChange.AddDynamic(this, &ACharacterBase::OnHealthChanged);
    	AutoDeterminTeamIDbyControllerType();
    	
    }
    
    // Called every frame
    void ACharacterBase::Tick(float DeltaTime)
    {
    	Super::Tick(DeltaTime);
    
    }
    
    // Called to bind functionality to input
    void ACharacterBase::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
    {
    	Super::SetupPlayerInputComponent(PlayerInputComponent);
    
    }
    
    UAbilitySystemComponent * ACharacterBase::GetAbilitySystemComponent() const
    {
    	return AbilitySystemComp;
    }
    
    void ACharacterBase::AquireAbility(TSubclassOf<UGameplayAbility> AbilityToAquire)
    {
    	if (AbilitySystemComp)
    	{
    		if (HasAuthority() && AbilityToAquire)
    		{
    			AbilitySystemComp->GiveAbility(FGameplayAbilitySpec(AbilityToAquire, 1, 0));
    		}
    		AbilitySystemComp->InitAbilityActorInfo(this, this);
    	}
    }
    
    void ACharacterBase::OnHealthChanged(float Health, float MaxHealth)
    {
    	if (Health<= 0.0f && !bIsDead)
    	{
    		bIsDead = true;
    		Dead();
    		BP_Die();
    	}
    	BP_OnHealthChanged(Health, MaxHealth);
    }
    
    bool ACharacterBase::IsOtherHostile(ACharacterBase * Other)
    {
    	return TeamID != Other->GetTeamID();
    }
    
    uint8 ACharacterBase::GetTeamID() const
    {
    	return TeamID;
    }
    
    void ACharacterBase::AutoDeterminTeamIDbyControllerType()
    {
    	if (GetController() && GetController()->IsPlayerController())
    		TeamID = 0;
    	{
    	}
    }
    
    void ACharacterBase::Dead()
    {
    	APlayerController * PC = Cast <APlayerController>(GetController());
    	if (PC)
    	{
    		PC->DisableInput(PC);
    	}
    	AAIController * AIC = Cast<AAIController>(GetController());
    	if (AIC)
    	{
    		AIC->GetBrainComponent()->StopLogic("Dead");
    	}
    
    }
    
    //AttributeSetBase.h
    // Fill out your copyright notice in the Description page of Project Settings.
    
    #pragma once
    
    #include "CoreMinimal.h"
    #include "AttributeSet.h"
    #include "AttributeSetBase.generated.h"
    
    /**
     * 
     */
    
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnHealthChangeDelegate, float, Health, float, MaxHealth);
    
    UCLASS()
    class ABILITYSYSTEM_API UAttributeSetBase : public UAttributeSet
    {
    	GENERATED_BODY()
    
    
    
    
    public:
    	UAttributeSetBase();
    	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AttributeSetBase")
    		FGameplayAttributeData Health;
    	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AttributeSetBase")
    		FGameplayAttributeData MaxHealth;
    	
    	void PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData &Data) override;
    	
    	FOnHealthChangeDelegate OnHealthChange;
    };
    
    // AttributeSetBase.cpp
    // Fill out your copyright notice in the Description page of Project Settings.
    
    #include "AttributeSetBase.h"
    # include "GameplayEffectExtension.h"
    # include "GameplayEffect.h"
    
    
    
    
    UAttributeSetBase::UAttributeSetBase()
    	:Health(200.0f),
    	MaxHealth(200.0f)
    {
    
    }
    
    void UAttributeSetBase::PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData & Data)
    {
    	if (Data.EvaluatedData.Attribute.GetUProperty() == FindFieldChecked<UProperty>(UAttributeSetBase::StaticClass(), GET_MEMBER_NAME_CHECKED(UAttributeSetBase, Health)))
    	{
    		Health.SetCurrentValue(FMath::Clamp(Health.GetCurrentValue(), 0.f, MaxHealth.GetCurrentValue()));
    		Health.SetBaseValue(FMath::Clamp(Health.GetBaseValue(), 0.f, MaxHealth.GetCurrentValue()));
    		UE_LOG(LogTemp, Warning, TEXT("Ouch, I took some damage, now my health is :%f"), Health.GetCurrentValue());
    		OnHealthChange.Broadcast(Health.GetCurrentValue(), MaxHealth.GetCurrentValue());
    	}
    }
    
    
    //AbilitySystem.Build.cs
    // Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
    
    using UnrealBuildTool;
    
    public class AbilitySystem : ModuleRules
    {
    	public AbilitySystem(ReadOnlyTargetRules Target) : base(Target)
    	{
    		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
    
    		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay","GameplayAbilities", "GamePlayTags", "GameplayTasks", "AIModule" });
    	}
    }
    
    展开全文
  • UE4 技能系统训练教程 // CharacterBase.h // Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/Character.h" #...

    UE4 技能系统训练教程

    // CharacterBase.h
    // Fill out your copyright notice in the Description page of Project Settings.
    
    #pragma once
    
    #include "CoreMinimal.h"
    #include "GameFramework/Character.h"
    #include "AbilitySystemInterface.h"
    #include "AbilitySystemComponent.h"
    #include "Abilities/GameplayAbility.h"
    #include "CharacterBase.generated.h"
    
    
    UCLASS()
    class ABILITYSYSTEM_API ACharacterBase : public ACharacter, public IAbilitySystemInterface
    {
    	GENERATED_BODY()
    
    public:
    	// Sets default values for this character's properties
    	ACharacterBase();
    
    protected:
    	// Called when the game starts or when spawned
    	virtual void BeginPlay() override;
    
    public:	
    	// Called every frame
    	virtual void Tick(float DeltaTime) override;
    
    	// Called to bind functionality to input
    	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
    
    	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "CharacterBase")
    		UAbilitySystemComponent* AbilitySystemComp;
    	virtual UAbilitySystemComponent* GetAbilitySystemComponent() const;
    
    	UFUNCTION(BlueprintCallable, Category = "CharacterBase")
    		void AquireAbility(TSubclassOf<UGameplayAbility> AbilityToAquire);
    };
    
    // CharacterBase.cpp
    // Fill out your copyright notice in the Description page of Project Settings.
    
    #include "CharacterBase.h"
    //#include "../Public/CharacterBase.h"
    
    
    // Sets default values
    ACharacterBase::ACharacterBase()
    {
     	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    	PrimaryActorTick.bCanEverTick = true;
    	AbilitySystemComp = CreateDefaultSubobject<UAbilitySystemComponent>("AbilitySystemComp");
    
    }
    
    // Called when the game starts or when spawned
    void ACharacterBase::BeginPlay()
    {
    	Super::BeginPlay();
    	
    }
    
    // Called every frame
    void ACharacterBase::Tick(float DeltaTime)
    {
    	Super::Tick(DeltaTime);
    
    }
    
    // Called to bind functionality to input
    void ACharacterBase::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
    {
    	Super::SetupPlayerInputComponent(PlayerInputComponent);
    
    }
    
    UAbilitySystemComponent * ACharacterBase::GetAbilitySystemComponent() const
    {
    	return AbilitySystemComp;
    }
    
    void ACharacterBase::AquireAbility(TSubclassOf<UGameplayAbility> AbilityToAquire)
    {
    	if (AbilitySystemComp)
    	{
    		if (HasAuthority() && AbilityToAquire)
    		{
    			AbilitySystemComp->GiveAbility(FGameplayAbilitySpec(AbilityToAquire, 1, 0));
    		}
    		AbilitySystemComp->InitAbilityActorInfo(this, this);
    	}
    }
    
    
    // AbilitySystem.Build.cs
    // Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
    
    using UnrealBuildTool;
    
    public class AbilitySystem : ModuleRules
    {
    	public AbilitySystem(ReadOnlyTargetRules Target) : base(Target)
    	{
    		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
    
    		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay","GameplayAbilities", "GamePlayTags", "GameplayTasks" });
    	}
    }
    
    
    展开全文
  • UE 4 虚幻引擎游戏开发综合开发能力训练(技能系统的练习)视频教程 全部完结。这是最终全部写完的代码,可以拿来对照。
  • 翻译自Udemy的视频课程introduction-to-unreal-engine-4-ability-system ...01、首先在UE4中启用插件, 02、由于GAS还不完全支持蓝图,需要用到C++ ,首先在工程的cs配置文件中添加"GameplayAbilities", "...

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

    MeleeAttackAbility 近战攻击技

    1、用C++继承AbilitySystem中的方法和组件

    01、首先在UE4中启用插件,

    02、由于GAS还不完全支持蓝图,需要用到C++ ,首先在工程的cs配置文件中添加 "GameplayAbilities", "GameplayTags", "GameplayTasks",添加后编译一遍工程,有必要的话重新再打开工程,以便VS2019能够识别一些新加载的符号

    PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" , "GameplayAbilities", "GameplayTags", "GameplayTasks" });

    03、BaseCharacter.cpp文件中添加头文件,并且继承IAbilitySystemInterface接口,在其中添加一个UAbilitySysrtemComponent,另外继承接口就需要重写方法

    // Fill out your copyright notice in the Description page of Project Settings.

    #pragma once

    #include "CoreMinimal.h"
    #include "GameFramework/Character.h"
    #include "AbilitySystemInterface.h"
    #include "AbilitySystemComponent.h"

    #include "BaseCharacter.generated.h"

    UCLASS()
    class ABILITYSYSTEM_API ABaseCharacter : public ACharacter,public IAbilitySystemInterface
    {
    //IAbilitySystemInterface是用于获取AbilitySystemComponent的接口,
    //其内部就只有一个GetAbilitySystemComponent()纯需方法方法

        GENERATED_BODY()

    public:
        // Sets default values for this character's properties
        ABaseCharacter();

    protected:
        // Called when the game starts or when spawned
        virtual void BeginPlay() override;

    public:    
        // Called every frame
        virtual void Tick(float DeltaTime) override;

        // Called to bind functionality to input
        virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
        //声明一个UAbilitySystemComponent组件,一样的使用CreateDefaultSubobject的方式来定义
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = BaseCharacter)
        UAbilitySystemComponent* AbilitySystemComp;

        //重写接口中的虚方法
        virtual UAbilitySystemComponent* GetAbilitySystemComponent()const;

        //该函数用于获取具体的Ability
        UFUNCTION(BlueprintCallable, Category = BaseCharacter)
            void AquireAbility(TSubclassOf<UGameplayAbility>AbilityToAquire);

    };
     

    // Fill out your copyright notice in the Description page of Project Settings.


    #include "public/BaseCharacter.h"

    // Sets default values
    ABaseCharacter::ABaseCharacter()
    {
         // Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
        PrimaryActorTick.bCanEverTick = true;
        AbilitySystemComp = CreateDefaultSubobject<UAbilitySystemComponent>("AbilitySystemComp");
    }

    // Called when the game starts or when spawned
    void ABaseCharacter::BeginPlay()
    {
        Super::BeginPlay();
        
    }

    // Called every frame
    void ABaseCharacter::Tick(float DeltaTime)
    {
        Super::Tick(DeltaTime);

    }

    // Called to bind functionality to input
    void ABaseCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
    {
        Super::SetupPlayerInputComponent(PlayerInputComponent);

    }

    UAbilitySystemComponent* ABaseCharacter::GetAbilitySystemComponent()const {
        return AbilitySystemComp
    }
    void ABaseCharacter::AquireAbility(TSubclassOf<UGameplayAbility> AbilityToAquire)
    {
        //先判断AbilitySytemcomp是否为空
        if (AbilitySystemComp) {
            //HasAuthrity用于判断客户端是否对Actor有控制权
            //再判断传入的技能是否为空

            if (HasAuthority() && AbilityToAquire) {
                //GiveAbility用于具体的为AbilitySystemComp赋予能力,会调用TryActiveAbility
                //FGameplayAbilitySpec是一个用于存储被赋予Ability相关的数据信息的结构体

                AbilitySystemComp->GiveAbility(FGameplayAbilitySpec(AbilityToAquire, 1, 0));
                //InitAbilityActorInfo用于说明是谁在逻辑上控制Actor(Pawn、Characrter等等)、谁在物理上控制(可以是建筑,也可能和OwnedActor相同)
                AbilitySystemComp->InitAbilityActorInfo(this, this);
            }
        }
    }

    04、视频中推荐使用番茄插件,其实我并不推荐。一是版权问题(正版并不是太贵),二是性能问题(如果开多线程,每次打开工程CPU会满载),三是安全性(破解的基本都带有病毒),四是目前VS2019对UE4的智能提示已经可以了,里面的符号基本上都能加载出来,没必要再搞个插件。

    05、添加.gitignore文件,里面加入一行Content/ParagonShinbi/ 用于忽略掉商城的资源,可以在VS2019中看到目前为止的改动的文件数,

    另外上传到仓库的资源大小为787K,

     

    2、创建Melee Ability和Cool Down

    01、创建一个GameplayAbility蓝图,命名为GA_Melee,这个可以在BP_BaseCharacter中用AquireAbility获取,在之前一节中PrimaryAttack会play montage,现在把它放到GA_Melee中,使用playMontageAndWait节点,同样的把Rate调低一点,使得动画播放的不要太快

    02、在人物蓝图中,使用AquireAbility(这是在C++中写的函数)获取与使用TryActiveAbilityByClass触发技能,可以看到,把人物蓝图中的play montage放到具体的技能中

    03、创建GamePlayEffect蓝图GE_Melee_CoolDown,GamePlayEffect这个是纯信息类,主要是用于说明法术消耗,能量消耗,冷却时间等信息,需要在GA_Melee中的ClassDefaults中的CoolDowns中指定Cost Gameplay EffectClass为GameEffect_Melee

    04、另外具体设置GE_Melee_CoolDown里的信息,

    05、 添加tag,当一个AbilitySystemComp获得一个技能的时候,他也会相应的增加一个与技能相关的Tag,当该技能冷却完成后,会移除相应的Tag,从而能够再次释放,这里需要填在GrantedTags中,填错Cool Down没效果

    06、为了使得CoolDown生效,需要在GA_Melee中 ActiveAbility事件中CommitAbility

    3、创建属性集和health属性

    当前我们有了Melee attack这个技能,我们想让这个技能发生作用,需要用到attribute set

    01、创建C++ AttributeSet 类,命名为BaseAttributeSet,

    #pragma once

    #include "CoreMinimal.h"
    #include "AttributeSet.h"
    #include "BaseAttributeSet.generated.h"

    /**
     * 
     */
    UCLASS()
    class ABILITYSYSTEM_API UBaseAttributeSet : public UAttributeSet
    {
        GENERATED_BODY()

    public:
        //创建一个构造函数
        UBaseAttributeSet();

        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AttributeSet)
            FGameplayAttributeData Health;
        //FGameplayAttributeData拥有BaseValue和AttributeValue两个值

    };

    #include "BaseAttributeSet.h"

    UBaseAttributeSet::UBaseAttributeSet() :Health(200.f)
    {    

    //构造函数用于初始化Health

    }

     

     02、然后要让我们的BaseCharacter拥有这个Attribute Set,使用前置声明的方式添加如下代码

    //声明一个和UBaseAttributeSet组件,一样的使用CreateDefaultSubobject的方式来定义
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = BaseCharacter)
        class UBaseAttributeSet* AttributeSetComp;

    #include "public/BaseCharacter.h"
    #include "BaseAttributeSet.h"
    // Sets default values
    ABaseCharacter::ABaseCharacter()
    {
         // Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
        PrimaryActorTick.bCanEverTick = true;
        AbilitySystemComp = CreateDefaultSubobject<UAbilitySystemComponent>("AbilitySystemComp");
        AttributeSetComp = CreateDefaultSubobject<UBaseAttributeSet>("AttributeSetComp");
    }

    03、编译,然后就可以在BP_BaseCharacter中Get和Set这个AttributeSetComp了。如下代码打印测试CurrentHealth值

    4、添加Melee Overlaping事件

    01、为Mesh中的sword添加capsule碰撞体,调整Socket为Weapon_r,调节大小和位置,效果如下

    02、ctrl+W复制BP_BaseCharacter,命名为BP_Enemy,修改Enemy的Mesh,换一个皮肤,以便区分(原视频是先02后01,不妥)

    03、为SwordCollision添加Overlap事件,需要判断一下碰撞到的物体是不是敌人,不能是剑,也不能是自身,

    首先设置SwordCollision,只和Pawn发生碰撞,

     在Ovelap事件中首先判断不能是自身,然后判断是否是敌人,是的话,打印碰撞体的名称

    为了屏幕更清晰,断开其他Print String的连接,也可以观察到一次攻击会产生多个碰撞检测。需要在下一节中设置notify来解决

     5、Animation Notify State and Send GameplayEvent

    实现的功能就是普通状态,即没有进行攻击动作的时候,Sword是不进行碰撞检测的,只有当攻击动作进行,即动画蒙太奇播放的时候,在Notify处才进行碰撞检测。

    01、首先,将SwordCollision设置CollisionEnabled为NoCollision,这样子在普通状态下无碰撞检测

     02、创建一个蓝图AnimationNotifyState,命名为ANS_MeleeAttack,首先要在Montage中使用这个NotifyState,放到8-10帧的位置上

    03、ANS_MeleeAttack其中的EventGraph重写NotifyBegin和NotifyEnd方法

    首先getowner,如果是BP_BaseCharacter的话,获取SwordCollision,然后EnableCollision,设置为query only,不检测physicbody

    首先getowner,如果是BP_BaseCharacter的话,获取SwordCollision,然后DisableCollision,

    04、现在想在Sword发生碰撞的时候发送GameplayEvent事件(这是GAS自带的事件),其中payload传递技能所作用于的对象

    ,使用GameplayEventData打包Sword碰撞到的物体作为Payload

    05、,然后就可以在GA_Melee中监听gameplayEvent,在playmontage后修改如下
    :当Montage播放完成的时候,应该EndAbility,

    6、处理伤害

    01、处理伤害需要另外的GameplayEffect,命名为GE_Melee_Damage,指定作用的属性值Health,伤害的大小-20,为Instant立即伤害

    02、增添一个新的tag,这次是使用GameplayEffectAssetTag

    03、在GA_Melee中实际使用这个GameplayEffect,将之前的printstring 替换如下,作用就是将Damage实际应用到Health上

    04、为了实际的查看应用的效果,C++中在BaseAttributeSet重写PostGameplayEffectExecute方法,该方法会在属性值发生修改后执行(UE4.22中这个不能正常工作,没能够正常的打印,Debug时不会执行这一块的代码,也就是说,没能够正常的修改属性值,)问题解决了,之前的BP_Enemy在复制的过程中AttributeSet comp为none,所以对Enmemy使用ApplyDamageToTarget的时候并不会对Health产生影响。应该从BP_BaseCharacter重新派生一个BP_BaseEnemy出来(用派生的方式产生类,不要用复制的方式)

    在BaseAttributeSet.h中添加:

        virtual void PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data)override;

    对应的Cpp文件中添加 

    #include "BaseAttributeSet.h"
    #include"GameplayEffect.h"
    #include "GameplayEffectExtension.h"

    //PostGameplayEffectExecute是在属性值发生修改后自动调用
    void UBaseAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
    {

        if (Data.EvaluatedData.Attribute.GetUProperty() == FindFieldChecked<UProperty>(UBaseAttributeSet::StaticClass(), GET_MEMBER_NAME_CHECKED(UBaseAttributeSet, Health))) {
            //暂时先打印修改后的属性值
            UE_LOG(LogTemp, Warning, TEXT("Oh,i got som damagem,now my health is:%f"),Health.GetCurrentValue());
        }
    }
     

     

     7、添加生命值UI

    01、制作HealthBar,锚点居中,添加一个ProgressBar,调整颜色,大小等

     02、在Graph中添加一个custom event,命名为SetPercentage,添加一个float型的输入percentage,

     03、在BaseAttributeSet中设置一个Delegate,用来传递属性值的修改

    #include "CoreMinimal.h"
    #include "AttributeSet.h"
    #include "BaseAttributeSet.generated.h"

    /**
     * 
     */
    //创建一个Multicast多播类型的委托,里面传入两个参数
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnHealthChangeDelegate, float, Health, float, MaxHealth);
    UCLASS()
    class ABILITYSYSTEM_API UBaseAttributeSet : public UAttributeSet
    {
        GENERATED_BODY()

    public:
        //创建一个构造函数
        UBaseAttributeSet();
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AttributeSet)
            FGameplayAttributeData Health;
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AttributeSet)
            FGameplayAttributeData MaxHealth;

        //FGameplayAttributeData拥有BaseValue和AttributeValue两个值
        virtual void PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data)override;
        FOnHealthChangeDelegate OnHealthChange;
    };

     04、在PostGameplayEffectExecute中广播出去

    UBaseAttributeSet::UBaseAttributeSet() :Health(200.f),MaxHealth(200.f)
    {
        //构造函数用于初始化Health
    }

    void UBaseAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
    {

        if (Data.EvaluatedData.Attribute.GetUProperty() == FindFieldChecked<UProperty>(UBaseAttributeSet::StaticClass(), GET_MEMBER_NAME_CHECKED(UBaseAttributeSet, Health))) {
            //暂时先打印修改后的属性值
            UE_LOG(LogTemp, Warning, TEXT("Oh,i got som damagem,now my health is:%f"),Health.GetCurrentValue());
            //当属性值发生修改的时候广播出去
            OnHealthChange.Broadcast(Health.GetCurrentValue(), MaxHealth.GetCurrentValue());
        }
    }

    05、在BaseCharacter中接收 

        UFUNCTION()
            void OnHealthChange(float Health, float MaxHealth);
        UFUNCTION(BlueprintImplementableEvent, Category = BaseCharacter)
            void BP_OnHealthChange(float Health, float MaxHealth);//蓝图中实现

    // Called when the game starts or when spawned
    void ABaseCharacter::BeginPlay()
    {
        Super::BeginPlay();
        //在BeginPlay中动态的绑定委托
        AttributeSetComp->OnHealthChange.AddDynamic(this, &ABaseCharacter::OnHealthChange);
    }

    void ABaseCharacter::OnHealthChange(float Health, float MaxHealth)
    {
        BP_OnHealthChange(Health, MaxHealth);//通知蓝图事件调用
    }
     

    06、在BP_BaseEnemy中添加一个widget,命名为HealthBar,并且指定其中的UI为HealthBar

     07、在BP_BaseEnemy的EventGraph中,设置HealthBar的数值显示

    08、有必要重新关闭Editor,再打开编译一下,运行后效果如下就OK了

     8、添加死亡动画

    01、首先为了人物的生命值不会降低到0以下,需要添加

    void UBaseAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
    {

        if (Data.EvaluatedData.Attribute.GetUProperty() == FindFieldChecked<UProperty>(UBaseAttributeSet::StaticClass(), GET_MEMBER_NAME_CHECKED(UBaseAttributeSet, Health))) {
            //这一段的逻辑放在PreAttributeChange(这个是在属性值发生修改前调用)更好一些
            Health.SetCurrentValue(FMath::Clamp(Health.GetCurrentValue(), 0.f, MaxHealth.GetCurrentValue()));
            Health.SetBaseValue(FMath::Clamp(Health.GetBaseValue(), 0.f, MaxHealth.GetCurrentValue()));

            //暂时先打印修改后的属性值
            UE_LOG(LogTemp, Warning, TEXT("Oh,i got som damagem,now my health is:%f"),Health.GetCurrentValue());
            //当属性值发生修改的时候广播出去
            OnHealthChange.Broadcast(Health.GetCurrentValue(), MaxHealth.GetCurrentValue());
        }
    }

    02、当生命值为0时,播放死亡动画,再在BaseCharacter中添加一个蓝图事件函数

        UFUNCTION(BlueprintImplementableEvent, Category = BaseCharacter)
            void BP_Die();
    protected:
        bool bIsDeath;

    void ABaseCharacter::OnHealthChange(float Health, float MaxHealth)
    {
        if (Health <= 0.f&& !bIsDeath) {
            //生命值小于0,调用蓝图事件来播放死亡动画
            bIsDeath = true;
            BP_Die();
            
        }
        BP_OnHealthChange(Health, MaxHealth);//通知蓝图事件调用
    }

    03、在BP_BaseEnemy中 ,另外需要添加AM_ShinbiDeath动画蒙太奇,注意指定该蒙太奇的Slot

    接下来一节介绍设置简单的敌人AI,让敌人能够发现玩家,并且移动至玩家处,然后使用MeleeAttack技能

    展开全文
  • 翻译自Udemy的视频课程introduction-to-unreal-engine-4-ability-system Build Basic Classes 创建基础类 1、创建工程和人物设置 01、创建Git仓库,使用UE4.22 + VS2019 创建C++基础工程,并添加Paragon Shinbi到...

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

    Build Basic Classes 创建基础类

    1、创建工程和人物设置

    01、创建Git仓库,使用UE4.22 + VS2019 创建C++基础工程,并添加Paragon Shinbi到工程中

    02、创建C++ BaseCharacter,并且基于该Character派生蓝图子类BP_BaseCharacter

    03、BP_BaseCharacter中指定Mesh,添加SpringArm和Camera,适当调整位置,编译保存

    04、创建蓝图GameMode,命名为BP_GameMode,在其中指定Default Pawn class为BP_BaseCharacter,并且在项目工程设置里(Edit->Project Settings->Maps and Modes)设置Default Mode为BP_GameMode

    2、为Shinbi添加基础移动控制

    01、Edit->Project Settings->Input 添加输入

    02、创建C++ Player Controller类,并基于此派生蓝图子类BP_BasePlayerController,在GameMode中指定PlayerController为BP_BasePlayerController

    03、在BP_BasePlayerController的EventGraph中添加基础的移动控制逻辑

     3、添加相机的旋转控制

    01、在BP_BasePlayerController的EventGraph中添加基础的相机控制逻辑

     这里设置后不能够控制相机的Pitch

    相应的需要在BP_BaseCharacter中设置继承Controller的Pitch和Yaw以便使得Character来使用Controller的旋转,然而你会发现旋转相机的时候人物也会跟着上下旋转

    所以采用另一种方式:C++中经常会对SpringArm说bUsePawnControlRoation=true也是这个道理

    SpringArm中:

     02、当前的相机设置是符合射击游戏需求的,但是RGP游戏中经常想观察人物(。。。),即不想让左右旋转相机的时候让人物跟着动,将Use Controller Rotation Yaw取消勾选。

     另外还要再Movement component中勾选Oriten Rotation to Movement,这样子在移动的时候,人物在移动的时候会自动转向相机所面对的方向

     03、当在移动的时候相机旋转的太快,人物在转向相机的方向时候不自然,将Rotation Rate 设置的大一些,如720

    4、动画蓝图中的EventGraph

    01、创建animation blueprint,命名为AnimBP_Shinbi。

    02、EventGraph中主要是获取Velocity(用于驱动动画是否奔跑)和IsFalling(用于驱动动画是否跳跃)

     三个变量OwnedCharacter、MeshSpaceVelocity、IsFalling

    5、动画蓝图中使用BlendSpace

    01、AnimGraph的逻辑是通过状态机实现的,添加一个statemachine,locomotion表明动画发生在local space

    02、创建一个BlendSpace,命名为BS_Idle_Walk_Run

    03、在动画蓝图中使用该BlendSpace

    6、动画蓝图中添加Jump

    01、状态机中添加对应的动画与转换逻辑(简化了Jump部分的逻辑)

     

     7、使用动画蒙太奇做Melee Attack

    在动画蓝图中,Animation montage的播放时通过slot来完成的,

    01、创建Animation montage,命名为AM_Shinbi_Melee

    02、拖入想要播放的动画片段,可以指定自定义的slot

     03、动画蓝图中,添加一个slot,指明为自定义的slot

    04、在BP_BaseCharacter中创建一个Custom Event,当该事件发生的时候用来播放攻击的动画蒙太奇

    05、设置输入PrimaryAction绑定到鼠标左键,在BP_PlayerController中的鼠标输入事件中调用MeleeAttack

    8、想要在播放动画蒙太奇的过程中不打断下半身的运动,使用layerblendPerBone节点

    其中该节点的相关设置,参照Shinbi自带蓝图

    (说明,这里的动画上下半身不自然是由于上半身有一个360度转体的动作,如果没有较大转体的动作话会较自然一些,所以将之前的动画蒙太奇中的动画片段改为使用PrimaryMelee_D_Slow),如果我就是想用这种转体较大的动作时,我应该如何做呢?所以就有了下一节:

    9、针对Montage中添加Notify

    01、第一帧的时候添加一个Notify,命名为StartFullBody,适当的位置添加StartHalfBody

     02、动画蓝图中就会相应的获取到相应的通知事件,设置一个bool变量

     03、AnimGraph中应用BlendPosesByBool

     (说明,这相当于是强制性的播放完整动画,感觉在有的动画播放的时候应该停止移动,在接收到Start HalfBody这个通知的时候才可以移动,这样子才比较合适,如下是我自己添加的部分,主要是在人物中添加了两个CustomEvent用于设置MaxWalkSpeed的大小),此外还需要设置动画的播放速度,太快了反而缺乏感觉

     由于GAS还不完全支持蓝图,需要用到C++,在下一篇中继续记录

    展开全文
  • UE4 技能系统(GAS插件的使用) 06

    千次阅读 2019-07-27 12:30:18
    翻译自Udemy的视频课程introduction-to-unreal-engine-4-ability-system 设置UI图标,通过代码来获取与设置UI信息(冷却,Cost等) 1、首先创建一个材质,用于技能的图标,然后基于该图标创建一个Slot 2、设置...
  • // CharacterBase.h // Fill out your ... #pragma once #include "CoreMinimal.h" #include "GameFramework/Character.h" #include "AbilitySystemInterface.h" #include "AbilitySystemComponent.h" #include
  • Data) { if (Data.EvaluatedData.Attribute.GetUProperty() == FindFieldChecked(UAttributeSetBase::StaticClass(), GET_MEMBER_NAME_CHECKED(UAttributeSetBase, Health))) { UE_LOG(LogTemp, Warning, TEXT(...
  • 翻译自Udemy的视频课程introduction-to-unreal-engine-4-ability-system Health Regen Ability生命回复技 1、设置UI显示自身的生命值 说明下本节要达到的效果:玩家有自身的UI,用于显示自身的生命值变化(UI的...
  • 翻译自Udemy的视频课程introduction-to-unreal-engine-4-ability-system AI SetUp设置简单的敌人AI 1、设置行为树 01、创建BehaviorTree行为树,命名为BT_Enemy,再创建一个BlackBoard,命名为BB_Enemy.其中行为树...
  • 翻译自Udemy的视频课程introduction-to-unreal-engine-4-ability-system 所有翻译内容仅供个人学习参考使用 ,这一篇作为进阶的过渡篇 对于LaserAbility:(这个技能属于持续消耗法力值,持续发动),表现力不够...
  • 翻译自Udemy的视频课程introduction-to-unreal-engine-4-ability-system 所有翻译内容仅供个人学习参考使用 写完这个系列打算再去看看ActionRPG的源码,吸取点经验。 1、创建激光束材质(材质制作不是重点,可以用...
  • 翻译自Udemy的视频课程introduction-to-unreal-engine-4-ability-system Dashing Ability冲刺技 1、创建DashAbility,在里面添加使人物向前冲刺的逻辑 01、创建蓝图GameplayAbility,里面的逻辑就是,先获取当前...
  • UE4-Gameplay技能系统

    2021-04-16 11:19:53
    Gameplay技能系统能够帮助我们实现任何RPG或MOBA中设计的技能。可以便利的进行这些动作的 冷却倒计时 资源消耗 更改技能等级 技能效果配置(粒子系统、音效等等) 系统配置 由于Gameplay技能...
  • @[TOC](ue4技能系统(GameplayAbilitySystem)的学习) 第一章 搭建环境 最近学习了ue4技能系统 ,为了加深理解和记忆,所以写下此文。用的是UE4 4.25版本。由于技能系统尚不完全支持蓝图系统 ,所以要用C++项目...
  • Unreal Engine 4(虚幻UE4)GameplayAbilities 插件入门教程(七)Ability的信息传递等 Unreal Engine 4(虚幻UE4)GameplayAbilities 插件入门教程(六)GameplayEffect的级别设置 Unreal Engine...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,403
精华内容 561
关键字:

ue4技能系统