[UE5]튠 탱크-11

칼든개구리·2024년 12월 10일
0

[언리얼TO리얼]

목록 보기
20/42

이번 시간엔 마우스 커서가 어디로 움직이든 커서 위치에 따라 닿게 되는 오브젝트에 구가 나타나는 것을 만들어보겠다. 이렇게 만들려면 컨트롤러에 몇 가지 함수가 필요하다 이렇게 만들려면 컨트롤러에 몇 가지 함수가 필요하다. 컨트롤러 함수에 액세스 해야한다 !
컨트롤러가 필요한 이유는 커서 위치의 히트 결과를 받을 수 있는 컨트롤러 함수가 있기 때문이다.
프로젝트의 목표에서 커서를 움직일 때의 목표는 탱크의 포탑 부분, 메시의 가장 상부가 회전하여
커서 방향을 향하게 하는 것이다. 커서를 움직이면 컨트롤러의 함수로 커서 위치에 맞는 위치를 얻을 수 있다.
커서와 일치하는 히트 위치를 얻으려면 컨트롤러를 사용해야 한다.

컨트롤러란?
폰에는 컨트롤러가 존재하고 보이지 않는 오브젝트이다. 폰의 컨트롤러는 APlayerController 타입일 것이고, 게임이 시작될 때 컨트롤러가 폰에 빙의한다. 그래서 폰 탱크에 있는 카메라 시점으로 볼 수 있는 것이다. 이제 이 컨트롤러에 액세스 할 수 있다.
Tank 클래스는 GetController 라는 함수를 상속한다(APawn::GetController, Pawn클래스에서 상속됨). 이 컨트롤러를 받아서 변수에 저장을 해야된다. 그래야 커서 위치에서 히트 결과를 받을 대 필요한 함수에 액세스 할 수 있기 때문이다.

Tank클래스로 돌아가 BeginPlay에서 컨트롤러에 액세스해야 한다.

void ATank::BeginPlay()
{
	Super::BeginPlay();
}

super을 써줘야 beginplay함수의 모든 기능과 상위 클래스의 기능이 계속 호출될 수 있다.

APlayerController* PlayerControllerRef;

헤더파일에서 APlayerController 타입 변수를 만들고

void ATank::BeginPlay()
{
	Super::BeginPlay();
	PlayerControllerRef = GetController();
}

cpp파일에서 이렇게 만들어주는데, getcontroller을 보면 이 함수는 AController을 반환한다고 되어 있다. 허나 우리 변수는 AController가 아니라 APlayerController 타입이다. 지금 우리는 GetControlelr에서 AController 포인터 타입의 반환 값을 가져와서 APlayerController 포인터에 저장하려고 한다!
AController document를 보면 AController 아래에 AAIController와 APlayerController을 볼 수 있다. 즉, APlayerController가 AController의 하위 클래스라는 것이다
상위 타입의 오브젝트를 가져와 하위 타입의 포인터에 저장할 수 없다.

GetController은 AController의 주소를 반환한다. AController 포인터에 저장할 수는 있지만 APlayerController 포인터에는 저장할 수 없다.
하지만 사실 GetControlelr로 반환된 오브젝트가 APlayerController라는 것이다!
AController 포인터 형태의 주소가 있고, 여기에 APlayerController가 저장되지만 AController 형태로 있다면 필요한 함수에 액세스 할 수 없다. 왜냐면 함수가 APlayerController에 있기 때문이다.
함수는 GetHitResultUnderCursor인데, Acontroller 포인터 타입의 값이 있고, APlayerController 내에 있는 함수를 가져 오려고 한다면 실패하게 된다.
해결책은 바로 캐스트 이다
AController은 상위 클래스이고 APlayerController은 하위 클래스이다. 그리고APlayerConroller 포인터에는 AController가 저장될 수 없다. 다른 방법으로, AController 포인터에 APlayerController 오브젝트를 저장할 수 있다. GetController을 호출할 때 APlayerControlelr을 가리키는 AController 포인터를 반환하게 된다. 그러면 AController 포인터 타입의 값이 있을 경우 Cast 라는 특별한 함수를 이용해 포인터 타입을 APlayerController 포인터로 바꿀 수 있다. 오브젝트 자체가 캐스팅 하려는 타입에 해당한다면, 캐스팅은 한 포인터 타입을 다른 포인터 타입으로 바꿔줍니다.
유효하지 않은 타입으로 캐스팅하려고 하는 경우, 예를 들어 APlayerController오브젝트를 가리키는 AController 포인터로 ACharacter에 캐스팅 하려고 하면 Cast가 NULL을 반환하고 캐스팅에 실패한다
Cast<>() 함수는 이렇게 생겼고 이 탬플릿 함수는 선택한 타입에 맞춰지고, 이 함수에 전달할 타입은 캐스팅 할려는 타입이다. <>안에 캐스팅 할려는 타입을 넣고 () 안에 캐스팅 할려는 포인터를 넣는다

예) APlayerController와 AController 타입 포인터를 캐스팅하려고 한다면, Cast(AController*) -> APlayerController 포인터 타입이 반환된다
코드 상에서는 Cast(GetController())로 작성해야 한다.

요약하자면, GetController을 이용해 컨트롤러에 액세스 하였다. 또한 Cast 함수도 사용해 AConroller 포인터 타입에서 APlayerController 포인터 타입으로 캐스팅 하였다. 이제 APlayerController 클래스에 있는 필요한 함수 GetHitResultUnderCursor에 액세스할 수 있다.

profile
메타쏭이

0개의 댓글

Powered by GraphCDN, the GraphQL CDN