ScriptableObject란?
ScriptableObject는 Unity에서 제공하는 클래스 타입으로, 데이터를 저장하고 관리하기 위한 *컨테이너이다. 즉, 씬에 독립적으로 존재하며, 여러 오브젝트가 동일한 데이터를 참조해야 할 때 가장 유용하다.
*컨테이너: 데이터를 담아두는 그릇 역할을 하는 구조를 말한다.
공식 문서 정의에 따르면:
ScriptableObject는 프로젝트의 메모리 사용을 줄이고, 데이터의 사본을 생성하는 대신 공용 데이터 자원을 저장하고 여러 객체에서 공유할 수 있도록 설계된 클래스입니다.
1. ScriptableObject 기본 예제
using UnityEngine;
// ScriptableObject 정의
[CreateAssetMenu(fileName = "NewWeapon", menuName = "RPG/Weapon")]
public class WeaponData : ScriptableObject
{
public string weaponName;
public Sprite icon;
public int attackPower;
public int defensePower;
}
CreateAssetMenu 어트리뷰트를 붙이면, Project 창에서 Create -> RPG -> Weapon메뉴가 생긴다. 이것을 선택하면 NewWeapon.asset 파일이 생성되고, Inspector에서 값 입력이 가능해진다.


사용 예시:
public class WeaponUser : MonoBehaviour
{
public WeaponData weaponData;
void Start()
{
Debug.Log($"무기 이름: {weaponData.weaponName}, 공격력: {weaponData.attackPower}");
}
}


이러한 방식으로 Project에 저장된 SO 데이터를 참조할 수 있게 된다.
2. ScriptableObject 사용 이유
- 데이터 공유와 메모리 절약
Prefab에 데이터를 저장하면, Instantiate 할 때마다 값의 복사본이 생기게 된다. 반면 SO는 하나의 데이터 자원만 존재하고, 여러 오브젝트가 같은 것을 참조하게 된다.
ex) 인벤토리에 검이 100개가 있어도, 공격력 = 10 데이터는 SO 1개만 있다. - 씬 독립성
SO는 씬에 묶이지 않으므로, 씬이 바뀌어도 유지가 된다. 때문에 여러 씬에서 공통으로 사용하는 설정값에 적합하다. - 에디터 친화성
SO는 에셋이므로 Project 창에 보관되고, Inspector에서 값 수정이 간단하다. 때문에 비개발자도 프로그래머 도움 없이 데이터를 수정할 수 있어 협업에 도움이 된다.
SO는 단순히 데이터를 담는 클래스 이상으로, Unity에서 데이터 중심 설계(Data-Driven Design)를 가능하게 해주는 핵심 도구이다. 장비나 포션 등의 아이템, 스킬 시스템, 몬스터나 직업 포지션 별 기본 스텟 등 다양한 조건에서 활용이 가능할 것 같다.
using UnityEngine;
[CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/SpawnManagerScriptableObject", order = 1)]
public class SpawnManagerScriptableObject : ScriptableObject
{
public string prefabName;
public int numberOfPrefabsToCreate;
public Vector3[] spawnPoints;
}
using UnityEngine;
public class Spawner : MonoBehaviour
{
// The GameObject to instantiate.
public GameObject entityToSpawn;
// An instance of the ScriptableObject defined above.
public SpawnManagerScriptableObject spawnManagerValues;
// This will be appended to the name of the created entities and increment when each is created.
int instanceNumber = 1;
void Start()
{
SpawnEntities();
}
void SpawnEntities()
{
int currentSpawnPointIndex = 0;
for (int i = 0; i < spawnManagerValues.numberOfPrefabsToCreate; i++)
{
// Creates an instance of the prefab at the current spawn point.
GameObject currentEntity = Instantiate(entityToSpawn, spawnManagerValues.spawnPoints[currentSpawnPointIndex], Quaternion.identity);
// Sets the name of the instantiated entity to be the string defined in the ScriptableObject and then appends it with a unique number.
currentEntity.name = spawnManagerValues.prefabName + instanceNumber;
// Moves to the next spawn point index. If it goes out of range, it wraps back to the start.
currentSpawnPointIndex = (currentSpawnPointIndex + 1) % spawnManagerValues.spawnPoints.Length;
instanceNumber++;
}
}
}
Unity 공식 문서에서는 위와 같은 샘플 코드를 제공해 주었는데, 제공된 SO에는 어떤 프리팹을 몇 개나 어디에 생성할지에 대한 정보가 담겨있었다. 예를 들어 웨이브 기반 게임의 경우, 각 웨이브에 따라 어떤 몬스터를 어디에, 몇 마리씩 스폰해 줄지 규칙을 정해두고, 이를 레벨에 따라 불러오는 기믹에 있어서 해당 SO가 유용할 것처럼 느껴졌다.
SO를 다뤄본 적은 있었지만, 어디까지나 아이템이나 스킬정도가 전부였기에 이런 구조로도 생각해 볼 수 있다는 게 신선했다. 활용 방안이 무궁무진한 것 같아 더 어렵게 느껴지면서도 다양하게 도전해보고 싶은 느낌. 🧐
ScriptableObject - Unity 매뉴얼
ScriptableObject는 클래스 인스턴스와는 별도로 대량의 데이터를 저장하는 데 사용할 수 있는 데이터 컨테이너입니다. ScriptableObject의 주요 사용 사례 중 하나는 값의 사본이 생성되는 것을 방지하
docs.unity3d.com
'Today I Learned > [TIL] Unity' 카테고리의 다른 글
| [Git TIL] 100MB가 넘는 파일을 Git에 업로드 하는 방법 (0) | 2026.01.12 |
|---|---|
| [Unity TIL] - 베지어 곡선 (0) | 2025.12.16 |
| [Unity TIL] - partial (0) | 2025.11.30 |
| [Unity TIL] - TextMeshPro Style Sheet (0) | 2025.10.29 |
| [Unity TIL] - 배경 이미지 스크롤 기능 (0) | 2025.09.09 |