본문 바로가기
Technology/Computer

Unity SO(ScriptableObject)

by re-moon 2024. 12. 26.

ScriptableObject(SO)의 개념

ScriptableObject는 Unity에서 제공하는 데이터 컨테이너로, 메모리에 로드된 상태로 공유 가능하며, 여러 오브젝트나 씬에서 데이터를 재사용할 수 있는 특별한 Unity 클래스입니다.

주요 특징:

  1. 데이터 중심:
    • SO는 데이터를 저장하고 관리하는 데 초점이 맞춰져 있습니다. 행동 로직을 포함하지 않고, 필요한 데이터를 보관해 다른 스크립트나 오브젝트에서 참조할 수 있습니다.
  2. 씬 독립성:
    • 씬에 종속되지 않으므로 씬 간 데이터 공유가 가능합니다.
    • 프로젝트의 Assets 폴더에 파일 형태로 저장되며, 필요할 때 불러와 사용할 수 있습니다.
  3. 메모리 효율성:
    • 여러 오브젝트가 하나의 SO 인스턴스를 참조하기 때문에 메모리 사용량을 줄일 수 있습니다.
  4. 직렬화 지원:
    • Unity의 Inspector 창에서 데이터를 시각적으로 수정할 수 있습니다.
    • 데이터를 Unity의 내장 직렬화 시스템과 쉽게 연결 가능.

SO를 사용하는 것이 좋은 경우

  1. 반복적인 데이터 관리가 필요할 때:
    • 예: 퀘스트 시스템, 아이템 데이터, 스킬 데이터, 적 AI 속성 등.
    • 데이터가 복잡하고, 프로젝트 전역에서 여러 번 재사용될 때 유리합니다.
  2. 씬 간 데이터를 공유해야 할 때:
    • 예: 플레이어 설정, 전역 게임 상태, 씬 로드 간 유지해야 하는 데이터.
  3. UI 설정이나 매개변수가 많을 때:
    • 예: UI 테마 설정, 버튼 텍스트, 색상 팔레트 등.
  4. 데이터를 직관적으로 관리하고 싶을 때:
    • JSON/XML 파일과 비교해 Unity의 Inspector에서 데이터를 바로 수정 가능.
    • 스크립트 없이도 아티스트나 디자이너가 데이터 조작이 가능.
  5. 프리팹 및 오브젝트 간 데이터 공유가 필요할 때:
    • 여러 오브젝트나 프리팹에서 동일한 데이터 집합을 공유하려면 SO가 적합.

SO와 다른 방식의 차이점

방법 특징 사용 사례

ScriptableObject 씬 간 공유 가능. 데이터 중심. Inspector에서 수정 용이. 아이템 데이터, 퀘스트, 전역 설정 값.
MonoBehaviour 게임 오브젝트에 붙여야 함. 씬 내에서만 사용 가능. 캐릭터 동작, UI 인터랙션 등 행동 중심의 로직.
JSON/XML 외부 파일로 저장. 수정하려면 스크립트로 데이터를 로드해야 함. 저장/로드 시스템, 대량의 동적 데이터 관리.
PlayerPrefs 간단한 값 저장 (int, float, string). Inspector와 연결 불가. 사용자 설정 값 (볼륨, 키 설정 등).

SO를 사용하는 방법

1. ScriptableObject 클래스 작성

SO는 ScriptableObject 클래스를 상속받아 작성합니다.

using UnityEngine;

[CreateAssetMenu(fileName = "NewItem", menuName = "Game/Item")]
public class ItemSO : ScriptableObject
{
    public string itemName;
    public int itemID;
    public Sprite icon;
    public string description;
}
  • [CreateAssetMenu]를 사용하면 Assets > Create > Game > Item 메뉴를 통해 SO를 생성할 수 있습니다.
  • SO는 프로젝트 내의 파일로 저장되며, 여러 씬에서 참조 가능.

2. SO를 활용하는 스크립트

SO는 게임 오브젝트의 동작과 데이터를 연결하는 데 사용됩니다.

using UnityEngine;
using UnityEngine.UI;

public class ItemDisplay : MonoBehaviour
{
    public ItemSO itemData; // SO를 참조

    public Text itemNameText;
    public Image itemIcon;

    void Start()
    {
        // SO 데이터를 UI에 표시
        itemNameText.text = itemData.itemName;
        itemIcon.sprite = itemData.icon;
    }
}
  • ItemSO 데이터를 Inspector에서 연결해 사용합니다.
  • 이 코드를 여러 UI 오브젝트에서 재사용 가능하며, 데이터 변경 시 SO만 업데이트하면 됩니다.

SO와 JSON 데이터의 조합

SO를 기반으로 데이터 구조를 설정하고, 외부 JSON 파일을 읽어 SO에 반영하는 방법도 가능합니다. 예를 들어:

JSON 파일 구조

{
    "items": [
        {
            "itemName": "Sword",
            "itemID": 1,
            "description": "A sharp blade."
        },
        {
            "itemName": "Shield",
            "itemID": 2,
            "description": "A sturdy shield."
        }
    ]
}

SO에 JSON 데이터 로드

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

public class ItemLoader : MonoBehaviour
{
    public List<ItemSO> itemTemplates;
    private string jsonFilePath;

    void Start()
    {
        jsonFilePath = Path.Combine(Application.persistentDataPath, "items.json");
        LoadItemsFromJson();
    }

    public void LoadItemsFromJson()
    {
        if (File.Exists(jsonFilePath))
        {
            string jsonData = File.ReadAllText(jsonFilePath);
            ItemDataList itemDataList = JsonUtility.FromJson<ItemDataList>(jsonData);

            for (int i = 0; i < itemDataList.items.Count; i++)
            {
                if (i < itemTemplates.Count)
                {
                    itemTemplates[i].itemName = itemDataList.items[i].itemName;
                    itemTemplates[i].itemID = itemDataList.items[i].itemID;
                    itemTemplates[i].description = itemDataList.items[i].description;
                }
            }
        }
        else
        {
            Debug.LogError("JSON file not found.");
        }
    }
}

[System.Serializable]
public class ItemData
{
    public string itemName;
    public int itemID;
    public string description;
}

[System.Serializable]
public class ItemDataList
{
    public List<ItemData> items;
}

SO의 장점 요약

  • Inspector에서 데이터 시각적으로 관리 가능.
  • 씬 간 데이터 공유와 재사용 용이.
  • 데이터와 로직을 분리하여 유지보수 편리.
  • 메모리 효율적.

SO를 사용할 때 주의할 점

  1. 동시에 여러 곳에서 데이터를 수정하는 경우 충돌 방지:
    • SO 데이터는 참조형이므로, 수정한 내용이 모든 참조된 곳에 반영됩니다.
    • 필요하다면 **복사본(Clone)**을 만들어 작업하세요.
  2. 저장되지 않은 데이터 주의:
    • SO는 에디터 환경에서 파일로 저장해야 데이터를 유지합니다.
    • 런타임에서 수정된 데이터는 저장되지 않으므로, 필요하면 JSON/데이터베이스로 저장하세요.

 

언제 SO를 사용하고, 언제 단순 스크립트를 사용할까?

SO를 사용하는 것이 적합한 경우

  • 씬 관련 데이터가 많을 때:
    • 예: 씬 전환 조건, 설명, 이미지 등.
    • 데이터를 관리하기 위해 SO를 사용하는 것이 유리.
  • 씬 조건이 복잡하거나 UI와 연결되어 있을 때:
    • 예: 잠금 해제 조건이 있거나, 씬을 로드하기 전에 데이터를 확인해야 할 때.
    • SO로 데이터를 관리하면 코드의 복잡성을 줄일 수 있음.
  • 씬 데이터를 여러 곳에서 참조할 때:
    • 예: 씬 전환 UI, 잠금 상태 확인, 씬 미리보기 등에서 동일한 데이터를 참조.

단순 스크립트를 사용하는 것이 적합한 경우

  • 씬 전환이 단순할 때:
    • 예: 씬 이름을 기반으로 바로 이동만 하면 되는 경우.
    • SO를 사용하면 오히려 작업량이 늘어날 수 있음.
  • 프로젝트 규모가 작을 때:
    • 관리할 씬이 몇 개 없고, 복잡한 조건이 필요하지 않은 경우.