Valve Index 컨트롤러로 VRChat에서 손 모양을 애니메이션과 같이 사용하기
Avatar 3.0을 기준으로 하고 있습니다.
얼마 전 Valve사의 Index 컨트롤러를 구매했습니다. (정확히는 풀킷을 구매.)
그 전까지 사용하던 오큘러스의 CV1이라던가, 바이브 몽둥이라던가, 퀘스트2 컨트롤러 같은 경우에는 이미 정해진 애니메이션에 따라 손 모양이 바뀌었기 때문에 문제가 없었지만, 정전 용량식 센서를 사용하는 인덱스 컨트롤러의 경우 손의 세세한 구부러짐 등을 추적하기 때문에 이러한 애니메이션을 사용할 수 없게 됩니다.
그래서 인덱스 컨트롤러로 브이를 하면 사진과 같은 모양이 됩니다.

이런 문제를 해결할 수 있는 방법으로는 현재로서는 두 가지가 있는 것 같네요.
첫 번째는 손가락의 본을 벌려서, 손가락을 폈을 때 V가 되게 하는 방법.
두 번째는 토글을 켜거나 특정 조건을 만족했을 때 애니메이션을 강제로 오버라이드 해서 보여주는 방법.
우선, 첫 번째 방법의 경우에는 본을 처음부터 벌려놓는 방식이기 때문에 인덱스 컨트롤러의 정전 용량식 센서를 그대로 사용할 수 있습니다.(= V 포즈를 하기 이전에 손가락을 펴는 행동을 그대로 추적할 수 있음)
하지만 본이 벌려져있기 때문에 V가 아닌 다른 모양일 때는 이상하게 보일 수 있다는 문제가 있습니다.
그렇게 해서, 저는 두 번째 방법인 애니메이션을 오버라이드 하는 방향으로 결정하게 되었습니다.
애니메이션을 발동하는 방식은 토글, 버튼, 특정 조건을 만족하면 실행 등등.. 많은 방식으로 발동시킬 수 있지만
그 중 가장 기본적이고 직관적인 토글을 사용하도록 하겠습니다.

여기서 필요한 레이어는 Gesture 입니다.
만약 기존에 사용하던 레이어가 없으시다면, 새로 만들어주시면 됩니다.
이제 방법이 두 가지로 나뉘게 되는데요.
첫 번째는 기존 레이어에 모션을 추가하는 방법 (간단하지만 가독성이 떨어짐),
두 번째는 레이어를 추가해서 오버라이딩 하는 방법 (깔끔하지만 첫 번째 방법보다 복잡함)이 있습니다.
방법 1) 기존 레이어에 모션을 추가해서 사용하기

제스쳐 레이어는 레이어를 추가할 것도 딱히 없고, 수정을 한다고 해도 애니메이션을 바꿔서 손 모양을 바꾸는 정도라, 보통은 저렇게 3개만 있을거에요.
우선 왼손부터 해보겠습니다.
Left Hand 레이어를 클릭해 주세요.

따로 바꾸신 적이 없다면 사진과 같은 모습입니다.
저는 브이를 하고 싶기 때문에 Peace를 기준으로 하겠습니다.
Peace를 누른 후 Ctrl C, Ctrl V 해주세요.

그러면 Peace로부터 복사된 모션이 보입니다.
이걸 클릭해 주세요.

그러면 Inspector 탭에 사진과 같은 화면이 뜰텐데,
No Change - 이전 컨트롤 내역을 그대로 유지. (예: 이전에 Tracking로 설정되어 있는 컨트롤은 이 애니메이션이 재생되어도 변경되지 않음.)
Tracking - 애니메이션의 손 모양을 무시하고 컨트롤러를 쥔 손의 모션을 그대로 따라함.
Animation - 컨트롤러를 쥔 손의 모션을 무시하고 애니메이션의 손 모양으로 강제됨.

여기서 왼손의 손가락을 애니메이션의 모션으로 강제하기 위해 Left Fingers의 Animation에 체크해 줍니다. (오른손이면 Right Fingers)

Peace를 클릭합니다.

왼손이므로 Left Fingers의 Tracking에 체크합니다. (오른손이면 Right Fingers)

그 후 Any State에서 우클릭 하셔서 Make Transition을 누르신 후, 조금 전 복사했던 Peace 0을 클릭해 주세요. (마우스를 움직이면 선이 따라옵니다. 선이 안따라오면 Make Transition 다시 해주세요.)

이렇게 되어있으면 됩니다.
이제 토글이 켜졌는지 확인하기 위해 변수(Parameters)를 추가합니다.

Parameters 탭을 클릭합니다.

마찬가지로, 따로 수정하신 적이 없다면 4개의 변수만 있을텐데

+ 버튼을 눌러 Bool 변수를 추가합니다.

변수 이름은 적당히 넣습니다. 저는 Force_Gesture로 하겠습니다.
그리고 다시 Layers 탭으로 돌아와서

조금 전에 Make Transition 해주었던거 기억하시죠?
Peace 0으로 가고 있는 선을 클릭해 주세요.

Settings 옆에 화살표 눌러서 펼쳐줍니다.

기본적으로는 이렇게 되어 있을텐데 각 캐릭터마다 Transition Duration 값이 다를 수 있습니다.
0으로 하셔도 되지만 기왕 하는거 손 모션이랑 통일시켜주면 자연스러우니 귀찮아도 해주시는 편이 좋습니다.

마야의 다른 제스쳐의 세팅값은 사진과 같네요.

Has Exit Time에 체크하면 Exit Time을 수정할 수 있습니다.

다른 모션의 세팅값과 똑같이 맞춰준 다음, Has Exit Time과 Can Transition To Self의 체크를 풀어줍니다.

그리고 기존 Peace 모션의 Conditions 값을 봐야 하므로 Peace로 가는 화살표를 눌러보면

GestureLeft가 4번일 때 애니메이션이 실행되도록 되어 있네요.
여기서 +를 눌러 발동 조건을 추가합니다.

Force_Gesture가 false인 조건으로 추가해 주세요.
그리고 여기 있는 Conditions 전부를 Peace 0에 그대로 똑같이 넣습니다.

단, Force_Gesture 값이 true일 때로 설정해 주세요.
여기까지 하셨다면 왼손은 끝입니다. 오른손도 동일하게 해주시면 됩니다.
이후 Expression에 토글 추가하기 과정을 진행해 주세요.
방법 2) 레이어를 추가해서 오버라이딩 하기

오른쪽 위에 보이는 + 버튼을 눌러서 레이어를 두 개 추가해 주세요.
2개인 이유는 왼손, 오른손 각각 있어야 하기 때문입니다 :)

레이어를 두 개 만들었는데, 다른 레이어랑 뭔가 다른 점이 보이시나요?
다른 레이어는 밑에 선이 흰색인데 새로 만든 레이어는 회색이네요!
이 말은 해당 레이어의 Weight가 0임을 의미합니다.
0으로 되어있으면 모션이 발동되어도 보이지 않기 때문에 의미가 없게 돼요.

옆에 톱니바퀴를 눌러서 Weight를 1로 바꿔줍니다. (레이어 둘 다 해주세요)

그리고 각 레이어를 왼손, 오른손 레이어 밑에 하나씩 배치해 주세요.
레이어는 밑으로 갈 수록 위에 있는 레이어를 덮어쓰게 됩니다.
즉, Left Hand 보다 New Layer가 더 밑에 있기 때문에 Left Hand를 New Layer가 덮어쓸 수 있는 상태가 됩니다.

레이어 이름은 적당히 바꿔줍니다.

빈 레이어에는 Entry, Any State, Exit 말고는 아무것도 존재하지 않습니다.

빈 공간에 우클릭 해서 Create State - Empty를 눌러줍니다.
이걸 3번 해줍니다.

총 3개의 State가 생성되었습니다.

각 State의 이름을 적당히 바꿔줍니다.
주황색으로 된 State는 기본 상태를 의미하며, 아바타가 로드되면 가장 처음 설정되는 State입니다.
즉, 처음 로드되면 Idle이 로드되고, Idle에 애니메이션이 들어가 있다면 그 애니메이션이 재생되는 구조입니다.

Idle에서 우클릭 한 후 Make Transition을 클릭하고, Peace로 이어줍니다.

Peace에서 우클릭 한 후 Make Transition을 클릭하고 Buffer로 이어줍니다. 두 번 해주세요.

두 번 이상 Transition 된 State는 화살표가 여러 개로 보이게 됩니다.

Buffer에서 우클릭 한 후 Make Transition을 클릭하고 Exit로 이어줍니다.
이것도 두 번 해주세요.

최종적으로는 이런 모양이 됩니다.

Idle에서 Peace로 가는 선을 클릭해 보겠습니다.

Settings 옆에 화살표 눌러서 펼쳐줍니다.

기본적으로는 이렇게 되어 있을텐데 각 캐릭터마다 Transition Duration 값이 다를 수 있습니다.
0으로 하셔도 되지만 기왕 하는거 손 모션이랑 통일시켜주면 자연스러우니 귀찮아도 해주시는 편이 좋습니다.

마야의 다른 제스쳐의 세팅값은 사진과 같네요.

Has Exit Time에 체크하면 Exit Time을 수정할 수 있습니다.

다른 모션의 세팅값과 똑같이 맞춰준 다음, Has Exit Time과 Can Transition To Self의 체크를 풀어줍니다.
이 과정을 Peace, Buffer도 전부 똑같이 하는데
Exit Time이랑 Transition Duration의 값을 0으로 설정합니다. 중요합니다.

Transition이 여러 개인 Peace, Buffer의 경우, 화살표를 누르면 Transitions에 항목이 여러 개 뜨게 됩니다.
하나씩 누르시면서 변경하시면 됩니다.
다 변경하셨다면

Peace를 클릭하고

Motion에 손가락 브이하고 있는 애니메이션을 넣습니다.
그리고 Add Behaviour를 클릭합니다.

VRCAnimatorTrackingControl을 추가합니다.

그러면 Inspector 탭에 사진과 같은 화면이 뜰텐데,
No Change - 이전 컨트롤 내역을 그대로 유지. (예: 이전에 Tracking로 설정되어 있는 컨트롤은 이 애니메이션이 재생되어도 변경되지 않음.)
Tracking - 애니메이션의 손 모양을 무시하고 컨트롤러를 쥔 손의 모션을 그대로 따라함.
Animation - 컨트롤러를 쥔 손의 모션을 무시하고 애니메이션의 손 모양으로 강제됨.

왼손이므로 Left Fingers의 Animation에 체크합니다. (오른손이면 Right Fingers)

Buffer를 클릭합니다.

VRCAnimatorTrackingControl을 추가합니다.

왼손이므로 Left Fingers의 Tracking에 체크합니다. (오른손이면 Right Fingers)
이제 토글이 켜졌는지 확인하기 위해 변수(Parameters)를 추가합니다.

Parameters 탭을 클릭합니다.

마찬가지로, 따로 수정하신 적이 없다면 4개의 변수만 있을텐데

+ 버튼을 눌러 Bool 변수를 추가합니다.

변수 이름은 적당히 넣습니다. 저는 Force_Gesture로 하겠습니다.
그리고 다시 Layers 탭으로 돌아와서

Idle에서 Peace로 가는 Transition을 클릭합니다.

브이 모션이 적용되는 Peace는 4번 모션입니다.
Conditions의 + 버튼을 눌러 조건을 두 개 추가해 줍니다.
왼손이므로 GestureLeft 이고, Peace는 4번이므로 Equals는 4가 됩니다.
이후, Force_Gesture가 true인 조건을 추가해 줍니다.

Peace에서 Buffer로 가는 Transition을 클릭합니다.
여기는 아까 Transition을 두 개 생성했었습니다.
각 Transition에 조건이 서로 다르게 들어가니 주의해 주세요.

둘 중 위에 있는 Transition 클릭해 주세요.

조건을 GestureLeft가 4가 아닐 때로 설정합니다.

두 번째 Transition을 클릭합니다.

Force_Gesture가 false일 때로 설정합니다.

Buffer에서 Exit로 가는 Transition을 클릭합니다.

마찬가지로 Transition이 2개 입니다.
맨 위에 있는 Transition을 클릭합니다.

조건을 GestureLeft가 4가 아닐 때로 설정합니다.

두 번째 Transition을 클릭합니다.

Force_Gesture가 false일 때로 설정합니다.
여기까지 하셨다면 왼손은 끝입니다. 오른손도 동일하게 해주시면 됩니다.
Expression에 토글 추가하기
Hierarchy에서 아바타를 클릭하면

Inspector의 Expressions 섹션에 Menu와 Parameters로 지정된 파일이 있습니다.
Parameters 먼저 클릭해 줍니다.

Add를 클릭해서 변수 공간을 하나 추가합니다.

이름은 아까 Gesture 레이어에서 변수 이름으로 사용한 Force_Gesture를 넣습니다. (다른 이름으로 하신 분들은 그 이름을 넣어주시면 됩니다.)
절대로 토시 하나라도 틀리면 안 됩니다.
Type은 Bool로 설정하시고, Default와 Saved는 취향에 맞게 설정해 주시면 됩니다.
Default - 변수의 초기값을 설정합니다. 체크되어 있으면 기본적으로 활성화되고, 해제되어 있으면 비활성화가 기본입니다.
Saved - 아바타를 바꾸거나 월드를 이동해도 변수값을 유지합니다.

Menu를 클릭합니다.

Add Control을 클릭합니다.

이름과 아이콘은 적당히 설정하시면 되고
Type은 Toggle로 설정합니다. Button으로 하게 되면 현재 상태를 알 수 없을 뿐더러, 버튼이 눌린 상태에서만 변수가 true를 반환하므로 꼭 토글로 설정하셔야 합니다.
Parameter는 Force_Gesture로 선택합니다.
맨 오른쪽의 빈 칸에 적지말고 그 옆에 있는 드롭다운 메뉴에서 골라주세요.
전부 끝났습니다.
아바타를 테스트 모드 또는 업로드 하신 후 잘 되는지 확인해 보시면 됩니다.


여기까지 하시느라 정말 수고 많으셨습니다!
이제 사진 찍을 때 고통받지 않아도 돼요!!
내용에 문제가 있거나 더 나은 방법이 있다면 알려주시면 본문에 추가하겠습니다.
과정을 진행하면서 궁금하신 부분이 있으시다면 디스코드 NoriDev#3015 나 트위터 @_NORIDEV_ 로 디엠주시면 감사하겠습니다😊