언리얼엔진 학습 및 과제

[내일배움캠프] 상호작용 추가하기

park94128 2025. 8. 8. 22:08

어제 간단한 점프맵을 만들었다. 그런데 이것만으로는 심심하니까 기능을 추가해보자
어제 사용한 프로젝트를 다시 열어서 계속 진행한다.

 

1. 밀 수 있는 액터

플레이어가 밀 수 있는 액터를 만들어보자. 이 액터를 만들려면 우선 스태틱 메시 액터를 만들어야 한다.

위쪽의 일반에서 찾지 말고 아래쪽에서 검색하여 찾는다

 

스태틱 메시 액터를 만들었으니 당연히 사용할 스태틱 메시를 지정해야 한다. 때마침 Online Learning Kit에 적절한 스태틱 메시가 있으니 사용해보자

메시 이름은 'SM_Create'

 

그리고 이 액터는 가만히 있는 액터가 아니기 때문에 디테일의 트랜스폼에서 모빌리티를 '무버블'로 지정해야 한다.

 

 

여기부터 중요하다. 플레이어에게 밀리기 위해선 그러기 위한 물리 작용이 필요하다. 스태틱 메시 엑터의 디테일에서 '피직스'를 찾아보자. 그러면 '피직스 시뮬레이트'가 false인 것을 발견할 수 있는데 이를 true로 바꾼다. 질량은 100kg가 적당한 것 같다. 너무 가벼우면 밀리다 못해 그냥 날아가버리고 너무 무거우면 밀리지 않는다. 그 외 나머지는 기본값 그대로 놔두자

 

조금만 아래로 내리면 '콜리전'이 있는데, 여기서 '콜리전 프리셋'을 'PhysicsActor'로 지정해주자. 그리고 '캐릭터가 밟고 올라갈 수 있는지 여부'를 No로 지정하면 의도치 않게 밟고 올라타는 현상을 방지할 수 있다.

 

 

 

그럼 이제 가는 길목에다가 대충 몇 개 놔둬보자. 놓기에 따라 도움이 될 수도 있고 장애물이 될 수도 있다.

일단 이건 100% 장애물이다

 

추가로, 이 액터가 만약 지형 아래로 떨어진다면 더이상 쓸모가 없으니 제거해주자. 어제 캐릭터에게 일정 높이 아래로 떨어지면 처음 위치로 되돌아가는 기능을 만들었는데 이 기능을 가져와서 적용하되 일정 높이 아래로 떨어지면 스스로 제거되도록 바꾸면 된다.

 

2. 지정한 시간에 따라 움직이는 액터

지정된 시간에 따라서 움직이는 기능을 만들려면 어떻게 해야 할까? 매 프레임마다 호출되는 Tick에서 구현을 할 수도 있겠지만 이것보다 더 좋은 방법이 있다. 바로 타임라인(Timeline)이라는 기능이다.

블루프린트의 이벤트그래프에서 Add Timeline을 누르면 타임라인 노드가 생성된다. 이 타임라인을 더블 클릭하면 타임라인 에디터 화면이 열린다.

무엇을 하는 기능일까

타임라인 에디터 화면의 좌측 상단에 '+ 트랙'을 누르면 트랙을 추가하는 메뉴가 나오는데, 여기서 'Float 트랙 추가'를 눌러보자

 

그러면 뭔가 하얀 화면이 나오면서 그래프를 그릴 수 있게 된다. 여기서 마우스 오른쪽 버튼을 눌러 키를 추가하는 것으로 내용을 설정할 수 있다. 좀 만져보면 알겠지만 이 그래프는 지정한 시간에 따라 지정된 키에 따른 값을 출력한다. 위 스크린 샷의 내용을 해석하면 다음과 같다.

- 0초 부터 2초 까지는 0을 유지한다.

- 2초 부터 값이 일정하게 증가하며 4초일 때 2700이 된다.

- 4초부터 6초 까지 2700을 유지한다.

- 6초부터 값이 일정하게 감소하며 8초일 때 0이 된다.

- 그래프 위에 눌러진 버튼은 '루프'인데, 위 내용을 1번만 하지 않고 계속 반복한다.

 

 

슬슬 눈치챘을진 모르겠는데, 총 8초에 걸처 2700 거리를 계속 왕복하는 기능을 만들 것이다. 어디에 그런걸 만들것이냐면...

왼쪽 : 수정 전, 오른쪽 : 수정 후

바로 여기다. 여기서 가운데 바위를 움직이게 할 것이다. 그런데 앞뒤 지형의 간격이 너무 가깝기 때문에 좀 멀리 옮겨야 한다.

그리고 움직일 예정인 지형도 트랜스폼의 모빌리티를 무버블로 바꾼다. 앞으로 움직임이 있는 모든 것은 무버블로 변경해주자.

 

자, 타임라인도 만들었고 움직일 액터도 골랐다면 블루프린트를 완성하자. 블루프린트 편집 화면으로 가보자

이 블루프린트가 사용할 변수를 2개 추가한다. 움직일 액터를 할당할 액터 변수와 그 액터의 처음 위치를 저장할 벡터 변수가 필요하다. 액터 변수는 public으로 만든다.

BeginPlay에서 액터의 처음 위치를 저장하게 만든다.

 

그리고 Play나 Play from Start에 연결하여 타임라인을 실행한다. 어차피 게임 시작시 동작할 것이니 어디를 연결하든 상관없다. 둘의 차이는 타임라인 실행 도중 중단하고 다시 시작할 때 생기는데, Play는 중단한 시점에서 계속 진행하는데 Play from Start는 무조건 처음에서 시작한다.

타임라인의 값을 받아서 액터를 이동시켜야 하는데, 시간에 따라 실시간으로 값을 받아야 하니 Update에서 이어야 한다. 여기서는 받은 값을 처음 위치값에 더하는 방식으로 액터의 위치가 결정되는 방식으로 구현했다.

참고로 타임라인에서 트랙을 추가하고 그 이름을 바꾸지 않았다면 그냥 '새 트랙 0'일테니 핀의 이름도 이를 따른다.

이 액터는 눈에 보이지 않는다. 그냥 움직일 액터와 겹쳐놨을 뿐이다.

블루프린트를 컴파일하고 저장했으면 맵에 배치한다. 그리고 배치된 액터의 디테일 화면에서 아까 public으로 만든 변수를 찾을 수 있는데 이 변수에 움직일 액터를 할당하자. 변수를 찾기 힘들다면 검색 기능을 이용하면 된다.

 

3. 플레이어를 감지할 때만 움직이는 액터

어제 사용한 메시 중 하나 마음에 안드는 것이 있는데, 이 지형에서 움직이는 도중 계속 결러서 못움직이는 현상이 자주 발생했다. 그리서 이 부분을 삭제하고 움직이는 지형을 만들고자 한다.

- Object Type

일단 작업을 하기 전 해야 할 일이 있다. 프로젝트 세팅을 연다.

왼쪽 목록중 콜리전을 찾아서 콜리전 설정을 연다. 그러면 다양한 콜리전 설정이 보이는데, 앞서 밀 수 있는 액터에서 언급한 PhysicsActor 프리셋도 여기에 있다.

 

여기서 해야 할 일은 Object Channels에서 '새 오브젝트 채널'을 눌러 오브젝트 채널을 하나 만든다. 나는 'Robot'이라는 이름으로 만들었다. 기본 반응은 블록으로 하자.

 

그 다음 아래의 '새 프로파일'을 눌러 프로파일을 만들자. 미리 만들어진 프리셋 중 'Pawn'이라는 것이 있는데 이 내용을 그대로 베껴 설정하자. 다만 이름은 만들었던 오브젝트 채널과 똑같이 만들자

미리 만들어진 프리셋을 전부 확인해보자. 아마 Pawn과 다른 것이 있을 것이다.

그리고 오브젝트 채널 생성시 기본을 블록으로 했기 때문에 모든 프리셋에서 자동으로 블록으로 지정됐을 것이다. 하지만 Pawn 프리셋을 따라갈 것이니 모든 반응을 Pawn과 동일하게 맞추자. 위 스크린샷은 Trigger 프리셋의 내용인데 Pawn은 오버랩이지만 우리가 만든 것은 블록으로 되어 있을테니 Pawn처럼 오버랩으로 바꾸자. 나머지 프리셋도 확인하여 Pawn과 동일하게 바꾸자

 

다했다면 어제 만든 캐릭터 블루프린트에서 캡슐 컴포넌트를 설정해야 한다. 캡슐 컴포넌트의 디테일에서 콜리전을 찾은 후 콜리전 프리셋을 우리가 만든 것으로 지정한다.

 

- 움직일 액터의 구조

이번에 만들 액터는 움직일 지형을 변수로 가져오지 않고 내부 컴포넌트로 만들 것이다. 그리고 원형으로 움직일 지형으로 만들건데, 그러기 위해 축 역할을 하는 씬 컴포넌트를 만들고 그 하위 컴포넌트로 스태틱 메시 컴포넌트를 만들었다. 축과의 거리는 2000으로 지정했다.

여기서 지형을 밟은 플레이어를 인식하게 만들 것이므로 스태틱 메시의 하위 컴포넌트로 박스 콜라이더 컴포넌트를 만들었다.

 

박스 콜라이더는 밟거나 막는 용도가 아니라 감지 역할을 해야 한다. 따라서 콜라이더의 디테일에서 콜리전 프리셋을 'Trigger'로 지정해야 한다.

이미 추가하고 찍은 스크린샷이라 둘만 다른 아이콘이다.

콜라이더의 디테일에서 이벤트를 찾고 '컴포넌트 오버랩 시작시'와 '컴포넌트 오버랩 종료시'를 추가한다. 그러면 이벤트그래프에서 새로운 이벤트가 추가된다.

 

- 타임라인 만들기

이번에는 다음과 같은 내용으로 만든다.

- 플레이어를 감지한 직후 1초 뒤에 180도 회전한다.

- 180도 회전은 5초에 걸쳐 진행한다.

- 180도 회전후 1초 여유시간을 추가한다.

 

왜 밟은뒤 1초의 시간이 있냐면... 사실 직접 테스트해보니 플레이어가 밟기도 전에 움직여서 못밟는 문제를 발견했기 때문이다.

그리고 마지막 1초의 여유가 있는 이유는 이번에는 Reverse라는 것을 사용할 것이기 때문이다. Play가 앞에서 뒤로 재생한다면 Reverse는 뒤에서 앞으로 재생하는 기능이다. 즉, 역재생이다.

 

- 이벤트그래프 디자인

아까 앞에서 콜라이더를 통해 이벤트를 2개 추가했다. 이 이벤트는 핀이 좀 많은데, 여기서는 두 이벤트 모두 실행 핀과 Other Comp핀만 필요하다. 두 이벤트에 대하여 동일하게 아래의 내용대로 만들자

- 실행 핀은 'Switch on ECollisionChannel'에 연결한다.

- Other Comp 핀은 'Get Collision Object Type'노드를 연결하고 그 반환 값을 'Switch on ECollisionChannel'의 검사 값으로 지정한다.

Switch 노드가 2개

각 Switch on ECollisionChannel노드는 아까 우리가 추가했던 오브젝트 채널 이름의 핀이 있다. (나는 'Robot'으로 이름지었다.) 여기서 타임라인 노드에 연결해야 한다. OnComponentBeginOverlap에서 출발한 것은 Play에, OnComponentEndOverlap에서 출발한 것은 Reverse에 연결한다.

Rotaion 핀을 오른쪽 클릭하여 3개의 핀으로 분리할 수 있다.

그리고 Set Relative Rotation에서 타임라인의 반환 값을 사용한다. Z(Yaw)를 돌려야 수평 회전을 한다. 회전할 대상은 당연히 축 역할을 하는 컴포넌트다.

그리고 맵에 배치한다. 플레이어가 저 땅을 밟으면 반대편 땅으로 이동할 것이다.

 

4. 플레이어를 감지하는 또 다른 방법

전에는 여기가 FINISH였다.

맵을 변경하면서 맵을 더 길게 만드려고 한다. 그래서 도착 지점에 위프 기능을 하는 액터를 배치하여 다른 곳으로 이동하게 만들었다.

나머지는 지금까지 설명한 내용을 응용하여 만들 수 있다. 하지만 딱 하나 설명하지 않은 내용이 있는데, 플레이어를 감지하는 방법이 다르다. 보통 같은 기능에 대해서는 같은 매커니즘을 쓰는 것이 맞지만, 지금은 배우는 단계이므로 다른 방식을 사용했다.

 

내가 만든 플레이어 블루프린트의 이름은 MyCharacter이니 Cast to MyCharacter 노드가 존재한다.

언리얼 엔진의 모든 오브젝트는 액터다. C++ 코드로 만든 것도 블루프린트로 만든 것도 모두 액터다. 하지만 그것이 내가 만든 액터인지는 그냥 확인할 수 없다. 다 똑같은 액터니까.

그럴때 필요한 방법 중 하나는 변환(캐스팅)을 시도하는 것이다. 당연히 전혀 다른 종류라면 변환에 실패할 것이다. 이 노드는 변환 성공시와 실패시 각각 분기점이 존재하는데 이를 이용하여 플레이어 여부를 판단할 수 있다. (변환에 성공한 경우 변환한 액터를 사용할 수 있다.)

 

5. 유도리 있는 타임라인

이번에는 플레이어를 감지하면 넘어지는 기둥이 넘어지도록 구현했다. 다만 물리작용을 사용하기엔 의도하지 않은 상황이 발생할 것 같으니 그냥 타임라인을 가지고 넘어지는 것 처럼 연출했다.

 

시작후 4초에 걸쳐 -90이 되고, 그 뒤 5초에 -60이 될 때까지 증가하다가 다시 6초에 -90이 된다.

그런데 기둥이 넘어질때 어떻게 넘어지던가? 처음엔 천천히 기울어지다가 점점 빨라지지 않던가? 그럼 위 타임라인은 틀렸다. 하지만 타임라인은 직전 뿐만이 아니라 곡선을 그릴 수 있다.

 

타임라인 그래프의 키를 눌러보면 핸들 같은 것이 보이는데, 이것의 끝부분을 움직여보면 그래프 선도 그에 맞춰 휘어진다.

 

그리고 키에다 오른쪽 클릭을 하면 여러가지 설정이 나오는데 그 중 꺾임을 고르면 키의 양쪽 손잡이가 따로 움직여서 키를 기준으로 뾰족한 모양의 그래프를 그릴 수 있다.

이러면 좀 더 현실적으로 넘어지는 연출을 사용할 수 있다. (물론 실제 물리 작용으로 넘어지는것 보다는 어색하겠지만)

 

6. 벡터 타임라인 트랙

타임라인 에디터에서 트랙을 추가할 때 '벡터 트랙 추가'를 할 수도 있다.

 

벡터는 X, Y, Z 3종류의 값을 가진다. 따라서 벡터 타임라인은 동시에 3개의 값을 건드린다.

벡터 값에 따른 대각선 이동

그리고 벡터 타임라인을 사용했으니 반환값은 당연히 벡터다. 이를 이용하면 3차원 공간에서 단순 직선 이동 뿐만이 아니라 대각선 이동도 할 수 있고, 작정하고 만들면 이러저리 휘어지면서 정신없게 이동할 수도 있다.

 

7. 결과물