Unity

[Unity] ScriptableObject로 데이터 중심 구조 설계

Yangho 2025. 4. 18. 18:16

개요

유니티에서 게임 데이터를 효율적으로 관리하려면, 코드에 하드코딩하는 방식보다 데이터를 외부 에셋으로 분리하는 것이 바람직하다. 특히 캐릭터 능력치, 아이템 정보, 설정값처럼 여러 오브젝트에서 참조되는 값은 ScriptableObject를 사용해 관리하면, 유지보수성과 확장성이 크게 향상된다.

ScriptableObject는 MonoBehaviour와 달리 씬에 존재하지 않고, 독립된 에셋 파일 형태로 프로젝트에 저장되는 데이터 컨테이너다. 유니티 에디터 상에서 생성하고, 다양한 컴포넌트에서 참조할 수 있기 때문에 데이터 중심 설계(Data-Driven Architecture)에 매우 적합하다.

특징

  • 클래스는 반드시 ScriptableObject를 상속받아야 한다.
  • [CreateAssetMenu] 속성을 통해 에디터에서 생성할 수 있는 메뉴 항목을 추가한다.
  • 씬에 존재하지 않고, Project 뷰에서 에셋 파일로 관리된다.
  • 런타임에서도 데이터를 읽고 쓸 수 있으며, 복수의 객체가 동일한 인스턴스를 공유한다.
  • 메모리 효율이 높고, 단일 진실 원천(Single Source of Truth)을 구현할 수 있다.

사용 예시

1. ScriptableObject 클래스 정의

using UnityEngine;

[CreateAssetMenu(fileName = "NewCharacterData", menuName = "GameData/CharacterData")]
public class CharacterData : ScriptableObject
{
    public string characterName;
    public int maxHP;
    public float moveSpeed;
}

2. 캐릭터 오브젝트에서 참조하여 사용

public class Character : MonoBehaviour
{
    public CharacterData data;

    void Start()
    {
        Debug.Log($"이름: {data.characterName}, 체력: {data.maxHP}");
    }
}

이와 같이 에디터에서 CharacterData 에셋을 생성해 Character 오브젝트에 연결하면, 런타임 중에도 일관된 데이터 접근이 가능하다.

장점

  • 데이터 재사용성
    하나의 ScriptableObject를 여러 오브젝트에서 참조하여 중복을 줄일 수 있다.
  • 기획 및 아트 직군과의 협업 효율
    에디터에서 수치나 설정값을 직관적으로 수정할 수 있어, 비개발자도 활용할 수 있다.
  • 런타임 메모리 효율
    여러 인스턴스에 중복 저장되지 않아, 메모리 낭비를 줄일 수 있다.
  • 디버깅과 유지보수 용이
    코드와 데이터가 분리되어 있어, 특정 데이터만 수정해도 전체 게임 구조에 영향을 줄 수 있다.

주의사항

  • 공유 인스턴스의 한계
    런타임 중 ScriptableObject의 값을 수정하면 해당 인스턴스를 참조하는 모든 오브젝트에 영향을 미친다. 게임 상태를 저장하는 용도보다는 설정값, 기본값, 고정 정보에 적합하다.
  • 생성 방식 주의
    new 키워드 대신 ScriptableObject.CreateInstance<T>()로 생성해야 한다.
var temp = ScriptableObject.CreateInstance<CharacterData>();
 
  • 복제 사용 필요 시
    상태를 오브젝트별로 다르게 유지해야 한다면, 런타임 시 ScriptableObject를 복제하거나, MonoBehaviour 방식으로 대체하는 것이 더 적합하다.

마무리

ScriptableObject는 유니티에서 데이터와 로직을 분리하고, 재사용 가능한 구조를 설계하는 데 매우 유용한 기능이다. 특히 스탯, 설정값, 아이템 정보처럼 고정적이고 반복적으로 사용되는 데이터에 적합하며, 에디터 상에서 편리하게 수정할 수 있어 협업 개발 환경에서도 강력한 효율을 발휘한다.

게임 구조를 더 정돈되게 만들고, 유지보수가 쉬운 설계를 고민하고 있다면, ScriptableObject의 도입을 적극 추천한다.