본문 바로가기

언리얼엔진/C++슈팅프로젝트제작

Kill Zone제작하기

총알과 적은 무한대로 직진하기 때문에 인스턴스들이 많아져서 게임성능이 저하됩니다.

따라서 적당한 위치에 보이지 않는 장벽을 만들어 충돌시 없애도록하는 Kill Zone을 만들어 보겠습니다.

타이머를 달아 일정시간 경과후 없애주는 방법도 가능합니다.

프로젝트 세팅의 Collision탭에서 Preset항목에  New버튼을 눌러 다음과 같이 프리셋을 추가합니다.

Bullet과 Enemy는 WorldStatic(KillZone)과는 Overlay로하고 Player는 Block으로 하겠습니다. 

KillZone은 별도의 채널을 만들지 않고 WorldStatic채널을 사용하겠습니다. 에너미 총알의 프리셋도 WorldStatic오브젝트에 대한 응답을 Overlap으로 변경합니다. 플레이어도 WorldStatic채널에 대한 응답을 Block으로 하겠습니다.

이러면 KillZone 채널이 WorldStatic이니까 플레이어가 KillZone과 Block 됩니다. 

PlayerPawn.cpp의 생성자의 아래부분에 Collision관련 코드를 넣는다.  Player로 프리셋을 만들었다면 더 간단하다.

	//오버랩이벤트를 켠다.
	boxComp->SetGenerateOverlapEvents(true);
	//충돌 응답을 Query And Physics로 설정한다.
	boxComp->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
	//Object Type을 1번 채널(Player)로 설정한다.
	boxComp->SetCollisionObjectType(ECC_GameTraceChannel1);  // 콜리전채널1 Player로 설정 전부 ignore됨
	boxComp->SetCollisionResponseToChannel(ECC_GameTraceChannel2, ECR_Overlap); // Enemy와 Overlay설정
	boxComp->SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Block); // WorldStatic인 KillZone과는 Block설정

콜리전 오브젝트 채널 순서대로 ECC_GameTraceChannel 1 2 3이 된다.

이제 킬존클래스파일을 만든어 봅니다.

KillZone이란 이름으로 C++액터클래스파일을 생성합니다.

KillZone.h 에 충돌에 필요한 UBoxComponent만 선언하고 만들어 주면됩니다.

public:
UPROPERTY(EditAnywhere)
class UBoxComponent* boxComp;

KillZone.cpp

#include "KillZone.h"
#include "Components/BoxComponent.h"
// Sets default values
AKillZone::AKillZone()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	boxComp = CreateDefaultSubobject<UBoxComponent>(TEXT("BoxCollision"));
	SetRootComponent(boxComp);
	boxComp->SetMobility(EComponentMobility::Static);
	boxComp->SetBoxExtent(FVector(50, 2000, 50));
	boxComp->SetCollisionProfileName(TEXT("KillZone"));
}

빌드후 C++ KillZone클래스를 이용해서 BP_KillZone이라는 블루프린트파일을 생성합니다.

방금만든 BP_KillZone을 위아래로 끌어다 놓습니다.

 

playerPawn.cpp에는  WorldStatic의 block처리는 하지 않아도 된다  언리얼엔진이 자동으로 처리해준다.

그런데 실행해보면 KillZone과 PlayerPawn이 블록이 안된다. 문제는 PlayerPawn을 이동을 하는게 아니라 순간적으로 위치를 바꾸기 때문에 블록처리를 위해서는 움직임이 일어나는 PlayerPawn.cpp의 Tick()함수내 SetActorLocation() 매개변수에 true를 추가하여 sweep를 활성화 해야한다.

void APlayerPawn::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	FVector dir = FVector(0, h,v);
	dir.Normalize();
	FVector newLocation = GetActorLocation() + dir * moveSpeed * DeltaTime;
	SetActorLocation(newLocation, true);
}

이렇게 해도 블록이 일어나지 않는다면.

KillZone의 x,y위치를 0으로 해서 액터간의 높이를 맞춰준다. 그리고 Bullet와 Enemy는 Collision Preset을 사용하지만 Player는 공부를 위해 Custom으로 설정하여서 블루프린트의 Collision세팅이 틀어져 있을수 있으니 마지막으로 다시 확인해본다. 다음부터는 그냥 프리셋으로 하자