GAME DEV MASTERCLASS

Launching Grenades in Unreal Part 2: Attributes, Gameplay Effects, Replication

Another grenade-popping GAS tutorial

Intro

Attribute Set

#pragma once#include "CoreMinimal.h"
#include "AttributeSet.h"
#include "AbilitySystemComponent.h"
#include "CharacterBaseAttributeSet.generated.h"
// Macros from AttibuteSet.h to generate boilerplate code for getters and setters.
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \\
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \\
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \\
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \\
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
/**
*
*/
UCLASS()
class SIMPLEGAS_API UCharacterBaseAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public: UCharacterBaseAttributeSet(); UPROPERTY(BlueprintReadOnly, Category = "Health", ReplicatedUsing = OnRep_Health)
FGameplayAttributeData Health;
ATTRIBUTE_ACCESSORS(UCharacterBaseAttributeSet, Health)
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;protected: UFUNCTION()
virtual void OnRep_Health(const FGameplayAttributeData& OldHealth);
};
UCharacterBaseAttributeSet::UCharacterBaseAttributeSet() :
Health(100.0f)
{
}
void UCharacterBaseAttributeSet::OnRep_Health(const FGameplayAttributeData& OldHealth)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(UCharacterBaseAttributeSet, Health, OldHealth);
}
void UCharacterBaseAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME_CONDITION_NOTIFY(UCharacterBaseAttributeSet, Health, COND_None, REPNOTIFY_Always);
}

ASimpleGasCharacter class

#include <Runtime/Engine/Public/Net/UnrealNetwork.h>
/** Base Set Of Attributes */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Abilities, meta = (AllowPrivateAccess = "true"))
class UCharacterBaseAttributeSet* BaseAttributeSet;
protected:	virtual void OnHealthAttributeChanged(const FOnAttributeChangeData& Data);	void BeginPlay() override;void ASimpleGASCharacter::OnHealthAttributeChanged(const FOnAttributeChangeData& Data)
{
float Health = Data.NewValue;
UE_LOG(LogTemp, Warning, TEXT("Health: %f"), Health);
}
// Create a follow camera
FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation
FollowCamera->bUsePawnControlRotation = false; // Camera does not rotate relative to arm
AbilitySystemComponent = CreateDefaultSubobject<UAbilitySystemComponent>(TEXT("AbilitySystemComponent")); BaseAttributeSet = CreateDefaultSubobject<UCharacterBaseAttributeSet>(TEXT("AttributeSet"));
void ASimpleGASCharacter::BeginPlay()
{
Super::BeginPlay();
if (AbilitySystemComponent)
{
FGameplayAbilityActorInfo* actorInfo = new FGameplayAbilityActorInfo();
actorInfo->InitFromActor(this, this, AbilitySystemComponent);
AbilitySystemComponent->AbilityActorInfo = TSharedPtr<FGameplayAbilityActorInfo>(actorInfo);
for(const auto& StartupAbility : StartupAbilities)
{
if (StartupAbility && HasAuthority())
{
AbilitySystemComponent->GiveAbility(FGameplayAbilitySpec(StartupAbility.GetDefaultObject(), 1, 0));
AbilitySystemComponent->InitAbilityActorInfo(this, this);
}
}
AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(BaseAttributeSet->GetHealthAttribute()).AddUObject(this, &ASimpleGASCharacter::OnHealthAttributeChanged);
}
}

Death Ability

Gameplay Effects

GE_RestoreHealth class defaults

Grenade class

GE_GrenadeInstantDamage

Is it possible to pass attribute changes to a GE from the grenade object? Yes!

Networking 101

Conclusion

Useful Links

Technical Designer at Yager Interactive. Ex live-producer at Electronic Arts. I write about Unreal Engine development, game business, and technology.