2 분 소요

이 글은 유튜브 Sebastian Graves Create Dark Souls를 보고 따라 만들면서 헷갈리는 부분을 정리한 글입니다.

구현 개요

무기를 손에 들고 있는 것을 만든다.

구현 내용

대략적인 구현 내용은 다음과 같다.

  1. Item 클래스와 그것을 상속받는 WeaponItem 클래스를 만든다
  2. 양 손에 무기를 생성하여 자식으로 넣거나 장착 중인 무기를 파괴하여 안보이게하는
    기능이 구현된 WeaponHolderSlot 스크립트를 만들어 넣는다.
  3. 양 손에 장착된 WeaponHolderSlot스크립트를 관리하는 WeaponSlotManager 스크립트를 만든다.
  4. PlyaerInventory 스크립트를 하나 더 만들어 WeaponSlotManager 스크립트와 상호작용한다.

item 세팅

Item 스크립트

모든 아이템 클래스의 부모가 될 Item 스크립트를 만들어준다.

Item 를 상속받는 모든 클래스는 공통으로 아이콘과 이름을 가질 것이다.

아이템 스크립트의 경우 유니티에서 제공하는 스크립터블 오브젝트를 상속받게 한다.

public class Item : ScriptableObject
{
    [Header("Item Information")]
    public Sprite itemIcon;         // 아이템 아이콘
    public string itemName;         // 아이템 이름
}


WeaponItem 스크립트

Item 스크립트를 상속받으며 유니티 메뉴창에서 생성할 수 있도록
[CreateAssetMenu] 속성을 달아준다.

[CreateAssetMenu(menuName = "Items/Weapon Item")]
public class WeaponItem : Item
{
    public GameObject modelPrefab;      // 무기 프리팹
    public bool isUnarmed;              // 비무장 무기를 사용할때 체크(현재는 미사용)
}

createAssetMenu를 통해 WeaponItem은 메뉴에서 생성이 가능하게 되었다.

image


스크립터블 오브젝으를 통해 객체를 생성하기 전에 sword_01의 프리팹을 만들어준다.
sword_01 프리팹은 빈 오브젝트 Sword_01이 최상위 부모로
그 밑으로 무기의 위치와 크기를 잡아줄 Weapon Pivot 빈 오브젝트와
모델을 담당할 Sword_01을 자식으로 가진다.

이때 Weapon Pivot의 크기는 100 100 100으로 해준다.
플레이어 캐릭터 모델의 자식으로 들어가게되면 크기가 0.01배 되어있어
무기 또한 0.01배가 되버리기 떄문

image

WeaponItem 객체 Sword 생성

아이콘은 아직 없으므로 이름과 방금 만든 Sword_01 프리팹을 넣어줌

image

WeaponHolderSlot

플레이어의 양손에 달아줄 스크립트인 WeaponHolderSlot 스크립트를 만든다.

public class WeaponHolderSlot : MonoBehaviour
{
    public Transform parentOverride;        // 왼손의 경우 바로 손의 자식으로 넣지않고 빈 객체 밑으로 넣는다.
    public bool isLeftHandSlot;             // 어느쪽 손인지 (왼손인지 오른손인지)
    public bool isRightHandSlot;            // 구분할 변수

    public GameObject currentWeaponModel;   // 현재 장착 중인 무기

    // 무기 해제 (비활성화 해서 해제)
    public void UnloadWeapon()
    {
        if(currentWeaponModel != null)
        {
            currentWeaponModel.SetActive(false);
        }
    }

    // 무기 해제 (무기를 파괴해서 해제)
    public void UnloadWeaponAndDestroy()
    {
        if(currentWeaponModel != null) 
        {
            Destroy(currentWeaponModel);
        }
    }

    // 무기를 파괴하여 해제하고 새로운 무기 장착
    public void LoadWeaponModel(WeaponItem weaponItem)
    {
        UnloadWeaponAndDestroy();

        if(weaponItem == null)
        {
            UnloadWeapon();
            return;
        }

        GameObject model = Instantiate(weaponItem.modelPrefab) as GameObject;
        if(model != null)
        {
            if(parentOverride != null)
            {
                model.transform.parent = parentOverride;
            }
            else
            {
                model.transform.parent = transform;
            }

            model.transform.localPosition = Vector3.zero;
            model.transform.localRotation = Quaternion.identity;
            model.transform.localScale = Vector3.one;
        }
        currentWeaponModel = model;
    }
}

왼손과 오른손에 스크립트들 달아줌.

왼손

image

오른손

image


Player 세팅

WeaponSlotManager 스크립트

양손의 WeaponHolderSlot을 관리하는 WeaponSlotManager스크립트 생성

public class WeaponSlotManager : MonoBehaviour
{
    
    WeaponHolderSlot leftHandSlot;      
    WeaponHolderSlot rightHandSlot;

    private void Awake()
    {
        // 양손의 WeaponHolderSlot을 가져옴
        WeaponHolderSlot[] weaponHolderSlots = GetComponentsInChildren<WeaponHolderSlot>();
        foreach  (WeaponHolderSlot weaponSlot in weaponHolderSlots)
        {
            if(weaponSlot.isLeftHandSlot)
            {
                leftHandSlot = weaponSlot;
            }
            else if (weaponSlot.isRightHandSlot)
            {
                rightHandSlot = weaponSlot;
            }
        }
    }

    // WeaponHolderSlot를 이용하여 무기를 장착하는 함수 구현
    public void LoadWeaponOnSlot(WeaponItem weaponItem, bool isLeft)
    {
        if(isLeft)
        {
            leftHandSlot.LoadWeaponModel(weaponItem);
        }
        else
        {
            rightHandSlot.LoadWeaponModel(weaponItem);
        }
    }
}


플레이어의 모델에 스크립트를 넣어줌

image


PlayerInventory 스크립트

아직은 간단히 WeaponSlotManager를 통해 무기를 장착하는 부분만 구현

public class PlayerInventory : MonoBehaviour
{
    WeaponSlotManager weaponSlotManager;

    public WeaponItem rightWeapon;
    public WeaponItem leftWeapon;

    private void Awake()
    {
        weaponSlotManager = GetComponentInChildren<WeaponSlotManager>();
    }

    private void Start()
    {
        weaponSlotManager.LoadWeaponOnSlot(rightWeapon, false);
        weaponSlotManager.LoadWeaponOnSlot(leftWeapon, true);
    }
}


Player에 스크립트를 넣어주고 만들어둔 Sword 객체를 넣어준다.

image

무기 위치 조정

게임을 실행시키고 무기의 각도와 위치를 조정한다.
이때 먼저 오른손의 무기를 Prefab자체의 Weapon Pivot을 통해 조절한다.

image


이렇게 조정된 값을 복사하여 prefab에 붙여넣고 왼손의 삐뚤어진 부분은 왼손밑의 Hand Override를 통해 수정한다.

image


결과

결과

배운점

  • 무기 장착과 해제를 어떤식으로 하는지 알 수 있었다.
  • 양 손의 무기의 위치와 각도를 맞추는 방법을 알 수 있었다.

댓글남기기