상세 컨텐츠

본문 제목

인벤토리, 장비

유니티/게임만들기

by MJ_119 2024. 6. 2. 12:57

본문

인벤토리 시스템 - 스크립터블 오브젝트 사용

 

1. 아이템 시스템 구현하기

 

- ItemObject안에 있는 Item 클래스에 있는 buffs(ItemBuff)를 통해 캐릭터에 능력치 변화를 줌.

 

 

 @ ItemBuffer_New 스크립트

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public enum CharacterAttribute
{
    Agility,
    Intellect,
    Stamina,
    Strength
}


[Serializable]
public class ItemBuffer_New
{
    public CharacterAttribute stat;
    public int value;

    [SerializeField] 
    private int min; // 동일한 아이템(단검)이어도 공격력이 1일수가 있고 3일수가 있음, 그 최솟값과 최댓값을 정하기 위한것.

    [SerializeField]
    private int max;

    public int Min => min;
    public int Max => max;

    public ItemBuffer_New(int min, int max)
    {
        this.min = min;
        this.max = max;

        GenerateValue();
    }

    public void GenerateValue()
    {
        value = UnityEngine.Random.Range(min, max);
    }

    public void AddValue(ref int v)
    {
        v += value;
    }
}

 

 

 

 

- 프로퍼티

public int Min => min;
public int Max => max;

 

- min, max의 값을 읽기전용으로 외부에서 접근 가능하게 함. 아래와 동일한 기능을 가진 코드.

public int Min
{
    get { return min; }
}

public int Max
{
    get { return max; }
}

 

 - ref 키워드 : 메서드에 전달(호출)할때 메모리 주소를 전달해서 메소드 내부에서 변수의 값을 변경하면 호출한 쪽의 변수 값도 함께 변경됨.  

int myValue = 10;
AddValue(ref myValue); // myValue의 값이 메서드 내에서 변경됨

public void AddValue(ref int v)
{
    v += value;
}

 - 위의 코드에서 myValue값이 AddValue를 ref키워드를 사용했기때문에 결과값이 10이 아니라 10 + value 값으로 변함.

 

 - 아이템 오브젝트에서 복사해서 아이템 버프를 생성할 때에는 GenerateValue() 을 통해서 min값과 max값 사이에 랜덤한 능력치의 아이템 생성됨.

 

 

 

 

@ 이제 실제로 저장되어 데이터화 되는 item object를 구현해볼것임

item object는 스크립터블 오브젝트에서 상속을 받게 됨.

 

 @ Item_New 스크립트

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

[Serializable]
public class Item_New
{
    public int id = -1; // 아이템을 식별할 수 있는 id 값
    public string name; // 아이템 이름

    public ItemBuffer_New[] buffs; // 여러가지 버프가 있을수 있기 때문에 배열로 정함.

    public Item_New()
    {
        id = -1; // 아이템 id가 -1이면 비어있는 아이템이라는 뜻
        name = "";
    }

    public Item_New(ItemObject_New itemObject)// 아이템 오브젝트를 받아서 아이템 데이터에서 이 아이템을 새로 복사해서 생성한다는 생성자
    {
        name = itemObject.name;
        id = itemObject.data.id;

        buffs = new ItemBuffer_New[itemObject.data.buffs.Length];

        for (int i = 0; i < buffs.Length; i++)
        {
            buffs[i] = new ItemBuffer_New(itemObject.data.buffs[i].Min, itemObject.data.buffs[i].Max)
            {
                stat = itemObject.data.buffs[i].stat
            };
            
        }

    }
}

 

 

 

@ ItemObject_New 스크립트

using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using UnityEngine;

public enum ItemType_New : int
{
    Helmet = 0,
    Chest = 1,
    Pants = 2,
    Boots = 3,
    Pauldrons = 4,
    Gloves = 5,
    LeftWeapon = 6,
    RightWeapon = 7,
    Food,
    Default,
}


[CreateAssetMenu(fileName = "New Item", menuName = "Inventory System/Items/New Item")]
public class ItemObject_New : ScriptableObject
{
    public ItemType_New type; // 아이템 타입 정의
    public bool stackable; // 물약과 같이 겹쳐서 표시될 수 있는 아이템을 의미 

    public Sprite icon;
    public GameObject modelPrefab; // 캐릭터에게 부착되거나 같이 표시되어야 할 3D 오브젝트들을 의미

    public Item_New data = new Item_New();

    public List<string> boneNames = new List<string>(); // 캐릭터 조합 시스템에서 사용되는 변수

    [TextArea(15, 20)]
    public string description;

    private void OnValidate() // OnValidate() : 데이터를 변경하게 되면 호출되는 함수
    {
        boneNames.Clear();

        if(modelPrefab == null || modelPrefab.GetComponentInChildren<SkinnedMeshRenderer>() == null)
        {
            return;
        }

        SkinnedMeshRenderer renderer = modelPrefab.GetComponentInChildren<SkinnedMeshRenderer>();
        Transform[] bones = renderer.bones;

        foreach (Transform t in bones)
        {
            boneNames.Add(t.name);
        }
    }

    public Item_New CreateItem() // 아이템을 추가, 생성해서 변환하는 함수
    {
        Item_New newItem = new Item_New(this);
        return newItem;
    }


}

 

 

스킨 렌더러가 존재한다면 이 렌더러에서 트랜스폼 bones를 가져옮.

 

@ ItemObjectDataBase_New 스크립트

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(fileName = "New Item DataBase_New", menuName = "Inventory System/Items/DataBase_New")]
public class ItemObjectDataBase_New : ScriptableObject
{
    public ItemObject_New[] itemObjects;

    public void OnValidate()
    {
        for (int i = 0; i < itemObjects.Length; i++) // 아이템을 생성한다음 id를 일일히 넣어주기 귀찮으니까 for문을 사용해서 일률적으로 id 값을 넣어줌.
        {
            itemObjects[i].data.id = i;
        }
    }
}

 

 

 

2. 인벤토리 시스템 구현하기

 

 - 인벤토리 슬롯(InventorySlot)에서 아이템이 추가,삭제 될때마다 갱신 메세지를 발생시켜 액션들로 관리하고, 또 이 슬롯에 아이템 타입을 지정해서 지정된 아이템만 위치할 수 있도록 기능 구현.

 

 - 인벤토리(Inventory) : 인벤토리 슬롯들을 리스트화 해서 관리함, 인벤토리 UI와 연결되는 부분

 

 

 - 인벤토리 슬롯 구현

 

 

 

3. 인벤토리 UI 구현하기

 

 

- 인벤토리UI는 기본적으로 마우스 입력이 가장 중요하기에 이벤트 트리거를 반드시 게임 오브젝트에 컴포넌트로 추가되어 있어야 함.

[RequireComponent()] : 이 스크립트를 오브젝트에 넣으면 게임 오브젝트에 EventTrigger가 자동으로 추가됨. *누락 방지

 

 

 

 

4. 캐릭터 장비 교체 구현하기

 

5. 아이템 획득 & 사용 구현하기

관련글 더보기