Recently I started working on a personal project to flesh out some ideas, but I have hit some issue with multiplayer replication.
I am using GAS (Gameplay Ability System), which is for the sake of multiple abilities across different players. Currently, I have a skill that requires clients to input their mouse location, basically left-clicking wherever it is and sending the coordinate to the server and only initiating the ability. Unfortunately, it does not work for the server. The coordinate doesn’t replicate to the server, not sure if I missed anything.
PC_GATA_MouseLocation.h
#pragma once
#include "CoreMinimal.h"
#include "Abilities/GameplayAbilityTargetActor.h"
#include "PC_GATA_MouseLocation.generated.h"
/** Target data with a the client mouse location */
USTRUCT(BlueprintType)
struct PROJECTCARRIAGE_API FGameplayAbilityTargetData_MouseLocation : public FGameplayAbilityTargetData
{
GENERATED_USTRUCT_BODY()
FGameplayAbilityTargetData_MouseLocation()
{ }
FGameplayAbilityTargetData_MouseLocation(FVector InMouseLocation, FVector InMouseDirection)
{
MouseLocation = InMouseLocation;
MouseDirection = InMouseDirection;
}
/** Client mouse location */
UPROPERTY()
FVector_NetQuantize MouseLocation;
/** Client mouse location direction */
UPROPERTY()
FVector_NetQuantize MouseDirection;
bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess);
virtual UScriptStruct* GetScriptStruct() const override
{
return FGameplayAbilityTargetData_MouseLocation::StaticStruct();
}
};
template<> struct TIsPODType<FGameplayAbilityTargetData_MouseLocation> { enum { Value = true }; };
template<>
struct TStructOpsTypeTraits<FGameplayAbilityTargetData_MouseLocation> : public TStructOpsTypeTraitsBase2<FGameplayAbilityTargetData_MouseLocation>
{
enum
{
WithNetSerializer = true // For now this is REQUIRED for FGameplayAbilityTargetDataHandle net serialization to work
};
};
UCLASS()
class PROJECTCARRIAGE_API APC_GATA_MouseLocation : public AGameplayAbilityTargetActor
{
GENERATED_BODY()
public:
APC_GATA_MouseLocation();
UPROPERTY(BlueprintReadOnly, Category = Targeting)
FVector_NetQuantize MouseLocation;
UPROPERTY(BlueprintReadOnly, Category = Targeting)
FVector_NetQuantize MouseDirection;
virtual void StartTargeting(UGameplayAbility* Ability) override;
virtual bool IsConfirmTargetingAllowed() { return true; };
virtual void ConfirmTargetingAndContinue() override;
};
PC_GATA_MouseLocation.cpp
#include "Game/Abilities/TargetData/PC_GATA_MouseLocation.h"
#include "Game/GAS/PC_GameplayAbility.h"
#include "Kismet/GameplayStatics.h"
#include "Player/PC_PlayerCharacter.h"
#include "Utils/PC_GameUtils.h"
bool FGameplayAbilityTargetData_MouseLocation::NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)
{
MouseLocation.NetSerialize(Ar, Map, bOutSuccess);
MouseDirection.NetSerialize(Ar, Map, bOutSuccess);
return bOutSuccess;
}
APC_GATA_MouseLocation::APC_GATA_MouseLocation()
{
PrimaryActorTick.bCanEverTick = true;
ShouldProduceTargetDataOnServer = true;
}
void APC_GATA_MouseLocation::StartTargeting(UGameplayAbility* InAbility)
{
Super::StartTargeting(InAbility);
APlayerController* PC = OwningAbility->GetActorInfo().PlayerController.Get();
check(PC);
FVector CurrentMouseLocation;
FVector CurrentMouseDirection;
UE_LOG(LogTemp, Warning, TEXT("PlayerController: %s"), *GetNameSafe(PC));
UE_LOG(LogTemp, Warning, TEXT("MouseLoc: %s"), *MouseLocation.ToString());
UE_LOG(LogTemp, Warning, TEXT("MouseDirection: %s"), *MouseDirection.ToString());
if (GetLocalRole() != ROLE_Authority || (MouseLocation.IsZero() && MouseDirection.IsZero()))
{
UPC_GameUtils::GetMouseWorldLocation(PC, MouseLocation, MouseDirection);
}
}
void APC_GATA_MouseLocation::ConfirmTargetingAndContinue()
{
check(ShouldProduceTargetData());
FGameplayAbilityTargetData_MouseLocation* MouseInfo = new FGameplayAbilityTargetData_MouseLocation(MouseLocation, MouseDirection);
FGameplayAbilityTargetDataHandle Handle;
Handle.Add(MouseInfo);
UE_LOG(LogTemp, Warning, TEXT("PostLoc"));
UE_LOG(LogTemp, Warning, TEXT("MouseLoc: %s"), *MouseLocation.ToString());
UE_LOG(LogTemp, Warning, TEXT("MouseDirection: %s"), *MouseDirection.ToString());
TargetDataReadyDelegate.Broadcast(Handle);
}
Of course, in server calling the ability works fine, but not for clients. Any ideas?