AnyPortrait > 메뉴얼 > 캐릭터에 아이템 장착하기
AnyPortrait로 작성된 캐릭터에 외부의 오브젝트를 부착하기 위해서 소켓(관련 페이지)이라는 기능이 있습니다.
이 페이지에서는 이 기능을 이용하여 외부의 오브젝트, 특히 무기나 장비와 같은 아이템을 부착하는 방법을 설명합니다.
설명을 위해 제작된 데모 씬의 해적 소녀 캐릭터와 3D 모델로서 제작된 총입니다.
현재 캐릭터가 들고 있는 총을 삭제하고, 3D 총을 캐릭터가 오른손으로 잡도록 만들어봅시다.
주의
이 페이지에서는 차이점을 보여주기 위해 3D 모델을 준비했지만, 2D 이미지가 적용되는 Quad 메시나 Sprite를 준비하는 것이 좋습니다.
아래에서 설명할 렌더링 방식과 관련된 문제가 있기 때문입니다.
가장 먼저 해야하는 작업은 소켓을 설정하는 것입니다.
(1) 무기가 부착될 오른손의 본을 선택합니다.
(2) 스크립트로 해당 본을 호출해야하므로, 본의 이름을 기억합니다.
(3) Socket 속성을 활성화합니다.
기존의 총 메시는 숨기겠습니다.
(이 과정은 예제를 만들기 위한 단계이며 무시해도 됩니다.)
(1) 메시 그룹의 Setting 탭에서 (2) 총 메시를 선택하고 (3) Visible을 끕니다.
이제 장착할 무기를 준비합니다.
3D 메시를 비어있는 GameObject의 자식으로 설정하여 무기를 구성했습니다.
이렇게 준비하는 이유는, 오브젝트의 원점이 총의 손잡이여야 하기 때문입니다.
또한 본이 가리키는 방향은 Y축이므로, 총구도 Y 방향을 향하도록 만듭니다.
이제 스크립트를 아래와 같이 작성해봅시다.
using UnityEngine;
using AnyPortrait;
public class WeaponEquipScript : MonoBehaviour
{
public apPortrait portrait;
public Transform gunTransform;
void Start()
{
//캐릭터의 오른손 본을 무기의 부모로서 설정
Transform handBone = portrait.GetBoneSocket("Bone Hand R");
gunTransform.parent = handBone;
//위치와 회전을 소켓과 동일하게 만들고, 크기는 부호만 확인
gunTransform.localPosition = Vector3.zero;
gunTransform.localRotation = Quaternion.identity;
Vector3 gunScale = gunTransform.localScale;
if(gunScale.x < 0) { gunScale.x *= -1; }
if(gunScale.y < 0) { gunScale.y *= -1; }
gunTransform.localScale = gunScale;
}
}
GetBoneSocket 함수를 이용하여 오른손 본의 Transform을 가져올 수 있습니다.
무기의 GameObject를 오른손 본의 Transform의 자식이 되도록 변경하고 로컬 위치를 초기화하면, 무기 메시가 오른손의 움직임에 따라 움직일 것입니다.
위 스크립트를 씬에 적용합니다.
(1) 새로운 GameObject를 만듭니다.
(2) 작성한 스크립트를 추가된 GameObject에 추가하고, 캐릭터와 무기의 Transform을 각각 지정합니다.
게임을 실행해봅시다.
총이 캐릭터의 오른손에 부착되어 움직이는 것을 볼 수 있습니다.
총의 렌더링 순서가 이상합니다.
총이 캐릭터의 손 안에 들어가야 하는데, 지금은 캐릭터의 뒤쪽에 위치합니다.
총의 렌더링 순서를 지정하기 위해서는 메시의 렌더링 순서, 즉 Sorting Order를 알아야 합니다.
AnyPortrait 에디터를 다시 엽니다.
(1) 이 캐릭터의 오른손은 손바닥 메시와 손가락 메시로 나뉘어져 있으며, 총이 그 사이에 위치합니다.
(2) 오른손의 손가락 메시를 선택하고 (3) 메시의 이름 (Hand R Finger)를 기억합니다.
메시들의 렌더링 순서에 따라 서로 다른 Sorting Order가 할당되도록 만듭니다.
(1) Bake 버튼을 누릅니다.
(2) Setting 탭을 누릅니다.
(3) Sorting Order Option을 Depth To Order로 변경하고, Order Per Depth를 2로 증가시킵니다.
스크립트로 총 메시의 Sorting Order를 오른손 손가락 메시보다 1 적게 만들고자 하므로, Sorting Order는 2 이상의 간격으로 할당되어야 다른 메시와 렌더링 순서가 중복되는 것을 피할 수 있습니다.
스크립트를 아래와 같이 수정하여 Sorting Order를 제어합니다.
using UnityEngine;
using AnyPortrait;
public class WeaponEquipScript : MonoBehaviour
{
public apPortrait portrait;
public Transform gunTransform;
public MeshRenderer gunMeshRenderer;
void Start()
{
//캐릭터의 오른손 본을 무기의 부모로서 설정
Transform handBone = portrait.GetBoneSocket("Bone Hand R");
gunTransform.parent = handBone;
//위치와 회전을 소켓과 동일하게 만들고, 크기는 부호만 확인
gunTransform.localPosition = Vector3.zero;
gunTransform.localRotation = Quaternion.identity;
Vector3 gunScale = gunTransform.localScale;
if(gunScale.x < 0) { gunScale.x *= -1; }
if(gunScale.y < 0) { gunScale.y *= -1; }
gunTransform.localScale = gunScale;
//손가락 메시의 바로 뒤에서 렌더링 되도록 설정
int fingerSortingOrder = portrait.GetSortingOrder("Hand R Finger");
gunMeshRenderer.sortingOrder = fingerSortingOrder - 1;
}
}
총 모델의 MeshRenderer의 Sorting Order를 캐릭터의 오른손 손가락 메시(Hand R Finger)보다 1 작게 설정하는 스크립트입니다.
스크립트에 MeshRenderer gunMeshRenderer 변수가 추가되었으므로, 유니티 에디터에서 총 메시의 MeshRenderer를 할당합니다.
여기서 주의할 점이 있습니다.
기본적으로 부피를 가진 Opaque 방식의 재질은 Sorting Order로 렌더링 순서를 제어할 수 없습니다.
따라서 이 예제에서 3D 모델로 제작된 총의 렌더링 방식을 Transparent로 변경해야합니다.
Transparent 방식의 재질에서 이 모델의 렌더링은 다소 이상할 수 있습니다.
따라서 가능한 2D 이미지를 그대로 이용하는 Quad 메시나 Sprite로 아이템을 만들기를 권장합니다.
게임을 실행하면 렌더링 순서가 보정되어 캐릭터가 제대로 총을 쥐는 것이 표현됩니다.