Enemy AI가 Random 위치로 이동하며 순찰하는 기능을 구현했었는데, 이번에는 정해진 경로를 순찰하도록 구현해보았다.
🛣️ 경로 액터 만들기 : BP_PatrolPath
블루프린트 Actor 클래스(BP_PatrolPath)를 하나 생성하여, 컴포넌트로 Spline을 추가해주었다. Spline은 곡선을 의미하는데, 커브를 구현할 때 곡선을 꺾어 만드는것이 베지에 곡선(Bezier Curves)이었다. 또 그렇게 만들어진 경로를 실제로 렌더링해서 만들어 보여줄땐 캣멀롬 방식(Catmull-Romm)을 사용한다.
베지에 곡선과 캣멀롬 방식은 아래 게시글에 정리해두었다.
2023.02.22 - [Unreal4] - [UE4] 베지에 곡선(Bezier Curves), 에르밋/허밋 곡선(Hermite Curve), 캣멀롬 스플라인(Catmull-Rom Spline)
Construction Script는 액터가 생성될 때, 뷰포트에 배치될 때, 멤버변수가 하나라도 값이 변경될 때 호출된다. 해당 스크립트에서 현재 클래스 Name을 TextRender로 출력하고, Spline 컴포넌트 안에 Set Closed Loop 함수를 호출하였다.
Set Closed Loop 함수는 경로를 그린 후, Loop형태로 만들지 말지를 설정해주는 함수이다.
만들어진 액터를 뷰포트에 끌어다놓으면 위와 같이 Spline을 그릴 수 있는 스플라인 포인트가 나타나게 된다.
스플라인 포인트의 양 끝은 베지에 제어점이 존재한다.
스플라인 포인트를 복제하고 위치를 옮기며 경로를 만들 수 있고, 마지막 포인트까지 배치시킨 후, 변수로 만든 후 인스턴스 편집 가능으로 만들어둔 Loop 변수를 True로 변환하면 첫번째 포인트와 마지막 포인트가 연결되며 Loop 형태의 스플라인이 만들어진다.
🚩 PatrolComponent
만들어진 스플라인 포인트들로 Enemy가 이동하는 기능을 구현하기 위해 Patrol 컴포넌트를 생성하였다.
만들어두었던 Path 액터를 변수로 저장하여 Path 액터가 존재한다면, 해당하는 제어점(Index)의 Spline Point로 이동하는 Get Move To 함수를 작성하였다.
Get Location at Spline Point 함수를 통해 원하는 Path의 제어점 위치를 반환받을 수 있다. 이때 Coordinate Space를 Local로 설정하면 스플라인 포인트간의 상대간격이 나오므로 World로 설정한다.
원하는 제어점(Index)로 이동한 뒤, 계속해서 다음 제어점으로 이동하며 Enemy가 순찰하게 만들어야 하므로 다음 제어점을 구하는 Update Next Index 함수를 작성하였다.
Spline 컴포넌트에 있는 Get Number Of Spline Points 함수로 제어점의 총 개수를 가져와 저장하였다.
이후에는 역방향, 정방향을 구하는 Reverse Bool 변수와, 순환 여부를 판단하는 Loop Bool 변수에 따라 경우의 수를 나눠 다음 제어점을 구해야 한다.
위와 같은 제어점을 갖는 스플라인이 있을 때 정방향은 0->1->2->3->0 으로
역방향은 0->3->2->1->0 으로 이동한다.
루프가 아니라면 0->1->2->3->2->1->0 으로 왔다갔다하도록 구현하였다.
위 내용을 기반으로 Reverse가 False일 때 정방향으로 이동하는 소스코드를 작성하였다.
정방향은 현재 인덱스가 끝 인덱스보다 작을때 계속해서 ++ 증가하고, 끝 인덱스에 도달했을 때, Loop 라면 0으로, Loop 가 아니라면 끝 인덱스의 하나 이전 인덱스로 이동한 뒤, Reverse를 다시 역순으로 돌려 반대로 이동한다.
Reverse가 True라면 역방향이기 때문에 현재 인덱스가 0보다 크다면 계속 -- 감소시키고, 0과 같아진 경우 Loop 라면 끝 인덱스로 바로 이동하고, Loop 가 아니라면 인덱스 1로 이동하고 정방향으로 돌아가도록 Reverse를 반전시켜주었다.
🚩 Patrol Task : BTTask_Patrol
이동할 스플라인의 제어점 위치를 모두 구했으니, Enemy의 실제 위치를 움직이도록 실행하는 Task 클래스를 작성하였다.
이전에 Enemy가 랜덤 위치로 이동하며 순찰하던 Task를 수정하여, 두 가지 순찰 경우를 나누었다.
Patrol Component를 가지고 있고, 이동할 스플라인 제어점이 있다면 경로 순찰 방식을 수행하도록 한다.
반대로, Patrol Component를 가지고있지 않거나, 가지고 있지만 이동할 스플라인 제어점이 없다면 랜덤 위치 순찰 방식을 수행하도록 하였다.
Tick AI 이벤트도 위와 마찬가지로 두 가지 경우를 나누어 순찰을 수행한다. 랜덤 순찰이라면 랜덤으로 이동한 뒤, Finish Excute를 반환하고, 스플라인 순찰이라면 만들어두었던 Update Next Index 함수를 호출해 다음 제어점 정보를 얻은 후 Finish를 호출한다.