22년 10월 부터 23년 2월까지 진행하였고, 강형엽 교수님의 지도 하에 프로젝트를 진행했다. 해당 프로젝트의 목표는 이전까지 게임에 없는 기술 혹은 좀 더 좋은 방식을 타겟 논문을 설정하여 언리얼 엔진에 구현해 보는 것이었다.
게임에 존재하는 다양한 물체와 상호작용에 있어서 파괴할 수 있을 것 같지만 파괴되지 않거나, 어색한 모습으로 파괴되는 모습을 해결해보고 싶어서 Breaking Good: Fracture Modes for Realtime Destruction 논문 (https://github.com/sgsellan/fracture-modes)을 타겟 논문으로 결정하여 프로젝트를 진행하였다. 해당 논문은 mesh의 데이터를 가지고 진동, 탄성 모드를 통해 물체의 약한 부위를 찾아내어 해당 데이터를 반영한 새로운 mesh 데이터를 runtime이 아닌 시점 계산하여 가지고 있고, 이후 runtime에 impact가 들어오면 이전에 계산한 데이터를 기반으로 계산하기 때문에 빠른 시간에 실시간에 들어오는 충격에 의존적인 파괴 시뮬레이션이 가능하도록 하는 코드이다.
해당 논문의 내용을 언리얼로 구현하는 과정에서 어려움이 처음부터 존재했다. 해당 논문의 코드는 python으로 이루어져 있고, 여러 라이브러리들이 포함되어 있어서 해당 코드를 언리얼 엔진으로 옮기는 것에 어려움이 있었다. 처음에는 언리얼의 python 기능을 사용해 보기 위해 해당 기능을 찾아보고 공부하여, 해당 코드를 언리얼에서 실행하는 것 까지는 도달하였지만, 언리얼 내부 액터의 데이터를 python 코드와 연동하여 사용할 방식을 찾지 못했고, 프로젝트 진행의 어려움을 겪었다.
언리얼에서 python 코드를 실행시킨 모습
- 실제로 이 기능을 사용하지는 못했다.
교수님께서 해당 코드를 직접 구현해보는 것이 당연히 좋지만, 통신을 한 번 사용해보라는 피드백을 받고 tcp 통신 공부를 하여 프로젝트에 적용하고 나서 프로젝트 구현 진도가 나갔다. 처음에는 계산된 데이터를 단순히 python 으로부터 받아서 언리얼에서 보여주는 형식이었고, 이후에는 언리얼 엔진에서 데이터를 보내고 다시 계산된 데이터를 받아오는 형식으로 수정하면서 해결했다. 이 과정에서 tcp 통신으로 string 데이터를 주고 받는 방법을 사용했다. 이 string데이터를 사용하기 위해서, string을 다른 데이터 타입으로 바꾸는 코드를 많이 다뤄볼 수 있었고, 언리얼이 가진 여러 함수들을 사용하여 string 데이터 처리를 해볼 수 있었다.
tcp 통신 파이썬 코드 일부
- string을 특수 기호로 분리시켜서 언리얼로 보낸 후 언리얼에서 해당 기호를 기반으로 분리해서 vector와 int 배열을 만들었다.
언리얼 블루프린트 1
- 언리얼 에서 string 분리하는 블루프린트 일부
언리얼 블루프린트 2
- 언리얼 tcp 통신 블루프린트 일부 - 플러그인이 존재해서 쉽게 구현할 수 있었다.
프로젝트 진행하면서 생각나는 몇 가지 어려움이 있었다. procedural mesh 생성을 했는데, 물체가 투명하게 보이는 문제였다. 이 문제는 index를 통해 vertex로 면을 생성할 때의 순서 때문에 발생한 문제였다.
RHS vs LHS
- OpenGL은 RHS, DirectX 는 LHS를 사용한다.
mesh를 생성하는 순서를 index에 따라 설정하는데, 해당 순서를 오른손 법칙(RHS) 혹은 왼손 법칙(LHS)를 사용하여 해당 vertex로 이루어진 면의 앞을 정하게 된다. (엄지 손가락이 나오는 방향이 면의 앞) 앞서 말한 문제가 논문의 코드와 언리얼의 방식이 달라서 발생하는 문제였다. 이 문제는 array의 인덱스를 바꾸는 코드를 만들어서 해결했다.
해결 전 투명 mesh와 해결 후 texture 적용된 mesh
다음 문제로는 mesh가 부서진 후 위치에 관한 문제였다. 이 문제는 해당 mesh의 기반이 되는 mesh가 특정 위치에서 부서지기 이전 transform 을 저장하고 새로운 mesh 를 생성하면서 해당 transform을 적용하여 해결하였다.
해결하지 못한 문제는 runtime 성능에 관한 문제이다. 이전까지의 게임 내의 문제도 파괴 시뮬레이션을 runtime에 하면 성능이 나오지 않는 문제가 있어서 많이 사용되지 않았다. 그래서 이 논문으로 해당 문제를 해결하고 실시간에 시뮬레이션을 해보고 싶었으나, 데이터를 통신을 통해 주고받다 보니 이 부분에서 성능 저하가 심하게 나타났다. mesh의 vertex를 줄여서 시간을 조금씩 줄일수는 있었지만, 2~4초 정도의 딜레이 후에 파괴되는 모습이 나타나게 되는데 이 부분이 프로젝트 하면서 가장 아쉬웠던 부분이다.
언리얼이 아닌 다른 코드를 언리얼에 구현하기 위해 사용하는 방식 중 하나인 통신을 써볼 수 있었고, 언리얼 내부에 구현된 코드와 여러 함수를 찾아보고 사용하면서 나중에 게임을 만들 때 써보고 싶은 기능 (https://docs.unrealengine.com/4.26/en-US/BlueprintAPI/Components/ProceduralMesh/SliceProceduralMesh/)들도 많이 알게 되었다. 대단한 기술을 사용하고 구현한 것은 아니지만, 팀원들 없이 혼자 힘으로 프로젝트를 끝내서 개인적으로 보람찬 프로젝트였다.
아쉬운 점으로 직접 해당 코드를 이해하고 언리얼에 구현해 보고 싶었지만, tcp 통신을 사용했기 때문에 실제 동작 방식을 완전하게 이해하지 못한 점이고, 통신을 사용하지 않았다면 mesh 가 부서지는 과정에서 생기는 딜레이를 줄이거나 없애서 앞서 언급한 문제를 해결할 수 있을 것 같았는데, 해결하지 못한 것이 아쉬웠다.
앞으로 physical simulation 관련 논문과 프로젝트를 찾아보고 해당 프로젝트도 개선할 수 있다면 개선해보고 싶고, 다음 학기에 할 다른 프로젝트에서는 물리적인 부분을 이해하고 직접 구현해보고 싶다.