
캐릭터 애니메이션
- 애니메이션 블루프린트
- 블렌드 스페이스
- 캐릭터 속도
카메라 각도 변경
액터에 상호작용 넣기
- 오버랩(Overlap)
- 회전
- 마찰
공부 후 느낀 점
이때까지는 캐릭터가 움직이기만 했다. 뭔가 움직일 때 애니메이션이 있으면 좋겠다고 생각했는데 마침 오늘 배우게 됐다. 이걸 배우기 전에는 캐릭터가 돌처럼 아무런 동작이 없었지만 애니메이션 블루프린트로 캐릭터에게 생동감을 불어넣어 줄 수 있었다.
아래는 애니메이션 블루프린트를 만드는 순서다.
그럼 이런 창이 뜬다. 애니메이션 → 애니메이션 블루프린트를 클릭한다.
우클릭 하기 전 애니메이션 블루프린트를 넣을 경로를 먼저 새 폴더를 만들어 위치를 잡아야 한다.

이걸 더블 클릭하면 선택한 블루프린트 창이 나온다.
ABP는 Animation Blue Print 줄여서 ABP
왼쪽 상단에는 애니메이션이 실행되면 어떻게 보이는지 미리보기가 가능한 뷰포트
왼쪽 하단은 블루프린트 목록
가운데는 AnimGraph(애님 그래프)
우측 상단은 디테일 창
우측 하단은 에셋 브라우저가 보인다.
거기서 에셋 브라우저에 들어간다.
여기 보이는 목록 중 하나인 A_Bot_Idle을 드롭다운으로 애님 그래프로 가져왔다.
이렇게 연결도 가능하다. 컴파일을 누르면..
캐릭터의 팔이 차렷 자세로 바뀌었다.
여기서 애님 클래스를 ABP_MY_Character로 바꿔주고 컴파일 후 저장

블렌드 스페이스는 또 뭘까.. 블렌드가 섞는다는건 아는데..
여러 애니메이션 클립(예: 걷기, 뛰기, 달리기)을 하나의 공간에서 조합된다.
캐릭터의 현재 상태(속도, 방향 등)에 따라 적절한 애니메이션을 생성한다.
속도(speed)와 방향(direction) 같은 변수들을 기준으로 애니메이션을 조합한다.
예를 들어, 캐릭터가 천천히 걸을 때는 "걷기" 애니메이션을, 빠르게 달릴 때는 "달리기" 애니메이션을 사용하며, 속도에 따라 두 애니메이션 사이를 부드럽게 전환한다.

아래는 만드는 법 설명
다 만들면 이렇게 블렌드 스페이스가 새로 생긴다.
더블 클릭하면..
이런 창이 뜨는데 뷰포트 아래에 약간 가로, 세로 그래프 같은 이상한 창이 뜬다.
거기에 에셋 브라우저에 있는 애니메이션을 드롭다운으로 가져와서 섞으면 된다.
왼쪽에 있는 디테일 창에서 Axis Settings를 본다. 저렇게 설정을 끝내면..
왼쪽의 세로 축의 이름이 Speed로 바뀌었고 최대 축값이 500, 뒤에 희미하게 보이는 선이 왼쪽, 오른쪽으로 2분할이 되었다.

저 흰색 점이 에셋 브라우저에서 끌어온 애니메이션이고 뒤에 흰색 실선 기준에 정확히 맞춰져 있는데 Shift를 누른 채로 드래그하면 저렇게 깔끔히 된다.
gif처럼 ctrl를 누르고 속도에 따라 애니메이션이 어떻게 작동하나 확인할 수 있다.

아니면 그냥 에셋 브라우저의 애니메이션 하나만 가져올 수도 있다.
예시로 A_Bot_Fall, A_Bot_Idle

Is Valid는 해당하는 값이 있는지 없는지 확인
Try Get Pawn Owner는 해당 클래스를 가지고 있는 주인 = 액터(ABP_Character)를 의미
Get Velocity에서 속도를 빼올 수 있다.
Break Vector는 점프할 때 달리면 안되니까 Z축을 제외한 X, Y축의 속도 값만 가져오도록 한다.
이 때, Get Velocity에서 Return Value핀에 우클릭해서 구조체 핀 분할로도 똑같이 가능하다.
Make Vector는 Get Velocity에서 받은 속도의 Vector 값을 만들어준다.
Vector Length는 벡터값을 받아 벡터의 길이를 만들어준다.
마지막으로 그 벡터의 길이가 Speed 변수에 들어간다.
벡터의 길이는 스칼라 값으로 속력이다.
어쨋든 이제 캐릭터가 Speed값을 가질 때 달리는 애니메이션이 나오도록
설정하였으니 드디어 캐릭터가 달리는 모션이 나온다!
여기서 Make Rotator로 X, Y, Z축의 회전 각도를 만들어 준다.
Set Control Rotation은 카메라 시점을 각도에 따라 회전시켜준다.
X를 45도로 줬을때는 W,A,S,D가 다 움직여졌다.
X를 90도로 주니까 W,S키는 먹히고 A,D키가 먹히지 않았다.
Why? (아직 모르겠다. 나중에 정리..)
어쨋든 Rotation이 들어간 노드들로 카메라의 시점을 변경할 수 있다!
오버랩 이벤트는 캐릭터가 특정 공간을 통과하거나 겹쳐졌을 때 발생한다.
우선 트리거 볼륨을 찾아야 한다. 퀵 메뉴에서 액터 배치 패널을 연다.
액터 배치 패널에서 트리거 볼륨을 찾아 배치했다.
저기 주황색 정육면체에 기즈모가 살짝 보이는 게 트리거 볼륨이다.
트리거 볼륨 선택 후 레벨 블루프린트를 열었다.
왜 굳이 선택 후에 블루프린트를 열지? 의문이 들었지만 우클릭으로 노드를 생성할 때
선택한 액터(컨텍스트)에 대한 이벤트 추가, 함수 호출 기능이 새로 생겼다.
항상 컨텍스트에 따라 체크했을 때랑 안 했을 때 차이점이 궁금했다.
구글에 검색하니 이벤트가 일어나는 조건, 환경이 컨텍스트이다.선택한 요소 + 그 선택한 요소의 작업 환경이 컨텍스트라고 이해했다.
그래서 선택한 액터의 이벤트 추가, 함수 호출을 하려면 컨텍스트를 체크하고
그게 아니면 체크를 해제하면 된다.
여기서 이벤트 추가→콜리전→Add On Actor Begin Overlap&Add On Actor End Overlap을 했다.
트리거 볼륨 때와 마찬가지로 액터를 선택하고 블루프린트를 열었다.
여기부터 라이브 강의를 보며 따라할 때 많이 놓치고 뒤늦게 따라갔다. 그냥 우클릭이 아니라 꼭 핀을 끌어서 노드를 생성하자. 그래야 지정한 요소에 따른 특정 기능을 가진 노드들이 나온다.
그리고 트리거 볼륨에 캐릭터가 오버랩하면 문이 안 보이도록 이렇게 설정했다.
하지만 문을 치웠음에도 지나갈 수 없었다. 투명한 벽에 막힌 느낌인데 문 위의 n자 모양으로 있는 벽이 문제였다.
그래서..
이 벽의 이름을 콘텐츠 드로어에서 검색하고 스태틱 메시를 더블 클릭해 이런 창에 들어왔다. 뷰포트 왼쪽 상단에 표시를 누르고 단순 콜리전을 누르면 이렇게 초록색 영역이 막고 있어서 못 지나갔다는 걸 알 수 있다. 콜리전은 충돌을 뜻한다.
궁금해서 실험해봤는데 V자 초록 실선 사이로 점프하면 지나가진다.
그래도 원하는 게 캐릭이 눈에 보이는 뚫린 공간을 지나가는 것이기 때문에
길을 뚫어야 한다. 초록색 영역이 저 물체에 맞게 하려면..
자동 조정을 할 수 있다!
일단 콜리전을 제거한다. 강의에서는 콜리전 제거하고 콜리전 조정을 했지만 그냥 바로 콜리전 조정을 해도 된다.
여기 맨 밑에 자동 컨벡스 콜리전을 누른다.
그러면 우측 하단에 컨벡스 분해 창이 뜬다.
헐 개수는 늘어날 수록 디테일하게 초록색 영역을 그려준다. 그러니 8개 정도로 맞추면..
알아서 물체에 맞게 콜리전 영역이 그려진다. 그렇지만 이 때 좋다고 헐 개수를 막 늘리거나 컨벡스 분해를 많이하면 좋지 않다.
언리얼 엔진에서 물체를 분석해서 그거에 맞게 영역을 그려주는데 많은 연산이 들어가니까 최적화를 위해선 필요할 때만 쓰는게 맞다.
그래도 통과가 되지 않았다.
이렇게 중간에 Destory Actor를 넣으면 Target이 되는 액터가 사라진다.
이렇게 Set Collision Enabled를 넣고 액터 자체를 사라지게 하지 않고 충돌을 무시하도록 No Collision 설정을 해도 결과는 똑같다.
하고 나니 벽을 쉽게 통과했다!
이렇게 On Actor End Overlap노드와 다른 노드들을 연결하고 Set Collision Enabled에서 다시 Collision Enabled로 설정하면 캐릭터가 트리거 볼륨이 벗어났을 때 다시 문이 생성된다!
이 문 이름은 아웃라이너에서 'Building01_367'으로 확인했다. 맵에 있는 걸 복사해서 사용하고 싶으니 새 블루프린트 클래스를 만들었다. 콘텐츠 드로어에서 우클릭→블루프린트 클래스→액터를 고르면 된다. 거기 더블클릭해서 들어가면..
이런 새 블루프린트(액터)가 보인다. 여기서 콘텐츠 드로어에서 Building01_367으로 생성한다.
선택한 문의 디테일 패널의 스태틱 메시를 보면 사용하는 메시의 이름을 알 수 있다.
이렇게 콘텐츠 드로어에서 검색을 하고 드롭다운하면 알아서 추가가 된다.
여기서 살짝 위치를 저 중앙 원에 맞게 움직였다.
왜냐하면 그렇게 맞춰야 레벨에서 실제 문처럼 열고 닫히기 때문이다.
이제 동작은 준비되었으니 아까처럼 트리거 볼륨같은 게 필요하다.
그 역할을 Box Collision이 해주는데 블루프린트의 컴포넌트에 추가를 누르고 box를 검색하면 바로 나온다. 그럼 박스가 나오는데 이걸 트리거로 문이 열려야 되니 적절히 크기를 늘려야 한다.
대충 늘렸는데 그리드 정확하게 맞추는걸 좋아하면 뷰포트 아래에 원근을 다른 걸로 바꿔서 맞추면 된다. 상단으로 하고 맞추었다.


이렇게 상단에서 그리드를 맞추고 다시 원근으로 돌아와서 보면 훨씬 깔끔해졌다!!
자 이제
여기서 Overlapped Component는 오버랩된 나 자신(빙의된 캐릭터)을 반환하고
Other Actor는 오버랩된 상대 target을 반환한다.
여기서는 As BP NBC Character를 Promote to variable(변수로 승격)할 수 있다.
여기서 Pawn과 NBC_Character가 똑같은거 아닌가 생각했다. 하지만 오버워치로 따지면 0번이 솔져, 1번이 윈스턴이라 했을 때
Pawn에 아이템을 먹는 동작을 넣으면 두 캐릭 다 먹어지지만
0번만 정하면 0번만 먹어진다. NBC_Character 말고 다른 캐릭터가 들어오면
BP NBC Character의 변수는 설정되지 않을 것이다..
이런식으로 최종 구성이 된다. Add Actor Local Rotation은 Target이 self로 되어있으니 Box가 포함된 enhancedDoor을 기준으로 돈다. 그래서 X, Y, Z축을 뷰포트에서 일단 확인한다.
파란 축으로 돌리면 문처럼 잘 돌려질 거 같고 기즈모를 확인하면 Z축이다. Add Actor Local Rotation에 Z축의 값을 변경하고 실행했다. 문 앞의 박스를 왔다갔다 할때마다 문이 점점 회전하며 열렸다.
그리고 문이 회전하면 트리거 볼륨 역할을 하는 Box가 회전하는 문에 붙어있어서
문을 회전시키려면 문 앞을 서성거려야 한다.
왜인진 모르겠지만 카메라 시점을 자유롭게 움직일 수 있는 지금은 캐릭터가 가만히 있는 상태에서 물체랑 충돌을 만들기는 어렵다고 했다. 그래도 회전하는 자동차를 만들어보기로 했다.
블루프린트 클래스를 만들고 필요한 변수들을 만들어 줬다.
Radius는 반지름 ← 얼마나 처음 기준점에서 띄어서 만들건지를 정함
Origin ← 회전하는 축의 원래 위치
Speed는 속도 ← 얼마나 빠르게 회전할 지 정함
참고로 블루프린트 목록의 저 눈모양이 눈이 떠져있으면 월드의 디테일 창에서
해당 자동차 스태틱 메시를 가지고 있는 액터를 클릭했을 때 변수를 바로 조정할 수 있다!
다음은 자동차의 이벤트 그래프다.
Get Actor Location은 선택한 액터(자동차)의 위치 정보를 가져온다.
저런식으로 Radius(반지름)를 X축에 더해서 Vector값으로 만들어주면
월드의 자동차 위치가 Radius의 값이 더해진 값이 World Location에 적용된다.
Event Tick에 보이는 Delta Seconds는 프레임과 프레임 사이의 시간이다. 만약 프레임이 30이면 30분의 1초가 Delta Seconds가 된다. 게임을 하면 프레임이란 단어가 많이 나온다.
거리 = 속도×시간 공식을 기억하자.
10프레임을 가진 사람은 1/10초마다 1프레임 끝나고 거리 이동
60프레임을 가진 사람은 1/60초마다 1프레임 끝나고 거리 이동
60프레임이 10프레임에 비해 거리가 조금씩 이동되는 게 눈에 보이기 때문에 부드럽다.
FPS가 낮으면 움직임이 덜 부드러워 보이고,
FPS가 높으면 더 부드럽게 보이는 이유가 바로 이 Delta Seconds의 차이였다.
이제 캐릭터가 움직여서 자동차와 충돌했을 때 이벤트를 위해 On Component Hit를 이벤트 추가→콜리전에서 선택했다.
Launch Character는 Target과 충돌 이후 target의 상태를 특정 속도로 발사하도록 하고 그 이후 falling 상태로 만든다. 쉽게 말하면, 캐릭터를 날려주는 기능이다.
Add Impulse는 target이 Primitive Component인데 아직 뭔지 모르겠고
단일 바디에 충격량을 가해주는 거라고 들었다. 단발성으로 팡! 쏘는 느낌이다.
캐릭터를 날려야 하니 Lanch Character를 사용했다.
On Component Hit의 Hit에 구조체 핀 분할을 사용했다. to Vector(float)를 사용해 Hit Normal에 음수로 벡터값을 곱해주면 캐릭터 반대 방향의 속력을 구해준다.
실제로 양수로 실험하니 캐릭터가 방향 그대로 빠르게 날라갔다.
구글에다 벡터의 정규화라고 검색해보자..
Hit normal은 부딪힌 위치의 벡터값이라고 들었다.
gpt의 도움을 받았다.
Hit Normal에 양수 값을 곱하면, 충돌 표면의 정방향으로 힘이 작용한다.
따라서 캐릭터가 충돌 표면 방향으로 밀리거나 날아가게 된다.
충돌 방향으로 힘을 가해 벽을 "뚫고 나가는" 듯한 효과.
Hit Normal에 음수 값을 곱하면, 충돌 표면의 반대 방향으로 힘이 작용한다.
캐릭터가 충돌 지점에서 "튕겨 나가는" 효과
충돌하는 힘을 -20000으로 주었더니 공중으로 날아가버렸다..
그리고 다른 오브젝트도 날리고 싶으면 해당 오브젝트의 디테일 창에서
피직스 시뮬레이션에 체크하면 충돌을 받아 밀려나거나 날라가게 된다.
만든 캐릭터 블루프린트에서 캐릭터 무브먼트를 클릭하면 이런 디테일 창이 뜬다.
마찰 인수 제동과 감속 걷기 제동으로 캐릭터의 마찰값을 조정해보았다.
발판을 위해 floor를 꺼내서 오버랩 때처럼 블루프린트 클래스를 만들고 Box도 설정해줬다.

이렇게 전체적으로 미끄러지는 발판을 만들어 보았다.
위 사진에 있는 SET 노드를 불러올 때
지면 마찰은 'friction'이라 검색하고 'Set Ground Friction'을 클릭!
감속 걷기 제동은 'deceleration'이라 검색하면 '캐릭터 무브먼트: 걷기' 가 나오는데 거기서 'Set Braking Deceleration Walking'을 클릭하면 된다.
여기서 캐릭터 변수를 만든 이유는 거기서 Character Movement를 빼와서
지면 마찰과 감속 걷기 제동의 값이 설정될 수 있는 target을 지정하기 위해서다.
target이 없다면 캐릭터에게 저 설정값이 적용되지 않을 것이다.
이렇게 Delay 노드와 Time 변수, Set Simulate Physhics를 활용하면 공중의 발판을 몇 초 뒤에 떨어지게 할 수 있다.
Simulate Physhics가 피직스 시뮬레이션인데 체크를 했을 때
공중에 있는 물체면 중력이 적용되어 아래로 떨어진다.
아까 전 캐릭터가 바닥을 밟았을 때 Overlap되면 이벤트를 발생시키는 걸 해보았다.
그걸 이용해 플레이어가 공중 바닥을 밟으면 몇 초 뒤에 그 바닥이 떨어지게 할 수 있다!
라이브 강의를 들으며 따라갈 때 이걸 몰라서 좀 헤멨다. 그리고 원하는 게 안나오면 컨텍스트를 해제하면 된다.
완벽하게 하려하다 보니 그 방법 찾는데 시간을 다 투자해야 했다. 그래서 원하는 레벨을 만들어 볼 때는 어떻게든 구성을 하고 방법이 맘에 안들어도 그냥 해야겠다.
의외로 다른 사람들이 이미 해놓은 게 많고 결과도 빨리 찾을 수 있다. "아 이런거 내가 구현할 수 있나?" >> 일단 다른 사람이 한 방식이나 플러그인 찾기(더 쉬운 방법)