[UE4] Load Mesh-2: Mesh 배치하기 (GEditor, GetActiveViewport, GetClient, FLevelEditorViewportClient, ProceduralMeshComponent, SpawnActorDeffered-FinishSpawning, OnConstuction)
🪧 Mesh 배치
이전시간에 바탕화면에 저장되어있는 Mesh 파일을 읽어서 정점 정보를 모두 가져오는것까지 완성하였다.
이제는 가져온 정점 정보로 Mesh 객체를 제작하여 뷰포트에 띄울 수 있도록 배치 기능을 구현하였다.
1️⃣ Mesh를 배치할 지점 구하기 - LineTrace
카메라가 바라보고있는 방향에 Mesh를 배치하기 위해, 카메라의 방향으로 LineTrace 충돌을 체크하였다.
GEditor 는 에디터의 전역 객체로, GetActiveViewport 함수로 뷰포트를 가져오고, 뷰포트의 GetClient 함수를 호출하면 뷰포트의 카메라를 가져올 수 있다.
이러한 카메라 객체를 FLevelEditorViewportClient 자료형의 객체로 저장하였다.
LineTrace의 시작 지점은 카메라의 위치이고, 끝 지점은 시작지점으로부터 (10000,0,0) 만큼 회전시킨 지점으로 설정하였다.
FLevelEditorViewportClient 클래스의 GetViewRotation 함수를 사용하면 언리얼 엔진에서 쿼터니언으로 표현되는 플레이어 또는 카메라의 현재 View 회전을 반환해준다.
이러한 View 회전 값의 RotateVector 함수를 사용하면 현재의 회전 값(GetViewRotation 결과값)을 기준으로 매개변수로 전달한 FVector 크기 만큼 회전시킬 수 있다.
이는 플레이어/카메라가 바라보는 방향을 계산하거나, 플레이어/카메라를 기준으로 게임세계에서 객체의 방향을 결정하는데 유용하게 사용할 수 있다.
즉, Mesh가 배치될 위치는 카메라의 방향으로부터 Pitch 방향으로 10000만큼 이동된 범위만큼이 된다.
Rotation(Pitch, Yaw, Roll)
GEditor의 GetEditorWorldContext.World() 함수를 사용하면 현재 보고있는 World 객체를 가져올 수 있다.
이렇게 가져온 World로 LineTrace를 수행하였다.
2️⃣ Mesh를 배치할 지점 구하기 - Transform 초기화
LineTrace로 Mesh가 배치될 지점을 HitResult로 구할 수 있으므로 Direction을 구하여 Location을 Transform에 저장시켜주었다.
location은 hitResult의 시작지점에서부터 '방향만큼' '충돌한 거리' - 'Mesh의 반지름'을 뺀 값을 곱하여 구했다.
Mesh의 Radius값을 빼어 Mesh가 땅에 박히지 않고 위로 잘 올라와 배치되도록 하였다.
Rotation은 Direction의 Yaw값만을 가져와 저장하였다.
이제 불러온 Mesh 정보를 입력시키고, 배치할 객체인 ACStaticMesh_Copied를 생성하여 SpawnActorDeferred 해주었다.
우선, ACStaticMesh_Copied를 만든 내용을 확인해보자
3️⃣ Mesh 객체로 사용될 StaticMesh_Copied 액터 클래스 생성
![]() |
![]() |
StaticMesh_Copied 클래스는 이전에 정점들로만 Mesh를 그렸던 예제와 똑같이 구현하면 된다.
핵심은 ProceduralMeshComponent를 이용하여 Mesh를 CreateMeshSection 함수로 생성하고, Mesh 그리기에 필요한 정보들을 TArray에 변수들(Positions, Indices, Normals, Uvs, Colors)로 저장해놓는 것이다.
💡 Mesh의 생성 타이밍
Mesh의 생성은 Runtime 상황에서 실행되는것이 아니기 때문에 어디에서 "데이터를 가져다가 Mesh를 만들어라-" 라는 명령어를 호출해주어야 하는지 고민해봐야 한다.
또한 Mesh를 생성할 때 필요한 정보들을 전부 전달받은 뒤에 생성해야지만 올바른 Mesh가 생성될 수 있을것이다.
우선 StaticMesh_Copied 객체는 ButtonCommand에서 SpawnActorDeffered 로 생성시키기 때문에, StaticMesh_Copied 클래스의 생성자에서는 Mesh를 만들면 안된다.
Deffered는 생성시키고, 배치된 이후에 수행되기 때문에 생성자에선 안된다.
액터의 수명주기를 잘 보면 SpawnActorDeffered를 시작한 후 FinishSpawningActor까지 마친 뒤, BeginPlay 전까지의 단계들이 있다.
이중에서 OnConstuction 주기나 OnActorSpawned 주기를 선택하여 Mesh를 생성하면 된다.
나는 OnConstuction 함수를 호출하여 해당 주기에서 Mesh를 생성하도록 구현하였다.
🚩팁 !
여기서 On 으로 시작된것이 함수이면 Override 하여 구현해야 하고, 변수라면 델리게이트처럼 연결해주며 사용해야 한다.
4️⃣ Mesh 객체(StaticMesh_Copied) 생성하기
이렇게 만들어진 StaticMesh_Copied 객체를 SpawnActorDeffered로 스폰시켜주었다.
매개변수 중 ESpawnActorCollisionHandlingMethod열거형의 AdjustIfPossibleButAlwaysSpawn 은 항상 스폰은 시키고, 가능하다면 조절하라는 명령어를 전달한다.
이후에는 불러왔던 정점 데이터를 actor에 전달해주었고, FinishSpawning 함수를 통해 Deffered의 마무리를 지으며, Mesh를 배치할 위치를 확정시켰다.
이후에 OnConstuction 액터주기가 실행되며, 정보를 모두 전달받은 Procedural Mesh 컴포넌트인 Mesh의 생성이 시작된다.
컴파일 후 프로그램을 실행시키면, 툴바의 Load Mesh 버튼을 눌렀을 때 불러올 Mesh 파일을 선택할 수 있고, 파일을 선택하면 카메라가 바라보는 방향에 Mesh가 StaticMesh_Copied 객체로 생성된다.