라인 트레이스

CJB_ny·2022년 12월 9일
0

UE4

목록 보기
2/20
post-thumbnail

라인 트레이스 👍👍👍👍👍

다른 게임 개발 에디터에서는 Raycast 라고함.

유니티할 때 해본 작업이다.

1. 배울 것들

  • 라인 트레이스 (싱글 및 멀티)

  • 스윕 트레이스 (Sweep Trace)

  • 트레이스 채널 (Trace Channel)

  • 트레이스 반응 (Trace Responess)


새 프로젝트는 Mechanics를 지원하기 위해 새로 프젝만들것이다.

2. Line Trace

게임 세계에서 ㄷ두 지점 사이에 어떤 물체가 있는지 알려달라고 게임에 요청하는 한가지 방법이다.

라인 트레이스의 공통적이고 중요한 기능은 "트레이스 채널"이다.

라인트레이스를 사용할 때 특정 물체만 확인하고 싶은 경우가 있을 텐데 이때 사용하는게 트레이스 채널임.
약간 필터같은거로 다 걸러낸다고 생각하면 될거같다.

  • Visibility

    보이는 물체를 확인하기 위해 라인트레이스를 사용할 경우 Visibility 트레이스 채널을 사용하면된다.
    플레이어 이동을 막기위한 투명벽 같은 경우에는 Visibility 트레이스와 충돌하지 않음.

  • Interaction

    상호작용할 수 있는 물체를 확인하기 위한 라인 트레이스

  • Pawn 트레이스

    게임 세계를 이동할 수 있는 폰을 확인하기 위해 라인트레이스를 시행하는 경우 Pawn 트레이스 채널과 충돌한다.

캐릭터 클래스

먼저 UE4로 프로젝트 만들어준다. 3인칭으로 만듦.(이름은 아무렇게 만듦)

메탈 기어 솔리드 같은 탑 다운 시점으로 볼 것이기 때문에 카메라 설정과 플레이어 이동 제어부터 해주도록 하자.

ADogeBallCharacter::ADogeBallCharacter()
{
	// Set size for collision capsule
	GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);

	// set our turn rates for input
	BaseTurnRate = 45.f;
	BaseLookUpRate = 45.f;

	// Don't rotate when the controller rotates. Let that just affect the camera.
	bUseControllerRotationPitch = false;
	bUseControllerRotationYaw = false;
	bUseControllerRotationRoll = false;

	// Configure character movement
	GetCharacterMovement()->bOrientRotationToMovement = true; // Character moves in the direction of input...	
	GetCharacterMovement()->RotationRate = FRotator(0.0f, 540.0f, 0.0f); // ...at this rotation rate
	GetCharacterMovement()->JumpZVelocity = 600.f;
	GetCharacterMovement()->AirControl = 0.2f;

	// Create a camera boom (pulls in towards the player if there is a collision)
	CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
	CameraBoom->SetupAttachment(RootComponent);
	CameraBoom->TargetArmLength = 900.0f; // The camera follows at this distance behind the character	
	
	// 플레이어의 이동 입력에 따라 카메라의 회전이 변경되지 않도록 false로 변경
	CameraBoom->bUsePawnControlRotation = false; // Rotate the arm based on the controller 

	// 카메라가 플레이어를 내려다 보도록 설정
	CameraBoom->SetRelativeRotation(FRotator(-70.f, 0.f, 0.f));

	// 카메라의 회전이 캐릭터의 회전에 따라 변경되지 않도록 false설정
	CameraBoom->bInheritPitch = false;
	CameraBoom->bInheritYaw = false;
	CameraBoom->bInheritRoll = false;

	// Create a follow camera
	FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
	FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation
	FollowCamera->bUsePawnControlRotation = false;
}

자기가 만든 클래스 생성자부분에 다 때려 박아 넣어 주도록 한다.

CameraBoom의 TargetArmLength는 카메라가 이거리만큼 떨여저서 플레이어 따라가는 거리이다. 300.f인데 -> 900.f로 변경해주도록 하자.

이후 bUsePawnControlRotation은 false로 해주도록 하자 (설명은 주석 참고)

이후 SetRelativeRotation의 FRotator 생성자의 파라미터 Pitch, Yaw, Roll 에 -70, 0, 0넣어준다.

이후

Player이동에 제약을 두기 위해서 이상태로 똑같이 만들어 주도록 하자 (jump기능 삭제함)

Enemy 클래스

GetWorld함수는 모든 액터에서 접근(읽기)가 가능하며 액터가 속한 World객체를 반환한다. 라인 트레이스를 실행하기 위해서는 World객체가 필요하다.

이렇게 클래스를 만들어준다.

EnemyCharacter에

해당함수 선언해주도록 하자.

라인 트레이싱을 구현할 때 필요한 헤더파일들을 미리 적어주도록 하자.

bool AEnemyCharacter::CanSeeActor(const AActor* TargetActor) const
{
	if (!TargetActor)
		return false;

	// 라인 트레이스의 결과를 저장한다.
	FHitResult hit;
	// 라인 트레이스에 Hit변수를 전달하면, 실행되는 라인 트레이스에서 변수에 관련 정보를 채워 넣어준다.

	// 라인 트레이스의 시작과 끝 위치
	FVector start = GetActorLocation();
	FVector end = TargetActor->GetActorLocation();

	// 시야 판단을 위해 비교할 트레이스 채널
	ECollisionChannel channel = ECollisionChannel::ECC_Visibility;
	// ECollisionChannel 열거형은 비교하는데 사용할 수 있는 모든 트레이스 채널을 나타낸다
    // 지금은 보이는 것을 트레이스 할 것이기 때문에 visibility사용


	// 적(나 자신 == EnemyCharacter)가 범위 안에 있을 경우 Visibility트레이스 채널과 충돌할 때 바로 멈추는 것 방지하기 위한 작업
	FCollisionQueryParams queryParams; // Trace에 옵션을 추가할 수 있음.

	// 이 라인트레이스를 실행하는 액터를 무시한다.
	queryParams.AddIgnoredActor(this);

	// 확인할 대상 액터를 무시할 액터 목록에 추가한다.
	queryParams.AddIgnoredActor(TargetActor);

	// 라인 트레이스 실행하기
	GetWorld()->LineTraceSingleByChannel(hit, start, end, channel, queryParams);

	// 라인 트레이스 시각화
    // 인자 더 넣어주면 모양, 굵기 등등 조절 가능함.
	DrawDebugLine(GetWorld(), start, end, FColor::Red);

	// 만약 충돌한 물체가 있다면 Player를 볼 수 없다는 뜻이다. p210참고
	return !hit.bBlockingHit;
}
void AEnemyCharacter::LookAtActor(AActor* TargetActor)
{
	if (!TargetActor)
		return;

	if (CanSeeActor(TargetActor))
	{
		FVector start = GetActorLocation();
		FVector end = TargetActor->GetActorLocation();
		
		// 시작 지점에서 끝 지점을 바라보는 데 필요한 회전 계산하기
		FRotator lookAtRotation = UKismetMathLibrary::FindLookAtRotation(start, end);

		// 적 캐릭터의 회전을 앞서 구한 회전값으로 설정한다.
		SetActorRotation(lookAtRotation);
	}
}

Tick함수 구현

// Called every frame
void AEnemyCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	// 현재 플레이어가 제어하는 캐릭터 구하기
	ACharacter* playerCharacter = UGameplayStatics::GetPlayerCharacter(this, 0);
	// 해당 함수는 World Constant Object, Player Index를 받는다.
	// World Constant Object : 한 객체는 현재 World에 속하며 함수가 어떤 월드 객체에 접근해야하는지 알려주기 위해 사용한다.
	// Player Index : 싱글 게임일 경우 0(첫번째 플레이어)로 사용가능함.

	LookAtActor(playerCharacter);
}

라인 트레이스 결과

굿굿.

3. Sweep Trace ❗

라인 트레이스의 변형인 Sweep Trace

라인트레이스는 기본적으로 두 지점 사이에서 광선을 발사하는 반면,

스윕 트레이스는 두 지점 사이에서 직선으로 물체를 던지는 동작을 "시뮬레이션"한다.

던져지는 물체는 시뮬레이션되며(게임에서는 존재하지 않는다) 다양한 모양을 가질 수 있다.

스윕 트레이스에서 충돌 위치는 시작 지점에서 끝 지점으로 던져진 가상의 물체가 다른 물체와 부딪힌 첫번째 지점을 나타낸다.(모형은 박스, 구체, 캡슐중에 선택가능)

첫번째 큰 사각형은 트레이스 채널 속성으로 인해 무시 된다고 가정을 하자

스윕 트레이스는 특정상황에서 라인트레이스보다 유용함.

오브젝틑 클릭후 -> Collision -> 디테일 -> defualt => custom

custom 으로하면 이 물체가 라인 트레이스와객체 충돌에 반응하는 방식을 지정할 수 있음.

트레이스 반응에 Visibility가 Block이라 트레이스 채널을 막아서 적이 볼 수 없었는데

해당부분을 ignore 또는 곂칩으로 하면

이렇게 막혀 있어도 볼 수 있다.

그러면 곂침과 무시의 차이점은?? => "멀티 라인 트레이스"를 알아야 이해할 수 있다.

멀티 라인 트레이스

CanSeeActor함수에서 LineTraceSingleByChannel() 함수를 실핼해서 라인트레이스를 볼 수 있었는데

LineTraceMultiByChannel() 함수도 있다.

싱글 라인 트레이스는 어떤 물체에 부딪힌 후에는 충돌 검사를 중지. 부딪힌 물체와 충돌했다는 정보를 알려줌.

멀티라인 트레이스는 동일한 라인 트레이스와 충돌한 모든 물체에 대한 정보를 확인할 수 있다.

싱글 라인 트레이스는 사용중인 트레이스 채널에 대한 응답이 무시 또는 곂침으로 설정된 물체를 무시한다.
반응이 Block으로 된 물체를 찾으면 충돌 감지를 중단한다.

멀티 라인 트레이스는 겹침으로 설정된 물체를 무시하는 대신, 이 물체를 라인 트레이스로 충돌을 검사하는 중에 발견한 물체로 추가하고 원하는 트레이스 채널을 막는 Block물체를 찾으면 충돌 검사를 중단한다.

스나이퍼 존나 강력한 총알같은 경우 다뚫고 날아가는 부분 구현할 때 좋을듯?

커스텀 EnemySight 트레이스 채널 만들기

원하는 트레이스 채널을 직접만들 경우.

UE4에서는 기본 트레이스 채널 Visibility, Camera가 기본으로 제공됨.

프로젝트셋팅 -> Collision -> 새 트레이스 채널

만들고나면

DefualtEngine.ini => 내가 추가한 트레이스 채널이 있다.

이후 적이 사용할 트레이스 채널을 바꿔 주도록 하자.

=>

라인 트레이스 시작 위치 변경하기

지금은 엉덩이에서 라인 트레이스 발사함.

현재 EnemyCharacter.h에서

protected:
	// 라인 트레이스 시작 위치 변경
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = LookAt, meta = (AllowPrivateAccess = "true"));
	USceneComponent* SightSource;

이렇게 적어준다. 지금 UPROPERTY함수가 Enemycharacter객체한테 컴포넌트 붙여주는 함수인거같다.
UPROPERTY함수에 들어갈 수 있는 인자는

https://docs.unrealengine.com/5.1/ko/unreal-engine-uproperty-specifiers/

언리얼 공식 문서를 참고바란다.

그리고나서 .cpp파일에서 생성자 부분에서

AEnemyCharacter::AEnemyCharacter()
{
	PrimaryActorTick.bCanEverTick = true;

	SightSource = CreateDefaultSubobject<USceneComponent>(TEXT("Sight Source"));
	SightSource->SetupAttachment(RootComponent);
}

이후 프로젝트에서 컴파일 후 결과를 확인을 하면은

이렇게 붙어있음. Transform위치를 조절해주면 결과는

결과는 아래와 같음.

profile
공부 일기장으로 변해버린 블로그 (https://cjbworld.tistory.com/ <- 이사중)

0개의 댓글