본문 바로가기

게임프로그래밍/실습1

[언리얼 실습] 30. 1회 공격 당 1히트만 하기


목차

  1. 공격 한번에 히트 한번

1. 공격 한번에 히트 한번

 

현재 히트 이벤트가 중복으로 발생한다. 공격을 했을때 한번 휘두르면 한번만 맞는게 대부분의 게임에서 정석일 것이다. 그렇기에 그것을 구현하려고 한다.

 

// 무기.cpp
void AWeapons::OnBoxOverlap(//생략
{
// 중략
    if (HitResult.GetActor())
    {
        IHitInterface* HitInterace = Cast<IHitInterface>(HitResult.GetActor());
        if (HitInterace)
        {
            HitInterace->GetHit(HitResult.ImpactPoint);
        }
    }
}

 

현재 무기 클래스의 오버랩 함수를 보면 hitresult에서 액터가 있으면 GetHit 함수를 호출하고 있다. 중복되서 히트하면 함수를 계속 호출하고 있는데 이 부분을 막아보자.

 

TArray<AActor*> ActorsToIgnore;

 

오버랩 함수에는 무시할 액터를 저장하는 배열이 있고 이를 이용할 것이다. 현재 지역변수로 설정되어 있는데 이렇게 되있으면 함수를 호출할때마다 초기화가 되있을테니 또 다른 무시할 액터 배열을 만들어서 이것을 사용할 것이다.

 

//무기.h

private:
	TArray<AActor*> IgnoreActors;

 

if (HitResult.GetActor())
{
	IHitInterface* HitInterace = Cast<IHitInterface>(HitResult.GetActor());
	if (HitInterace)
	{
		HitInterace->GetHit(HitResult.ImpactPoint);
	}
	IgnoreActors.AddUnique(HitResult.GetActor());
}

 

히트한 액터가 있으면 IgnoreActors 배열에 그 액터를 집어 넣어준다.

 

void AWeapons::OnBoxOverlap(// 매개변수 생략)
{
	const FVector Start = BoxTraceStart->GetComponentLocation();
	const FVector End = BoxTraceEnd->GetComponentLocation();

	TArray<AActor*> ActorsToIgnore;
	ActorsToIgnore.Add(this);

	for (AActor* Actor : IgnoreActors)
	{
		ActorsToIgnore.AddUnique(Actor);
	}
    
    FHitResult HitResult;
    
    //  생략
        
}

 

IgnoreActors는 물론 공격이 끝나면 초기화 시켜줘야 한다. 안 그러면 한번 때린 액터는 두번 다시 때리지 못할 것이다.

 

그리고 이건 콜리전을 비활성화 시키거나 비활성화 시킬때 하면 좋을 것으로 보인다.

 

캐릭터 cpp 파일로 들어가자. 그전에 IgnoreActors 를 캐릭터 클래스에서 쓰기 위해서 퍼블릭 섹션으로 옮겨놓았다.

 

void AKnight::SetWeaponCollisionEnabled(ECollisionEnabled::Type CollisionEnabled)
{
	if (EquippedWeapon && EquippedWeapon->GetWeaponBox())
	{
		EquippedWeapon->GetWeaponBox()->SetCollisionEnabled(CollisionEnabled);
		EquippedWeapon->IgnoreActors.Empty();
	}
}

 

이렇게 설정하면 처음 콜리전을 활성화 시키거나 콜리전 활성화가 끝날때 배열이 비게 된다. 이로써 한번의 공격당 한번의 히트만 가능하게 된다.