카테고리:

Day 7 : SkillComponent and SkillData

2024.01.04 Thursday Scrum Log

  • MH, 작성자 → SkillComponent 및 SkillData 추가 작업

  • IS → 버그 난 코드 복구 및 여러 스킬 구현

  • SW → 기본 UI 게임모드에서 타이머 리플리케이션 정상 작동 확인

  • HJ → ItemComponent 및 Item 설계 & 구현 시작

Daily 작업 과정

SkillComponent

아직 상점 UI를 통해 TMap에 SkillData를 등록하는 부분을 구현하지 않아 임의로 클래스를 등록하여 파이어볼 시전을 구현 완료.

각 클라이언트 별 동일한 파이어볼 위치 스폰을 위해 SpawnLocation을 Replicate하여 스폰하려 했지만, Replication이 정상작동하지 않아 실패.

→ 다른 Replication 방법을 통해 해결 예정

스폰 지점을 Skill 시전 시 정하기 때문에 움직이며 시전하는 스킬은 이전의 위치에서 스폰되는 문제 발생

→ AnimNotify에서 스폰 지점을 정하고 스폰하도록 한다.

//SkillComponent.h
#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "SkillComponent.generated.h"


UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class PUSH_API USkillComponent : public UActorComponent
{
	GENERATED_BODY()

public:
	USkillComponent();

protected:
	virtual void BeginPlay() override;

public:
	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;

public:
	void UseSkill(char InChar);

	UFUNCTION(BlueprintCallable)
		void Execute();

public:
	TMap<char, class USkillData*> SkillMap;
	ACharacter* Owner;

public:
	UPROPERTY(EditAnywhere)
		TSubclassOf<USkillData> ss;

public:
	UPROPERTY(EditAnywhere)
		class USkillData* curSkillData;

	UPROPERTY(EditAnywhere, Replicated)
		FVector SpawnLocation;

	void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
};
//SkillComponent.cpp
#include "Components/SkillComponent.h"
#include "GameFramework/Character.h"
#include "Net/UnrealNetwork.h"
#include "Skill/SkillData.h"
#include "Skill/Skill.h"
#include "Skill/SkillDatas/SkillData_Projectile.h"
#include "Global.h"

USkillComponent::USkillComponent()
{
	PrimaryComponentTick.bCanEverTick = true;
}


void USkillComponent::BeginPlay()
{
	Super::BeginPlay();

	Owner = Cast<ACharacter>(GetOwner());

	if(ss != nullptr)
		curSkillData = NewObject<USkillData>(Owner, ss);
}

void USkillComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

}

void USkillComponent::UseSkill(char InChar)
{
	if (!SkillMap.Contains(InChar))
		return;

	// curSkillData = SkillMap[InChar];
	Execute();
}

void USkillComponent::Execute()
{
	curSkillData->Play(Owner);
}

void USkillComponent::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);

	DOREPLIFETIME(USkillComponent, SpawnLocation);
}

SkillData

상점에 등록할 이름과 Texture 변수 추가

#pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "SkillData.generated.h"

UCLASS(Blueprintable, BlueprintType)
class PUSH_API USkillData : public UObject
{
	GENERATED_BODY()

public:
	virtual void BeginPlay();

public:
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
		FString SkillName;

	UPROPERTY(EditAnywhere, BlueprintReadOnly)
		class UTexture2D* SkillTexture;

	UPROPERTY(EditAnywhere)
		class UAnimMontage* ActionMontage;

	UPROPERTY(EditAnywhere)
		float PlayRate = 1.0f;

	UPROPERTY(EditAnywhere)
		TSubclassOf<class ASkill> Skill;

	UPROPERTY(EditAnywhere)
		float RelativeDistance = 0;

public:
	UFUNCTION()
	virtual void Play(ACharacter* InOwner);

};

NF_SpawnSkill

처음 SpawnSkill을 통해 각 클라이언트에서 생성 시도 → SpawnLocation이 Replicate 되지 않아 맞지 않음

SpawnSkill을 서버에서만 실행 → 서버에서도 SpawnLocation이 Replicate 되지 않음

→ 추후 Spawn 위치 조정..

//NF_SpawnSkill.cpp
#include "Notifies/Notify/NF_SpawnSkill.h"
#include "Global.h"
#include "GameFramework/Character.h"
#include "Components/SkillComponent.h"
#include "Skill/Skill.h"
#include "Skill/SkillData.h"
#include "Skill/SkillDatas/SkillData_Projectile.h"

FString UNF_SpawnSkill::GetNotifyName_Implementation() const
{
	return "Spawn Skill";
}

void UNF_SpawnSkill::Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation)
{
	Super::Notify(MeshComp, Animation);

	ACharacter* Owner = Cast<ACharacter>(MeshComp->GetOwner());
	if (Owner == nullptr)
		return;

	USkillComponent* SkillComponent =  Helpers::GetComponent<USkillComponent>(Owner);

	if (SkillComponent == nullptr)
		return;

	FVector SpawnLocation, RelativeSpawnLocation;

	TSubclassOf<ASkill> SpawnSkill = SkillComponent->curSkillData->Skill;

	USkillData_Projectile* SkillData = Cast<USkillData_Projectile>(SkillComponent->curSkillData);

	RelativeSpawnLocation = SkillComponent->SpawnLocation - Owner->GetActorLocation();
	SpawnLocation = Owner->GetActorLocation() + RelativeSpawnLocation + Owner->GetActorForwardVector() * SkillComponent->curSkillData->RelativeDistance;

	FRotator SpawnRotation = Owner->GetActorForwardVector().Rotation();

	FActorSpawnParameters params;
	params.Owner = Owner;
	params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;

	Owner->GetWorld()->SpawnActor<ASkill>(SpawnSkill, SpawnLocation, SpawnRotation, params);

	//if(controller == Owner->GetWorld()->GetFirstPlayerController())
		//SkillComponent->SpawnCallOnServer_Implementation(controller, SpawnSkill, SpawnLocation, SpawnRotation);

  //SkillComponent->SpawnCallOnServer_Implementation(SpawnSkill, SpawnLocation, SpawnRotation);
}