게임프로그래밍/실습1

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

우승자는메이 2024. 10. 29. 23:15

목차

  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();
	}
}

 

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