이번에는 블루프린트 말고 C++를 이용해서 구현해보자.
먼저 트레이싱을 수행할 컴포넌트를 생성해 보도록 한다.
트레이싱 및 그랩 기능을 갖고 있는 컴포넌트를 만들고, 이를 필요한 액터들에 부착하여 사용할 수 있다. 이러한 형태를 컴포지션 ('Composition') 이라고 한다.
다음에 따로 글로써 다루겠으나 간단히 설명하자면, 컴포지션은 상속 관계로는 표현하기 힘든 관계에서 '어떤 기능을 가지고 있느냐' 의 관점에서 구조를 설계할 수 있다.
'New C++ Class' 를 클릭해서
액터 컴포넌트를 선택한다.
그리고 이렇게 생성한 액터 컴포넌트를 Player 블루프린트에 부착한다.
이로써 Player 액터는 Grabber의 기능을 가지게 되었다.
그냥 모두 내부 변수로 때려박아도 되겠으나 확장성을 위해 트레이스 거리와 Grab Radius를 EditAnywhere
변수로 생성해서, 에디터에서 수정할 수 있도록 했다.
그리고 함수의 파라미터로 사용될 두 FVector 변수 Start, End를 생성했다.
매 틱마다 다음의 작업을 수행한다.
GetComponentLocation()
의 결과를 Start 벡터에 저장해서 시작점을 설정한다.GetForwardVector()
에다 MaxGrabDistance
을 곱한 값을 Start에 더한 값을 End에 저장한다.DrawDebugLine은 디버깅을 위한 직선을 그려주는 함수로, 트레이싱과 직접적 연관은 없다. 그러나 눈으로 보이는 편이 편리하기 때문에 사용해 주었다.
이 함수는 위 사진과 같이 월드 인스턴스와 Start, End, Color 파라미터를 필요로 한다. 그리고 FColor
클래스에는 편리하게 사용하도록 미리 만들어진 색깔들이 있고, 그 중에서 빨간색을 사용하도록 한다.
나머지 변수들은 선택사항인데, 중요하지 않으므로 넣지 않도록 한다.
GetWorld()
를 통해 얻은 월드 인스턴스에서 SweepSingleByChannel
함수를 호출한다. 이 함수는 반환값은 트레이싱 결과를 나타내 주는 불리언 값이지만, 첫 번째 인자로 받고 있는 FHitResult 변수를 참조자로 받음으로써 여기에다 결과값을 담아서 돌려준다.
FQuat 타입의 Rotation 파라미터를 넣어 주어야 하는데 별도의 회전이 없다는 뜻의 Identity
를 넣어 준다. 현재로선 크게 중요하지 않은 부분이다.
다음은 어떤 채널을 이용할 것인지를 지정해 주어야 한다. 이를 위해서 워크스페이스 폴더의 config
폴더 내의 defaultEngine.ini
파일을 열어 보자.
어지럽게 많은 데이터가 있으나 여기서 Ctrl+F로 채널명, 즉 'Grabber' 를 검색해 주면, 이런 행을 발견할 수 있다.
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel2,DefaultResponse=ECR_Ignore,bTraceType=True,bStaticObject=False,Name="Grabber")
여기서 Channel=
에 저장된 값인 ECC_GameTraceChannel2
이 바로 우리가 필요로 하는 채널명이다. 이 값을 사용해 주도록 한다.
마지막에는 어떤 형태로 트레이싱을 수행할 것인지에 대한 내용인데, 반지름이 GrabRadius
인 구 객체를 만들어서 넣어 준다. 이런 식으로 점 대 점으로 직선 구간을 살펴보는 것이 아니라 특정한 도형 모양으로 트레이싱을 수행하면 더 감지할 수 있는 부분이 두꺼워지게 되어, 주변 시야에서도 액터를 감지하도록 보정을 할 수 있다.
SweepSingleByChannel()
의 결과값이 true이면 무엇인가 감지되었다는 뜻이다. 결과로 받은 HitResult에서 GetActor()
-> GetActorNameOrLabel()
을 이용해서 액터의 이름을 출력할 수 있다.
로그를 확인해 보면 시선의 이동에 따라 두 가지 케이스 모두 잘 출력되고 있는 것을 확인할 수 있다.