유니티 데이터 저장 방법 그중에서도 Scriptable Object를 이용해 데이터를 저장하는 방법에 대해 배워보도록 합시다.
게임을 제작할 때 데이터를 저장해야 하는 경우가 생깁니다. 대표적으로 유저의 데이터를 저장하고 불러와야 할 때와 게임에서 사용할 데이터를 저장하고 향후 불러오는 경우가 있겠네요. 오늘은 이 두 가지 경우 중 후자인 게임에서 사용할 리소스 데이터를 형성하여 저장하는 방법에 대해 알아보려고 합니다.
리소스 데이터를 생성하고 저장하는 방법에는 여러가지가 있습니다. 스크립트에 선언하여 저장하는 방법, 외부 파일에 저장하는 방법 등이 있겠죠. 그런데 스크립트에 선언하여 저장하는 방법은 비효율적이고 상당히 불편하며 향후 수정하기 어려운 부분이 있습니다. 때문에 대부분의 경우 외부 파일에 저장하고 스크립트를 통해 해당 데이터를 불러와 메모리에 적재하여 사용하게 되죠.
파일을 통해 리소스 데이터를 불러오는 방식에도 다양한 방식이 있죠. Json , xml파일을 통해 불러오는 방식이 가장 대표적입니다. 하지만 유니티에 존재하는 [Scriptable Object]를 이용하면 손쉽게 데이터를 생성하여 저장하거나 삭제할 수 있죠. 오늘은 이 Scriptable Object의 사용 방법에 대해 알아보려고 합니다.
Scriptable Object를 이용해 유니티 데이터 저장하기
유니티를 실행하고 새로운 C# 스크립트를 생성해줍니다.
//유니티에 메뉴 추가
[CreateAssetMenu(fileName = "ScriptableObjectExample", menuName = "ScriptableObject/ScriptableObjectExample")]
public class ScriptableObjectExample : ScriptableObject //ScriptableObject를 상속
{
public int TestInt = 0;//저장할 데이터 변수
}
이후 위와 같은 코드를 작성해줬습니다. 생성한 스크립트에 ScriptableObject를 상속 받은 뒤 데이터를 저장할 변수를 생성해 주었습니다.
이후 CreateAssetMenu 함수를 이용하여 유니티에서 사용 가능하도록 메뉴를 만들어 주었습니다.
CreateAssetMenu 함수의 fileName 변수가 이 Scriptable Object의 이름이 되고 menuName의 변수로 오브젝트를 생성할 수 있는 메뉴의 경로를 설정해줄 수 있습니다.
위 사진과 같이 Asset 메뉴의 Create 메뉴에서 ‘ScriptableObject/ScriptableObjectExample’을 찾아보실 수 있습니다. 해당 메뉴를 클릭하면 파일이 생성되어 파일 탐색기에 표시되죠.
위 사진처럼 말이죠. 생성된 파일을 클릭해보면 인스펙터에 데이터가 표시됩니다. 표시된 데이터를 수정하여 저장할 수 있죠. 값 한 개만 가능한 것이 아니고 배열을 할당하여 여러 값을 저장하는 것도 가능합니다. 리스트의 ‘+와 -‘ 버튼을 이용해서 데이터를 추가하고 삭제할 수 있습니다.
이렇게 배열을 이용하면 여러 데이터를 Scriptable Object를 이용하여 저장할 수 있습니다. 기본적인 자료형 말고도 만약 자신이 필요한 변수가 할당된 클래스 또한 저장 가능합니다. 예를 들기 위해 클래스 하나를 생성해 보겠습니다.
[Serializable]//클래스를 직렬화하여 데이터를 저장할 수 있도록 만든다.
public class TestClass
{
public int Id;
public int Value;
public float Ratio;
public bool Boolean;
public GameObject Prefab;//게임 오브젝트 혹은
public Sprite Image;//이미지 등의 데이터 또한 저장 가능하다.
}
이렇게 데이터를 저장하기 위한 클래스를 생성할 때는 직렬화를 반드시 해주어야 합니다. 클래스 이름 위에 ‘[Serializable]’을 추가하여 직렬화 시켜줄 수 있죠. 이 상태로 아까 생성한 Scriptable Object를 살짝 수정해줍시다.
//유니티에 메뉴 추가
[CreateAssetMenu(fileName = "ScriptableObjectExample", menuName = "ScriptableObject/ScriptableObjectExample")]
public class ScriptableObjectExample : ScriptableObject //ScriptableObject를 상속
{
public TestClass[] TestInt;//저장할 데이터 변수
}
이렇게 수정한 후 다시 유니티로 돌아가 보도록 하죠.
유니티 인스펙터에 리스트의 ‘+’ 버튼을 클릭하면 새로운 객체가 생성됩니다. 생성된 객체의 데이터를 수정하거나 삭제할 수도 있죠. GameObject나 이미지 등등 다양한 데이터를 저장할 수 있기 때문에 프리팹 등을 호출할 수 있도록 하여 편리하게 사용할 수 있습니다.
저장된 데이터는 파일을 삭제하지 않는 이상 에셋 파일에 저장되어 있기 때문에 수정 및 관리도 간편히 할 수 있죠.
이렇게 Scriptable Object를 이용하여 유니티 에셋 파일로 리소스 데이터를 저장하는 방법에 대해 알아보았습니다. 다음에는 또 다른 리소스 데이터 저장 방법인 Json에 대해 알아보도록 하죠. 그럼 이번 글은 여기서 마치겠습니다.
Scriptable Object에 대한 자세한 내용은 아래 유니티 공식 문서 링크에서 살펴보실 수 있습니다.
Scriptable Object를 사용해서 프린트 하려면 어떤 C# 스크립트를 작성해야 하나요?
ScriptableObject를 사용해서 Debug.Log()를 출력하는 부분을 말씀하시는 것 이라면 MonoBehaviour을 상속받는 스크립트를 생성하고 ScriptableObject를 변수로 가지도록 코드를 작성한 뒤 원하시는 이벤트 함수 부분에서 ScriptableObject의 변수를 참조하여 출력하시면 됩니다.
예제 코드는 아래와 같은 것 같습니다
//데이터 저장 용 ScriptableObject 파일명 : TestScriptable.cs
public class TestScriptable : ScriptableObject
{
//테스트용 변수
public int TestInt = 5;
}
//테스트용 스크립트 파일명 : TestScriptablePrinter.cs
public class TestScriptablePrinter : MonoBehaviour
{
//ScriptableObject 참조
[SerializeField] private TestScriptable _testScriptable;
//이벤트 함수
private void Start()
{
//참조한 ScriptableObject의 변수 출력
Debug.Log(_testScriptable.TestInt);
}
}
다른 스크립트에서 Id의 값을 10으로 정하고 싶은데 어떤 C# 스크립트를 작성해야 하나요?
출력 부분과 마찬가지로 ScriptableObject의 변수를 변경하기 위해서는 참조한 ScriptableObject 클래스에서 값을 수정해 주기만 하면 됩니다. 다만 해당 변경 사항은 유니티의 플레이 버튼을 조작하여 테스트 플레이를 종료하게 되면 날아가게 됩니다.
//데이터 저장 용 ScriptableObject 파일명 : TestScriptable.cs
public class TestScriptable : ScriptableObject
{
//테스트용 변수
public int TestInt = 5;
}
//테스트용 스크립트 파일명 : TestScriptablePrinter.cs
public class TestScriptablePrinter : MonoBehaviour
{
//ScriptableObject 참조
[SerializeField] private TestScriptable _testScriptable;
//이벤트 함수
private void Start()
{
//참조한 ScriptableObject의 변수 변경
_testScriptable.TestInt = 0;
//참조한 ScriptableObject의 변수 출력
Debug.Log(_testScriptable.TestInt);
}
}