ScriptableObject는 클래스 인스턴스와는 별도로 대량의 데이터를 저장하는 데 사용할 수 있는 데이터 컨테이너이다.
이는 주로 하나의 값의 사본이 무한정 생성되는것을 막아 메모리 사용을 줄이는데 사용된다.
특히 변경 되지 않은 정적인 데이터를 저장하는 프리팹에서 유효하게 사용할 수 있다.
원본이 되는 프리팹에 ScriptableObject를 사용하여 데이터를 저장하면 모든 사본은 이를 공유하고 데이터 변경시 모든 복사본이 이를 공유한다.
에디터를 사용할 시에도 간단히 데이터를 교체하고 편집할 수 있는 장점이 있다.
하지만 뭐든지 저장하고 불러올 수 있지는 않다.
이번에는 ScriptableObject의 유의점을 살펴본다.
public class SOTest : MonoBehaviour
{
public StatSO stat;
[SerializeField] TextMeshProUGUI statName;
[SerializeField] TextMeshProUGUI statValue;
[SerializeField] Button plusButton;
[SerializeField] Button subButton;
[SerializeField] Button resetButton;
void Awake()
{
// 함수 등록
plusButton.onClick.AddListener(Plus);
subButton.onClick.AddListener(Subtract);
resetButton.onClick.AddListener(Reset);
// 값 적용
statName.text = stat.statName;
statValue.text = stat.statValue.ToString();
}
void OnEnable()
{
// 값 적용
statName.text = stat.statName;
statValue.text = stat.statValue.ToString();
}
public void Plus()
{
stat.statValue += 1;
statValue.text = stat.statValue.ToString();
}
public void Subtract()
{
stat.statValue -= 1;
statValue.text = stat.statValue.ToString();
}
public void Reset()
{
stat.statValue = 0;
statValue.text = stat.statValue.ToString();
}
}
위 코드는 단순하게 ScriptableObject의 값을 변경하고 이를 UI에 표시한다.
에디터에서는 변경한 ScriptableObject값이 즉시 변경 되고 플레이를 멈춰도 그대로 저장된다.

그리고 다시 실행하면 변경된 값이 그대로 불러 올 수 있다.

하지만 이를 그대로 빌드 시에서 하면 다르게 적용된다.
값 변경 화면

재시작시 화면

위와 같이 빌드시에는 변경한 ScriptableObject값이 유지 되지 않는다.
그렇기에 빌드시에는 ScriptableObject값을 변경, 저장 용도로는 사용하지 않고 다른 저장 방법을 써야한다.
B씬에서 값 변경

A씬으로 변경

B씬으로 다시 이동

위와 같이 B에서 변경한 ScriptableObject값이 A씬으로 전환하고 다시 B로 전환하였을 때 LUK 데이터가 유지 되지 않았다.
이 이유는 해당 씬에서 LUK ScriptableObject값을 참조하는 객체가 없었기 때문이다.
그렇기에 씬 전환시에는 전환하는 씬에서 해당 ScriptableObject값을 참조하는 객체가 있는지 확인해야한다.
빌드 시에도 씬 전환 시에 참조하는 객체가 없다면 ScriptableObject값은 유지 되지 않는다.
ScriptableObject는 결국 직력화 가능한 데이터 객체이다.
모든 데이터 타입을 저장 할 수 있고 이를 공유할 수 있다는 것은 매우 유용하다.
정적인 데이터를 공유할 경우 손쉽게 에디터에서 수정하고 다른 데이터와 교체할 수 있다.
또한 모든 객체가 참조하므로 값이 변경 될 때 모든 객체를 탐색하여 다시 적용할 필요가 없다는 장점이 있다.
하지만 변경한 데이터를 저장하는 용도로는 적절하지 않다.
데이터를 변경하고 저장하기위해서는 다른 방법을 사용해야한다.
때와 상황에 맞는 방법을 찾아 ScriptableObject를 사용해야 한다.