[UE5] Trace & Attack

GamzaTori·2024년 10월 27일

UE5 C++

목록 보기
19/27

PlayerController에서 TargetActor 업데이트

// h
private:
void OnInputStarted();

// cpp
void AMyPlayerController::OnInputStarted()
{
	StopMovement();
	bMousePressed = true;
	TargetActor = HighlightActor;
}
  • 마우스로 대상을 클릭하면 Target Actor로 업데이트 해준다.

Target을 따라가서 공격하는 함수 추가

// h
private:
void ChaseTargetAndAttack();

protected:
UPROPERTY(BlueprintReadOnly)
TObjectPtr<class AMyPlayer> MyPlayer;	// 나의 캐릭터를 캐싱해서 들고있는다

// cpp

void AMyPlayerController::BeginPlay()
{
	Super::BeginPlay();
	MyPlayer = Cast<AMyPlayer>(GetCharacter());
}

void AMyPlayerController::ChaseTargetAndAttack()
{
	if (TargetActor == nullptr)
	{
		return;
	}

	FVector Direction = TargetActor->GetActorLocation() - MyPlayer->GetActorLocation();
	if (Direction.Length() < 250.f)
	{
    	// TODO 공격 구현
		GEngine->AddOnScreenDebugMessage(0, 1.f, FColor::Cyan, TEXT("Attack"));
	}
	else
	{
		FVector WorldDirection = Direction.GetSafeNormal();
		MyPlayer->AddMovementInput(WorldDirection, 1.0, false);
	}
}
  • 일정 범위안에 들어오면 공격하고 그렇지 않으면 대상에게 다가간다

공격 애니메이션 추가 및 예외처리

void AMyPlayerController::ChaseTargetAndAttack()
{
	if (TargetActor == nullptr)
	{
		return;
	}

	if (GetCreatureState() == ECreatureState::Skill)
	{
		return;			// 이미 공격중이라면 실행 x
	}

	FVector Direction = TargetActor->GetActorLocation() - R1Player->GetActorLocation();
	if (Direction.Length() < 250.f)
	{
		GEngine->AddOnScreenDebugMessage(0, 1.f, FColor::Cyan, TEXT("Attack"));

		if (AttackMontage)
		{
			if (bMousePressed)
			{
				//if (GetCharacter()->GetMesh()->GetAnimInstance()->Montage_IsPlaying(nullptr) == false)
				//TargetActor->OnDamaged(R1Player->FinalDamage, MyPlayer);

				// 공격하는 대상을 바라보도록 설정
				FRotator Rotator = UKismetMathLibrary::FindLookAtRotation(MyPlayer->GetActorLocation(), TargetActor->GetActorLocation());
				MyPlayer->SetActorRotation(Rotator);

				GetCharacter()->PlayAnimMontage(AttackMontage);
				SetCreatureState(ECreatureState::Skill);

				TargetActor = HighlightActor;
			}
			else
			{
				TargetActor = nullptr;
			}
		}
	}
	else
	{
		FVector WorldDirection = Direction.GetSafeNormal();
		MyPlayer->AddMovementInput(WorldDirection, 1.0, false);
	}
}
  • 임시로 Animation Montage는 블루프린트로 연결한다.
  • 이미 공격중인 상태에서는 움직이거나 추가로 공격을 할 수 없도록 추가한다.
UENUM(BlueprintType)
enum class ECreatureState : uint8
{
	None,
	Moving,
	Skill,
	Dead
};
  • 플레이어를 상태로 관리한다.

캐릭터에 데미지를 받는 OnDamaged와 죽었을 때 호출되는 OnDead 함수 추가

// h
pulbic:
	virtual void OnDamaged(int32 Damage, TObjectPtr<AMyCharacter> Attacker);
	virtual void OnDead(TObjectPtr<AMyCharacter> Attacker);
  • 플레이어나 몬스터가 오버라이딩해서 사용한다.
// cpp
void AMyCharacter::OnDamaged(int32 Damage, TObjectPtr<AMyCharacter> Attacker)
{
	Hp = FMath::Clamp(Hp - Damage, 0, MaxHp);
	if (Hp == 0)
	{
		OnDead(Attacker);
	}

	D(FString::Printf(TEXT("%d"), Hp));
}

void AMyCharacter::OnDead(TObjectPtr<AMyCharacter> Attacker)
{
	if (CreatureState == ECreatureState::Dead)
	{
		return;
	}

	CreatureState = ECreatureState::Dead;
}
  • Clamp는 특정 값이 최솟값, 최댓값 사이에 있도록 한다

디버그 메시지 간편하게 띄우기

// define.h
#define D(x) if(GEngine) { GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Cyan, x); }
  • 매크로로 만들어두면 편하다
profile
게임 개발 공부중입니다.

0개의 댓글