컨트롤 릭 IK 튜토리얼
컨트롤릭을 통한 IK적용은 기존에 애니메이션 인스턴스 내부에서 적용하던 방식과 비슷하다.
- 내가 IK를 적용하길 원하는 본에서
- 라인트레이스를 쏴서
- 히트한 좌표를 이용해
- 본을 움직인다
두가지 경우로 나눌 것이다.
- IK본이 이미 있는 경우
- IK본이 없는 경우
공통 준비
일단 어떠한 경우든, 라인트레이스는 본마다 쏴야 하니까, 재사용하기 편하도록 함수로 만들어 처리하도록 하자.
함수 생성
입력을 “릭 엘리먼트 키”를 파라미터로 받는다.
이 변수는 릭에 이용할 수 있는 여러 타입이 있는데, 어떤 타입을 이용할 것인지
그리고 그 타입과 일치하는 것의 이름이 무엇인지 받을 수 있다.
- 받아온 타입과 이름을 가지고, 특정 본의 트랜스폼 정보를 가져온다.
- 라인트레이스가 시작할 좌표를 구한다. 본의 위치에서 30만큼 위로 올린 지점을 구했다. (Add로 5만큼 Y값을 더해주고 있는데, 굳이 없어도 될 듯?)
- 라인트레이스가 끝날 좌표를 구한다. 본의 위치에서 100만큼 아래 지점을 구했다.
- 구한 좌표로 SphereTrace 한 뒤, 결과로 나온 히트 로케이션을 리턴한다.
이렇게 생성된 함수는, 다른 캐릭터의 ControlRig에서도 불러 사용할 수 있더라
변수 생성
만든 함수의 결과로 구한 좌표중. Z값만 필요하니까 Z값을 저장할 변수를 선언하자.
다리가 두개면 두개의 변수
네개면 네개의 변수
n개면 n개의 변수를 만들면 되겠다.
나는 사슴에다 쓸거니까, 4개의 변수를 선언할 것이고
각각 이름을 다음과 같이 정해주겠다
- float FloorLH(왼손, 앞발)
- float FloorRH(오른손, 앞발)
- float FloorLF(왼발)
- float FloorRF(오른발)
이 변수에 각각 본마다 실행한 라인트레이스 결과값이 저장될 것이다.
적용
내가 사용할 스켈레톤 구조에 IK본이 없는 경우, 가상의 본을 만들어 사용할 것이다.
하지만, IK본이 같이 있는 경우에는 굳이 가상의 본을 만들 필요 없이. 그냥 IK본을 사용하면 된다.
아래 내용에서 가상의 본이 들어갈 자리에 IK본을 넣어주면 된다는 뜻이다.
가상 본 생성
컨트롤릭에서는 스켈레톤 구조에 내 마음대로 가상의 본을 추가할 수 있다.
내가 IK로 조정할 본마다 가상의 본을 추가해주고, 가상의 본을 움직인 후, 기존의 본의 위치를 가상의 본 위치로 갱신시킬것이다.
내가 가상의 본을 생성하길 원하는 원래 본 이름을 우클릭 한 뒤, 신규 - 새본 을 누르면 가상 본이 추가된다.
총 7개의 가상의 본을 추가하자. 구분을 위해서 가상본 이름을 소괄호 안에다 적어놓겠다.
- RightHand (TempRHand)
- LeftHand (TempLHand)
- RightFoot (TempRFoot)
- LeftFoot (TempLFoot)
- Neck (TempNeck) , 만약 Neck에 해당하는 본이 여러개인 경우 하나 골라서 적용해보고 이상하다 싶으면 다른 본을 사용하는 식으로 하면 된다.
- Head (TempHead)
- Pelvis (TempPelvis)
보면, 네 다리 이외에 3개가 더 추가되었는데, 이유는 다음과 같다.
경사로에서 다리만 굽힐게 아니라 경사진 만큼 골반, 머리, 목도 같이 회전하기 위함.
내리막길에서 앞다리만 늘어나 있으면 이상하지 않은가?
이렇게 추가된 가상 본은 전부 기존의 본 위치에 종속되어 있는데, 다 때어주도록 하자.
가상본을 우클릭 하고 부모 해제 하면 된다.
부모가 해제된 가상의 본은 계층구조 가장 아랫쪽으로 내려가게 된다.
블루프린트 노드 작성
이제 블루프린트 노드를 이용해서 IK를 적용해보자.
먼저 ForwardSolve함수를 재정의 하도록 하겠다.
이 함수는 틱마다 호출된다.
가상본의 위치를 실제 본의 위치와 맞추기
먼저 가상본을 실제 본 위치와 일치시키자.
IK본이 이미 있어서 가상의 본을 만들지 않았다면, 넘겨도 된다.
Get Transform노드를 통해서 특정 이름에 해당하는 본의 위치정보를 가져온다.
함수를 우클릭해서 검색하거나, 혹은 계층구조에서 본 이름을 끌어와도 된다.
이렇게 가져온 본 위치를 가지고, SetTransform을 이용해 가상본의 위치를 갱신해준다.
모든 생성한 가상본에 대해서 실행하면 된다.
라인트레이스 결과를 저장하기
생성한 라인트레이스 함수를 이용해서, 본의 Z값을 얼마나 움직여야 할 지 찾아 저장한다.
가상 본에 대해서 트레이스를 수행하고, 그 결과중 Z값을 변수에 저장하고 있다.
왼쪽 발에 대해서 트레이스를 수행했으니까, 그 결과를 FloorLF(왼쪽 발) 변수에다 저장하는 것이다.
모든 다리에 대해서 트레이스를 수행하고 그 값을 저장하면 된다.
함수 생성부분과 실제 사용한 함수가 다른 부분에 대해서
실제 사용한 함수가 조금 다른데, 위에서 함수 내부 노드를 보면,
특정 본의 위치에서 단순히 위 아래 위치를 구하기 위해서 값을 더하거나 빼고 있다.
좀 더 편하게 사용하기 위해서 더하거나 빼야 할 값을 한개의 값으로 통일하고,
외부에서 함수를 직접 사용할 때, 파라미터로 전달하도록 변경하였다.
리턴으로는 굳이 Z값 이외에 사용되는 값이 없는 관계로 그냥 Z값만 리턴하게 했다.
허리 위치 갱신하기
이렇게 구한 트레이스 값들을 이용해서, 일단 허리위치를 적당히 올리거나 내려주도록 하자.
뒷발에 대한 값을 가지고 갱신을 할 것이다.
보면, Pelvis 가상본의 위치를 가져온 뒤,
양 Foot의 값 중 낮은값을 구해서 가상본위 위치에 더해주고 있다.
그렇게 구한 새 위치값을, 다시 Pelvis가상본에 덮어쓴다.
만약 큰 값으로 갱신할 경우에는 허리위치가 쓸때없이 많이 올라가게 될 것이다.
결과를 이용해서 IK 적용하기
여기가 가장 복잡하다.
먼저 FullBody IK 함수를 호출한다.
이 함수에서 실제 IK를 적용하게 될 것이다.
IK의 루트를 설정해 준 뒤, Effector배열에다 IK로 변경할 본과 위치 및 회전값을 전달해주면 된다.
하나씩 보도록 하자.
-
Pelvis
가상의 Pelvis를 가져온 뒤, 원본 Pelvis본의 트랜스폼을 덮어 썼다. 바로 전단계에서 갱신했기 때문이다.
지금보면 그냥 이 부분에 통합해도 상관없을거같긴 하다. -
Neck 가상의 Neck의 Tr을 가져온 뒤, 원본 Neck본을 갱신한다.
회전값은 그냥 그대로 전달하고, 위치값만 변경할텐데,
가상본의 위치에다가, 오른손/왼손 flaot값 중 더 작은값을 Z값으로 추가할 것이다.
이 과정으로 허리와 마찬가지로 목을 좀 더 올려주거나 내려주는 효과를 줄 수 있다. -
각각의 다리
다리의 가상본을 가져온 뒤, 원본 본의 회전값은 그대로 덮어쓰고,
위치값만 변경한다.
이 때, 가상본의 위치값에서 각각 가상본에 해당하는 float값( TempLFoot의 경우 FloorLF )를 Z로 하여 더하여 적용한다.
요 과정으로 다리가 올라가거나 내려가거나 할 것이다. -
Head
머리도 움직여주자.
머리 가상본을 가져온 뒤, 원본 본에다가 회전값은 그대로 덮어쓰고,
위치값을 갱신할텐데, 가상본의 위치값에다 목과 마찬가지로 오른손/왼손 flaot값 중 작은 값을 Z값으로 더해준 뒤 덮어쓰자.
목이랑 똑같다.
여기까지 하면, 컨트롤릭 IK 설정이 끝났다.
이렇게 만든 컨트롤릭을 애니메이션 인스턴스 내부에서 사용하면 된다.
애니메이션 인스턴스에서 컨트롤릭 적용
애니메이션 인스턴스 내부 애님 그래프에서 컨트롤릭 노드를 검색해서 연결해준다.
컨트롤릭 노드를 클릭하면 나오는 디테일 패널에서, 내가 만든 컨트롤릭을 넣어주는것을 잊지 말자.