文件结构:
更改文件将高亮显示
Source
- Private
- AbilitySystemComponen
- RPGAbilitySystemComponent.cpp
- RPGAttributeSet.cpp
- Character
- PGGameCharacterBase.cpp
- RPGGameEnemy.cpp
- RPGGamePlayerCharacter.cpp
- Game
- RPGGameModeBase.cpp
- Interaction
- EnemyInterface.cpp
- Player
- RPGPlayerController.cpp
- RPGPlayerState.cpp
- Actor
- RPGEffectActor.cpp
- AbilitySystemComponen
- Public
- AbilitySystemComponent
- RPGAbilitySystemComponent.h
- RPGAttributeSet.h
- Character
- RPGGameCharacterBase.h
- RPGGameEnemy.h
- RPGGamePlayerCharacter.h
- Game
- RPGGameModeBase.h
- Interaction
- EnemyInterface.h
- Player
- RPGPlayerController.h
- RPGPlayerState.h
- Actor
- RPGEffectActor.h
- AbilitySystemComponent
文件表述:
RPGAttributeSet
.h文件
新增四个属性,同时考虑多人游戏情况
// Copyright KimiLiu
#pragma once
#include "CoreMinimal.h"
#include "AbilitySystemComponent.h"
#include "AttributeSet.h"
#include "RPGAttributeSet.generated.h"
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
/**
* AS拥有预测功能(Prediction)能够让多人游戏的客户端在拥有更少的延迟。客户端能够立刻改变自己维护的AS,然后通知服务端,由服务端判定这个更
* 改是否合法,如果不合法,则服务端拒绝更改AS并通知客户端回滚AS
*/
UCLASS()
class AURA_API URPGAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
URPGAttributeSet();
//复制变量时必须重写的函数,用于注册需要复制的变量
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
/**
* 创建AS属性步骤:
* 1. 声明FGameplayAttributeData类型变量
* 2. 用UPROPERTY()宏修饰
* 3. 如果是多人游戏,需要在宏内声明: ReplicatedUsing = OnRep_属性名,同时声明一个UFUNCTION()方法OnRep_属性名()。当服务端的该属性
* 值变化时,OnRep_属性名()将会被调用,我们在这个函数内处理变化事件
* 4. 实现OnRep_属性名()函数,在函数内调用GAMEPLAYATTRIBUTE_REPNOTIFY(URPGAttributeSet, 属性名, 旧属性值)宏,用来保存旧值用于
* 服务端通知客户端进行回滚
* 5. 重写GetLifetimeReplicatedProps()函数,在该函数内注册属性
* 6. 使用ATTRIBUTE_ACCESSORS()宏来初始化value_getter, property_getter, value_setter, initter
*/
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Health, Category="Vital Attribute")
FGameplayAttributeData Health;
ATTRIBUTE_ACCESSORS(URPGAttributeSet, Health);
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_MaxHealth, Category="Vital Attribute")
FGameplayAttributeData MaxHealth;
ATTRIBUTE_ACCESSORS(URPGAttributeSet, MaxHealth);
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Mana, Category="Vital Attribute")
FGameplayAttributeData Mana;
ATTRIBUTE_ACCESSORS(URPGAttributeSet, Mana);
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Mana, Category="Vital Attribute")
FGameplayAttributeData MaxMana;
ATTRIBUTE_ACCESSORS(URPGAttributeSet, MaxMana);
UFUNCTION()
void OnRep_Health(const FGameplayAttributeData& OldHealth) const;
UFUNCTION()
void OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth) const ;
UFUNCTION()
void OnRep_Mana(const FGameplayAttributeData& OldMana) const;
UFUNCTION()
void OnRep_MaxMana(const FGameplayAttributeData& OldMaxMana) const;
};
.cpp文件
函数实现
// Copyright KimiLiu
#include "AbilitySytstem/RPGAttributeSet.h"
#include "Net/UnrealNetwork.h"
URPGAttributeSet::URPGAttributeSet()
{
}
void URPGAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
//注册需要复制的属性Health,没有复制条件,不论复制的结果是否等于客户端原有结果,都进行复制调用
DOREPLIFETIME_CONDITION_NOTIFY(URPGAttributeSet, Health, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(URPGAttributeSet, MaxHealth, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(URPGAttributeSet, Mana, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(URPGAttributeSet, MaxMana, COND_None, REPNOTIFY_Always);
}
void URPGAttributeSet::OnRep_Health(const FGameplayAttributeData& OldHealth) const
{
//当Health属性被调用,此函数被调用,传入OldHealth作为旧值,该旧值将会被保存以免服务端通知客户端该属性需要回滚
GAMEPLAYATTRIBUTE_REPNOTIFY(URPGAttributeSet, Health, OldHealth);
}
void URPGAttributeSet::OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth) const
{
GAMEPLAYATTRIBUTE_REPNOTIFY(URPGAttributeSet, Health, OldMaxHealth);
}
void URPGAttributeSet::OnRep_Mana(const FGameplayAttributeData& OldMana) const
{
GAMEPLAYATTRIBUTE_REPNOTIFY(URPGAttributeSet, Mana, OldMana);
}
void URPGAttributeSet::OnRep_MaxMana(const FGameplayAttributeData& OldMaxMana) const
{
GAMEPLAYATTRIBUTE_REPNOTIFY(URPGAttributeSet, MaxMana, OldMaxMana);
}
RPGEffectActor
对AttributeSet内的属性值做出改变的物体的父类,有可能是各种药水,或是某个陷阱。
.h文件
声明一个静态网格体以及一个碰撞体
// Copyright KimiLiu
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "RPGEffectActor.generated.h"
class USphereComponent;
class UStaticMeshComponent;
UCLASS()
class AURA_API ARPGEffectActor : public AActor
{
GENERATED_BODY()
public:
ARPGEffectActor();
UFUNCTION()
virtual void OnOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
UFUNCTION()
virtual void EndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
protected:
virtual void BeginPlay() override;
private:
UPROPERTY(VisibleAnywhere)
TObjectPtr<USphereComponent> Sphere;
UPROPERTY(VisibleAnywhere)
TObjectPtr<UStaticMeshComponent> Mesh;
};
.cpp文件
// Copyright KimiLiu
#include "Actor/RPGEffectActor.h"
#include "AbilitySystemComponent.h"
#include "AbilitySystemInterface.h"
#include "AbilitySytstem/RPGAttributeSet.h"
#include "Components/SphereComponent.h"
// Sets default values
ARPGEffectActor::ARPGEffectActor()
{
PrimaryActorTick.bCanEverTick = false;
Mesh = CreateDefaultSubobject<UStaticMeshComponent>("Mesh");
SetRootComponent(Mesh);
Sphere = CreateDefaultSubobject<USphereComponent>("Sphere");
Sphere->SetupAttachment(GetRootComponent());
}
void ARPGEffectActor::OnOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
if (IAbilitySystemInterface* ASCInterface = Cast<IAbilitySystemInterface>(OtherActor))
{
//可以获取到指定对象的AttributeSet, 对于PlayerCharacter来说,在Possedby()函数内已经给PlayerCharacter的AttributeSet和
//AbilitySystemComponent赋值了,赋的值是PlayerState内的AttributeSet和AbilitySystemComponent
const URPGAttributeSet* RPGAttributeSet =Cast<URPGAttributeSet>(ASCInterface->GetAbilitySystemComponent()->GetAttributeSet(URPGAttributeSet::StaticClass()));
GEngine->AddOnScreenDebugMessage(1, 2.0f, FColor::Red, FString("Character On Overlapped"));
Destroy();
}
}
void ARPGEffectActor::EndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
}
void ARPGEffectActor::BeginPlay()
{
Super::BeginPlay();
Sphere->OnComponentBeginOverlap.AddDynamic(this, &ARPGEffectActor::OnOverlap);
Sphere->OnComponentEndOverlap.AddDynamic(this,&ARPGEffectActor::EndOverlap);
}