1. 레벨디자인
레벨 디자인을 위주로 간단한 플랫포머 레벨을 만들어보려고 합니다.
먼저 디자인 초안입니다.

Excalidraw — Collaborative whiteboarding made easy
Excalidraw is a virtual collaborative whiteboard tool that lets you easily sketch diagrams that have a hand-drawn feel to them.
excalidraw.com
위 사이트를 이용해서 대강 그림을 그렸습니다.
사진과 크게 다르지 않게 만들겠습니다.
2. 사용될 주요 에셋들
에셋은 Online Learning Kit, Lower Sector Building Kit 두 가지를 사용했습니다.

MovingPlatform 입니다.
저번에 배운 InterpToMovemet를 사용해서 위 아래로 동작하는 플랫폼입니다.
혹은 원하는 움직임을 위해 직접 구현할 생각도 해두겠습니다.

PowerCart입니다.
블루프린트 클래스를 새로 만들어 주려합니다.
3. 디자인
맨위 디자인 설계처럼 맵을 만들어줍니다.
3-1. 콜리전을 이용한 함정발판

해당 부분에 콜리전을 지워서 그냥 지나가면 떨어지도록 설계합니다.
3-2. 오버랩을 이용한 이동 발판
발판을 하나 만들겁니다.

이런 이동 발판을 구현하려고 합니다.
발판위에 플레이어가 올라오면, boix collision과 반응해서 발판이 움직이게 됩니다.
기본 로직은 이렇습니다.
캐릭터가 box collision에 닿는다 > 발판이 움직인다 > 캐릭터가 box colision을 벗어나면 박스가 원래 위치로 돌아온다
이렇게 됩니다.
하나씩 구현해 보겠습니다.

액터 블루프린트 클래스 만들어서
스태틱메쉬, box collision 넣었습니다.
이 collision으로 캐릭터가 닿는다. 라는것을 반정 할 수 있습니다.

발판이 움직이는 것을 구현하겠습니다.
먼저 게임이 시작되면 오브젝트의 현재 위치를 StartLocation이라는 Vector 변수에 초기화 합니다.
Event Actor Begin Overlap을 통해서 BP_Character 액터가 들어오면 As BP Character 변수에 해당 액터를 담습니다.
Event Actor End Overlap을 통해서 BP_Character가 빠져나가면 As BP Character 변수를 비워놓습니다.

위 블루프린트를 기준으로
Event Tick당 As BP Character가 존재하는지를 확인하고, 존재한다면 Branch의 조건
현제 Actor의 위치와 StartLocation위치의 거리를 MoveDistance 값과 비교해서 True여야 Actor의 위치를 이동시킵니다.
MoveDistance 변수에는 Default 값으로 100을 주었습니다.
한 번 실행해 보겠습니다.


잘 움직입니다.
여기서 발판 이동 속도를 좀 더 높여주고, X축으로 움직이게 바꾸겠습니다.
Velocity의 값을 200, 0, 0
MoveDistance의 값을 600으로 높였습니다.

좋습니다. 잘 움직이네요
캐릭터가 box collision에 닿는다 > 발판이 움직인다 > 캐릭터가 box colision을 벗어나면 박스가 원래 위치로 돌아온다
위 로직중 2번째 까지 구현이 되었습니다. 나머지도 구현 해보겠습니다.
여기서 부터는 조건을 조금 더 생각해야 합니다.
캐릭터가 box colision을 벗어나면, 즉 Event Actor End Overlap을 통해서 BP_Character가 빠져나가면 작동을 해야하고
Moving Actor가 원래 위치로 돌아와야 합니다.
저는 좀 복잡하게 짯습니다.

최종 로직입니다.
새로운 bool값을 만들었습니다 SetActorState를 선언했습니다.

게임이 시작하면 처음 위치와 bool값을 true로 저장합니다.
Sequence 첫번째 노드는 현재위치와 Start Location을 비교합니다.
참일경우 SetActorState가 참인지를 확인합니다. (제거해도 상관 없습니다)
참일경우 Velocity를 음수로 바꾸고 SetActorState를 거짓으로 저장합니다.
두번째 노드는 SetActorState가 참인지 확인합니다. 거짓일 경우(Velocity가 바뀌었을 경우) 액터를 움직입니다.
마지막은 Set Actor Location을 수정했습니다.
단순하게 액터가 움직인 다음 SetActorState가 낫 연산을 하고, 현재위치와 Start Location을 비교한 연산과 <= 연산을 합니다.
True일경우 Velocity를 다시 양수로 바꾸고 SetActorState를 참으로 바꿔줍니다.
위 블루프린트로 정상 작동을 하지만 문제가 있습니다.

원래는 이 위치를 <= 연산이 아닌 == 연산을 하려 했습니다.
그래야 원래 위치에서 출발하고 원래 위치에서 멈추기 때문입니다.
좀 더 공부가 필요한 부분입니다.
3-3. 자동으로 이동하고 회전하는 발판

위 발판을 만들 예정입니다.

새로운 블루프린크 클래스 만들었습니다.

스태틱 메쉬 컴포넌트 추가하고 PowerCar 스태틱 메쉬 넣습니다.
자 이번 로직도 생각을 해보겠습니다.
이번에는 일정시간마다 - 자동반복, 앞으로 간 뒤 회전입니다.
그럼 일단 앞으로 가는 로직을 먼저 만들어야 합니다.
위에서 만든 MovingActor와 크게 다르지 않습니다.

그 다음은 일정 거리를 이동하고 회전입니다.
회전 로직을 먼저 구현하겠습니다.

간단하게 회전 로직이 구현되었습니다. 나머지 핀 하나는 Delta Seconds에서 가져왔습니다.
다음으로는 먼저 앞으로 움직이고, 즉 움직임이 끝나는게 먼저입니다.
중간부터 코드를 완전히 뒤엎었습니다.
제가 원하는건 액터가 완벽하게 동일한 반복 움직임을 해야합니다.
하지만 위와 같은 로직을 사용하면, printf string을 찍어봤을때, 정확하게 90도 회전, 정확하게 원하는 위치에서 반복이 안됩니다.
timeline을 이용해서 만들었습니다.

전체 블루프린트입니다.

게임이 시작하면,
액터의 처음 위치를 StartLocation에 저장, 원하는 위치만큼 y축값을 더해주고 End Location에 저장
그리고 타임라인으로 반복합니다.

플랫포머 게임에서 플레이어가 움직일 시간을 주기 위해서 액터가 좀 더 빠르게 움직이게 만들었습니다.
타임라인 시간동안 Update를 통해 액터의 위치를 이동합니다. Lerp(Vector)을 통해 선형보간으로 자연스러운 움직임을 구성했습니다.
위와같이 만들면, 원하는 위치까지 정확하게 이동합니다.
Location Finished 노드는 타임라인이 끝나면 실행됩니다.

노란불 켜져있는 노드는
Location Finished 노드에서 Sequence노드로 연결하고 첫번째 노드입니다. CarState라는 불변수의 값을 정합니다.
CarState는 3번째 Sequence가 실행되는 조건을 만들었습니다.

Sequence 2번째 3번째 노드입니다.
2번째 노드는 Rotation 정보를 변수에 저장합니다.
3번째 노드는 CarState의 값으로 True일때 Rotation 타임라인이 실행되고 False일 때,

위와같이 Location 타임라인으로 돌아와서 실행합니다.

나머지 Switch on ETimelineDirection은 타임라인이 지금 정방향으로 실행되고 있는지, 역방향으로 실행되고 있는지를 판별해서 실행합니다.
Forward는 정방향으로 실행, Backward는 역방향으로 실행입니다.

전체적인 노드의 흐름은
게임이 시작되면 > StartLocation, EndLocation 값을 저장 > Location Timeline 실행 > 액터 움직임 > Timeline 종료(Finished 실행) >
Sequence 0 >
현재 액터의 위치와 스타트 위치의 액터가 다름 CarState는 False(액터가 원래 위치와 다름) > CarState상태는 True >
Sequence 1 >
Start Rocation이 비었는지 확인(아직 미구현 상태라서 Location Timeline 실행되면 무조건 실행) True > StartRocation, EndRocation 저장 >
Sequence 2 >
CarState 값을 확인 (액터가 원래 위치에 돌아왔는지) True > Rotation Timeline 실행 > 액터가 회전함 > Timeline 종료(Finished 실행) > Switch on ETimelineDirection 실행 Forward >
Rotation Timeline 실행(Reverse from End, 쉽게 역방향으로 실행) > Timeline 종료(Finished 실행) > Switch on ETimelineDirection 실행 Backward >
Switch on ETimelineDirection 실행 Forward > Location Timeline 실행(Reverse from End, 쉽게 역방향으로 실행) > Timeline 종료(Finished 실행) >
Sequence 0 >
현재 액터의 위치와 스타트 위치의 액터가 같음 CarState는 True(액터가 원래 위치와 다름) > CarState상태는 False >
Sequence 1 >
Start Rocation이 비었는지 확인(아직 미구현 상태라서 Location Timeline 실행되면 무조건 실행) True > StartRocation, EndRocation 저장 >
Sequence 2 >
CarState 값을 확인 (액터가 원래 위치에 돌아왔는지) False > Location Timeline 실행(Play from start, 쉽게 정방향으로 실행) > 반복....
위와 같습니다.
3-4. 골인 지점

빈액터에 box collision 만 추가해서 만들었습니다.

간단하게 오버랩되면 Goal!!이라는 문구가 출력됩니다.
완성된 게임 시연