본문 바로가기
TIL

[Unity] ScriptableObject

by vvin39 2025. 5. 23.

내일배움캠프 33일차 TIL

ScriptableObject는 Unity에서 데이터 중심 설계(Data-Driven Design) 를 할 수 있게 해주는 아주 유용한 기능이다.
특히 
게임 밸런스 데이터, 아이템 정보, 스킬 설정, 몬스터 스탯 등을 따로 관리할 때 정말 많이 사용할 수 있다.

 

📌 ScriptableObject란?

ScriptableObject는 Unity에서 MonoBehaviour와는 다르게 씬에 존재하지 않고, 에셋 파일로 저장할 수 있는 데이터 컨테이너이다. 클래스지만 GameObject에 붙이지 않고 씬의 오브젝트와는 독립적으로 존재한다.
인스펙터에서 데이터를 저장하고 재사용 가능하고, 메모리 효율 좋고, 유지보수 용이하다.

 

왜 사용할까?

이유  설명
재사용성 여러 오브젝트가 동일 데이터를 공유 가능
직렬화 인스펙터에서 값을 편집 가능
독립성 씬에 의존하지 않음 (씬 간 공유 가능)
퍼포먼스 GameObject를 생성하지 않아서 메모리 효율이 좋음
구조화 데이터와 로직 분리를 통해 코드가 더 깔끔해짐

 

ScriptableObject 기본 구조

using UnityEngine;

[CreateAssetMenu(fileName = "NewItemData", menuName = "Item/ItemData")]
public class ItemData : ScriptableObject
{
    public string itemName;
    public int damage;
    public Sprite icon;
}

 

📌 사용 예제: 무기 데이터 만들기

1. WeaponData.cs

using UnityEngine;

[CreateAssetMenu(fileName = "NewWeapon", menuName = "ScriptableObjects/WeaponData")]
public class WeaponData : ScriptableObject
{
    public string weaponName;
    public int attackPower;
    public float range;
    public Sprite icon;
}

2. 에셋 생성

  • Unity 에디터에서 Project 창 → 우클릭 → Create → ScriptableObjects → WeaponData
  • 여러 개의 무기 데이터를 각각 생성 가능

 

 

3. 무기를 사용하는 컴포넌트

using UnityEngine;

public class Weapon : MonoBehaviour
{
    public WeaponData data;

    void Start()
    {
        Debug.Log($"무기 이름: {data.weaponName}, 공격력: {data.attackPower}");
    }
}

여러 무기 오브젝트가 같은 WeaponData를 공유하면 일괄 수정도 쉬워진다.

 

언제 쓰면 좋은가?

상황  ScriptableObject 추천
아이템 데이터 관리
스킬/스탯/능력치 관리
퀘스트 정보 저장
전역 설정, 게임 규칙
저장/불러오기 용 ❌ (PlayerPrefs, JSON 추천)
씬에 존재하는 개별 객체의 고유 상태 ❌ (MonoBehaviour 추천)

 

장점과 주의사항

장점

  • 데이터 중심 설계 가능
  • 코드와 데이터 분리
  • 유지보수, 테스트 편리
  • 퍼포먼스 유리 (GameObject 생성 없음)

주의점

  • ScriptableObject는 참조형이라 공유된 값이 동시에 바뀔 수 있음 (런타임에 조작 시 주의)
  • 게임 플레이 중 값을 바꾸고 저장하려면 직렬화 시스템 또는 별도 저장 방식 필요
  • 에디터에서만 생성 가능, 런타임 생성은 복잡함

 

고급 활용

게임 설정 데이터

[CreateAssetMenu(menuName = "Settings/GameConfig")]
public class GameConfig : ScriptableObject
{
    public float enemySpawnRate;
    public int maxEnemies;
}

게임 밸런스 조정 시 게임 종료 후 수치만 바꿔서 테스트 가능!

 

상태 기반 시스템 (State Pattern + ScriptableObject)

  • 상태(State)나 전략(Strategy)을 ScriptableObject로 만들어 코드 분기 없이 사용 가능

 

결론

항목  설명
무엇인가? 에셋으로 저장 가능한 데이터 객체
왜 쓰나? 코드와 데이터를 분리하여 재사용, 유지보수, 퍼포먼스에 유리
언제 쓰나? 게임 내 반복되는 데이터 구조를 효율적으로 관리할 때
주의할 점 참조 기반이라 런타임에서 값 수정 시 주의 필요

 

 

 

 

 

최근댓글

최근글

skin by © 2024 ttuttak