Ragdoll 사용하기 - 게임에서 자연스럽게 적용하기
이전 섹션까지는 캐릭터에 인체형 래그돌을 적용하고 확장된 커스텀 본에 Character Joint를 넣어서 최대한 자연스러운 래그돌을 만들어내는 작업을 진행해보았다. 그렇게 함으로써 게임에 적용하기 적당한 래그돌을 얻었다. 래그돌을 설명하는 제일 첫 번째 섹션의 아래 쪽에서 실제로 게임에서 래그돌을 사용하는 방법에 대해서 이야기했었는데, 이번 섹션에서는 그 부분에 대해서 자세하게 이야기해볼 것이다.
게임에서 래그돌을 사용하는 실제 방법은 실제 애니메이션이 적용되어 있는 캐릭터 오브젝트가 살아있는 동안에는 정상적으로 움직이다가, 캐릭터의 체력이 0이 된다던가 하는 방식으로 사망하게 되면 캐릭터 오브젝트를 래그돌 오브젝트로 교체하는 것이다. 다음은 애니메이션된 캐릭터 오브젝트와 래그돌 오브젝트를 교체해주는 코드이다.
using UnityEngine;
public class Character : MonoBehaviour
{
public GameObject charObj;
public GameObject ragdollObj;
public Rigidbody spine;
void Update ()
{
if (Input.GetKeyDown(KeyCode.Space)) // Space 키를 누르면 캐릭터가 사망한다고 가정하자.
{
ChangeRagdoll();
spine.AddForce(new Vector3(0f, 0f, 5000f));
}
}
public void ChangeRagdoll()
{
charObj.gameObject.SetActive(false);
ragdollObj.gameObject.SetActive(true);
}
}
코드를 작성하고 이미지처럼 적용을 한 다음, 플레이 버튼을 눌러서 테스트를 해보자.
플레이 되는 도중에 Space 키를 누르면 달리기를 하던 캐릭터가 래그돌로 바뀌면서 풀썩 쓰러지는 것을 볼 수 있을 것이다. 하지만 예시 이미지에서도 보이듯이 캐릭터가 래그돌로 바뀔 때, 갑자기 캐릭터의 포즈가 T자로 바뀌면서 변경되는 것을 볼 수 있다. 이것은 래그돌의 기본 자세가 T자 자세이기 때문에 발생하는 문제이다. 하지만 유니티에서 제공하는 기본적인 래그돌 적용 기능은 T자 자세로 하기를 권장하기 때문에 다른 자세로 만드는 것은 추천하지 않는다.
그렇다면 이 어색한 래그돌 전환 문제를 어떻게 해결해야 할지를 찾아야 한다.
우선 캐릭터의 본은 유니티의 Hierarchy 뷰에서 오브젝트로 볼 수 있는데 각 본은 위치와 각도 정보를 가지고 있는 Transform 컴포넌트를 가진다.
애니메이션을 가진 오브젝트와 래그돌이 적용된 오브젝트를 살펴보면 같은 모델링을 사용했기 때문에 같은 구조를 가지고 있는 것을 알 수 있다.
1. 캐릭터의 각 본들은 그 위치와 각도에 대한 정보를 담고 잇는 Transform 컴포넌트를 가진다.
2. 애니메이션 캐릭터 오브젝트와 래그돌 오브젝트의 구조는 1:1로 대응이 된다.
위의 2가지 정보를 이용하나면 하나의 아이디어를 얻을 수 있다. 그것은 바로 "애니메이션 캐릭터 오브젝트가 래그돌 오브젝트로 교체될 때 각 본들의 위치와 각도를 전해주면 애니메이션 캐릭터 오브젝트가 취한 마지막 포즈를 래그돌 오브젝트가 취한 채로 시작되지 않을까?" 하는 것이다.
이 아이디어를 코드로 만들어보자.
using UnityEngine;
public class Character : MonoBehaviour
{
public GameObject charObj;
public GameObject ragdollObj;
public Rigidbody spine;
void Update ()
{
if (Input.GetKeyDown(KeyCode.Space))
{
ChangeRagdoll();
spine.AddForce(new Vector3(0f, 0f, 5000f));
}
}
public void ChangeRagdoll()
{
CopyAnimCharacterTransformToRagdoll(charObj.transform, ragdollObj.transform);
charObj.gameObject.SetActive(false);
ragdollObj.gameObject.SetActive(true);
}
private void CopyAnimCharacterTransformToRagdoll(Transform origin, Transform rag)
{
for (int i = 0; i < origin.transform.childCount; i++)
{
if (origin.transform.childCount != 0)
{
CopyAnimCharacterTransformToRagdoll(origin.transform.GetChild(i), rag.transform.GetChild(i));
}
rag.transform.GetChild(i).localPosition = origin.transform.GetChild(i).localPosition;
rag.transform.GetChild(i).localRotation = origin.transform.GetChild(i).localRotation;
}
}
}
위의 코드는 SetActive로 오브젝트들을 교체하기 직전에 원본의 자식 오브젝트들의 Transform을 래그돌의 자식 오브젝트들의 Transform에 복사해주는 작업을 진행한다.
완성된 코드를 적용하고 테스트를 해보면 Space 키를 누르면 달리는 동작과 자연스럽게 이어지면서 쓰러지는 것을 볼 수 있다.
[유니티 어필리에이트 프로그램]
아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.
[투네이션]
[Patreon]
[디스코드 채널]
'Unity3D > Physics' 카테고리의 다른 글
[Unity3D] 게임 오브젝트에 Collider 컴포넌트를 추가하지 않고 한번만 충돌체를 찾아내는 Physics의 Cast 계열 함수들의 사용법 (2) | 2017.09.07 |
---|---|
[Unity3D] Character Joint - 캐릭터에 물리효과를 받는 본 추가하기 (0) | 2017.07.26 |
[Unity3D] Ragdoll 사용하기 - 커스텀 본에 Ragdoll 적용하기 (0) | 2017.07.25 |
[Unity3D] Ragdoll 사용하기 - Character Joint의 옵션과 조정(5.6) (5) | 2017.07.23 |
[Unity3D] Ragdoll 사용하기(5.6기준) (0) | 2017.07.21 |