
디자인 패턴 중 플라이웨이트 패턴으로 구현된 기능이다. 미리 지정된 데이터들을 가지고 프리팹화 할 수 있다
스크립터블 오브젝트(Scriptable Object)는 데이터와 코드를 분리하기 유용한 기능. 프로그램 관리에 있어 데이터와 코드를 분리함으로써 편해진다MonoBehaviour 스크립트가 아닌 별도의 오브젝트로 관리할 수 있게 한다ScriptableObject 클래스를 상속 받아 틀을 작성한다[CreateAssetMenu(fileName = "생성시 파일명", menuName = "분류명/선택지 명")]
HP 포션을 주워서 인벤토리에 저장하고, 사용하면 체력을 회복할 수 있게 구현해보자스크립터블 오브젝트를 에디터 상에서 추가할 수 있게 만들어본다ScriptableObject를 상속받는 클래스를 작성한다스크립터블 오브젝트로 만들 수 있다public abstract class ItemData : ScriptableObject
{
// 아이템 이름
public string Name;
// 아이템 설명
[TextArea] public string Description;
// 아이템 아이콘
public Sprite Icon;
// 아이템 3D 프리팹
public GameObject Prefab;
// 사용: 자식 클래스에서 구체화
public abstract void Use(PlayerController controller);
}
스크립터블 오브젝트를 게임 오브젝트와 연결해 줄 프리팹의 스크립트다. 삭제 조건 또한 여기서 가진다public class ItemObject : MonoBehaviour
{
[field: SerializeField] public ItemData Data { get; private set; }
private GameObject _childObject;
private void OnEnable()
{
_childObject = Instantiate(Data.Prefab, transform);
}
private void OnDisable()
{
Destroy(_childObject);
}
}

씬 창에 빈 오브젝트를 만들고, 스크립트를 추가, 콜라이더도 추가한다(원하는 크기로 추가)public class PlayerController : MonoBehaviour
{
[SerializeField] private int _hp;
private Inventory _inventory;
private void Awake() => Init();
private void OnTriggerEnter(Collider other)
{
// 충돌한게 아이템이 맞는지는 당연히 체크해야됩니다.
_inventory.GetItem(other.GetComponent<ItemObject>().Data);
other.gameObject.SetActive(false);
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
_inventory.UseItem(0);
}
}
private void Init()
{
_inventory = GetComponent<Inventory>();
}
public void Recover(int value)
{
_hp += value;
}
}
hp, 아이템들을 저장할 inventory를 필드로 가진다public class Inventory : MonoBehaviour
{
[SerializeField] private List<ItemData> _slots = new();
private PlayerController _controller;
private void Awake() => Init();
private void Init()
{
_controller = GetComponent<PlayerController>();
}
public void GetItem(ItemData itemData)
{
_slots.Add(itemData);
}
public void UseItem(int index)
{
_slots[index].Use(_controller);
_slots.RemoveAt(index);
}
}
ItemData를 저장하기 위한 리스트로 인벤토리를 구현한다index가 무조건 0이 들어오기 때문에, 인벤토리에 들어온 순서대로 사용된다[CreateAssetMenu(fileName = "Hp Potion", menuName = "Scriptable Objects/Hp Potion", order = 1)]
public class HpPotion : ItemData
{
public int Value;
public override void Use(PlayerController controller)
{
controller.Recover(Value);
}
}
어트리뷰트를 추가해, 프로젝트 창에서 새로운 스크립터블 오브젝트로 추가할 수 있다. MonoBehaviour를 상속받지 않는 스크립트다ItemData를 상속 받아서 ScriptableObject 또한 상속받는다override로 추상 함수 Use()를 구현했다. PlayerController 형을 매개변수로 받아서 체력을 회복시킨다
프로젝트 창에서 위와 같이 새로 생성할 수 있다
fileName과 같이 기본 값은 Hp Potion으로 나온다

Name, Description, Value를 설정한다Cube를 씬 창에서 만들고 프리팹 화 후, 위 사진처럼 Prefab에 참조시킨다

ItemObject 프리팹을 먼저 원하는 위치에 배치한다
스크립터블 오브젝트를 참조시킨다


인벤토리에 들어간 것이다
인벤토리에 들어간 것을 확인할 수 있다PlayerController 스크립트에서 설정한 것과 같이 마우스 왼쪽 클릭을 누르면 사용한다스크립터블 오브젝트는 다양한 분야에서 활용할 수 있다게임 기획자들이 프로그래머에게 기능이나 게임 오브젝트의 구현을 요구하는 것이 스크립터블 오브젝트 형태로 제공될 수 있다. 만들어 주면, 기획자들이 원하는 대로 데이터를 고칠 수 있어서 협업이 원활해진다퀘스트를 구현할 수도 있다. 이벤트 처리를 해서 , 요구 몬스터 처치 수의 경우 -> 플레이어가 처치할 때마다 카운팅, 요구 아이템 수의 경우 -> 플레이어가 아이템을 얻고, 쓰거나 버릴 때마다 카운팅하여 처리할 수 있다스킬 구현도 가능하다. 필드 습득이나, 오브젝트로 존재시키고 싶을 때 사용할 수 있다아이템들을 스크립터블 오브젝트로 만드는 경우, 장비 아이템들을 필드에 떨어져 있는 경우 등을 생각하면 편하다