내일배움캠프 45일차 - 언리얼 C++: 장애물을 만들어 플랫포머 구현하기 3
움직이는 장애물을 무작위 배치하기
이전에 경로를 따라 움직이는 장애물, 회전하는 장애물을 만들어봤다. 이제 이것을 월드 상에 무작위로 배치하는 로직을 구현해보자.
플레이어가 움직일 수 있는 영역 내에 장애물을 배치하기 위해 적당한 플랫폼 영역을 배치해준다.
| 장애물 배치영역이 될 플랫폼 파티션(좌) 이들을 합친 맵 전체 영역(우) |
| 장애물 생성액터(ARoad) 빨간 영역이 장애물 생성 영역(UBoxComponent)이다. |
ARoad 액터에는 루트가 될 USceneComponent, 실체를 이루는 UStaticMeshComponent, 그리고 장애물 생성영역을 나타내는 UBoxComponent로 구성되어있다.
ARoad위에 월드 상 장애물을 생성하는 방법은 다음과 같다.
1) 스폰지점 FVector를 정의한다.
장애물 생성영역 UBoxComponent의 위치와 Extent를 설정하고 UKismetMathLibrary::RandomPointInBoundingBox()를 사용해 영역 내 스폰될 위치(FVector)을 지정한다. 또한 회전, 스케일링 등으로 실제 위치가 다를 수 있음을 고려해 UBoxComponent의 GetComponentTransform().TransformPosition()을 사용해 위치를 컴포넌트 기준으로 재계산해준다.
2) 스폰지점이 정의되면 그 지점이 정말로 생성하기 적합한지를 테스트한다.
장애물이 무작위로 스폰되다보면 스폰지점이 겹치는 부분도 있을 것이다. 겹치게 되면 시각적으로 부자연스러워지고 퀄리티가 떨어진다. 때문에 겹쳐지는 것을 막기 위해 장애물에 USphereComponennt 등으로 충돌검사를 할 필요가 있을 것이다.
2-1) 콜리전 생성
구 콜리전을 배치할 때 회전하는 장애물은 위치에 고정되어있기에 생성자단계에서 CreateDefaultSubObject로 만들면 그만이지만 움직이는 장애물은 이동경로도 무작위로 배치될 예정이기에 Spline이 배치된 이후의 런타임단계에 콜리전을 배치해야한다.
런타임단계에서 CreateDefaultSubObject를 사용하면 크래시가 발생한다. 때문에 생성자이후의 런타임 단계에서는 대신 NewObject나, AddComponentByClass를 사용한다.
(※ 본래 컴포넌트는 NewObject로 생성하는것을 권장하지는 않지만 이미 로직이 구성된 상태라 다음기회에 알맞게 사용하도록 한다)
그렇게 만든 구 콜리전을 각 Spline포인트에 배치하면 다음과 같은 모습을 띠게 된다.
| CreateDefaultSubObject로 만든 콜리전(좌, 생성자단계) NewObject혹은 AddComponentByClass로 각 포인트마다 배치한 콜리전(우, 런타임단계) |
2-2) 스폰 시 충돌검사
이제 스폰할때 생기는 콜리전이 이미 배치된 장애물의 콜리전과 충돌되는지 체크해야한다.
하지만 현 시점에서는 C++를 사용해 콜리전검사 혹은 트레이싱을 하는 법을 배우지 않았기 때문에, 수학적인 방식으로 접근하도록 한다. 각 콜리전들은 서로 구의 형태를 하고 있기 때문에 충돌을 직접 계산하는 방법은 어렵지 않다. 아래의 조건을 붙여 충돌여부를 검사한다.
| if(FVector::Distance(스폰지점, 다른 콜리전 중심) < 자신의 반지름 + 다른 콜리전 반지름)) |
위의 조건에 충족하면 충돌된 것으로 판정하고 다른 스폰지점을 찾고, 그렇지 않다면 배치하는 것을 원하는 장애물 개수만큼 배치될 때까지 반복하면 된다.
번외) PCG(Procedural Content Generation)
| ※PCG를 사용한 오브젝트 배치 |
※ 언리얼에는 이런 반복적인 검사를 통한 배치 외에도 자체적으로 알고리즘에 따른 빠른 무작위 배치를 지원해주는 PCG(Procedural Content Generation)라는 프레임워크 툴세트가 있다고 한다. 이 툴을 사용하면 자신이 지정한 규칙에 따라 영역 내 분포가 고르고 빠르게 많은 오브젝트를 배치할 수 있다고 한다.
장애물 생성 로직을 제대로 작성했다면 도로위에 장애물들이 올바르게 배치되는 것을 볼 수 있다.
| 배치 결과 |
플레이 영상
적당한 플레이어와 결승점을 추가해 플레이 가능한 환경을 만들어주도록 한다.
댓글
댓글 쓰기