Unity ScriptableObject

 ScriptableObject란

  • ScriptableObject는 클래스 인스턴스와는 별도로 대량의 데이터를 저장하는 데 사용할 수 있는 데이터 컨테이너입니다.

ScriptableObject를 쓰는 이유는 다음과 같습니다.

기존 클래스는 내부 변수 하나 당 4Byte가 듭니다(변수에 따라 다름) .

총 4개의 변수가 사용된다 가정할 때, 4X4 = 16Byte가 메모리에 사용되게 됩니다. 만약 좀비라는 몬스터 프리팹이 1000마리를 일반클래스의 변수로 구현했다면 16 X 1000 = 16000Byte(16KB)가 메모리에 사용되게 됩니다.

16KB는 큰 값은 아니지만, 추후 변수가 추가됨에 따라 점점 메모리 소모량이 많아질 것입니다.

하지만, 스크립터블 오브젝트를 사용하면 좀비를 몇 백마리 사용하든 메모리의 스크립터블 오브젝트의 데이터 원본만을 저장하고 이것을 참조하는 방식으로 작동해서 16Byte만 메모리 소모가 됩니다. 즉, 메모리의 소모를 줄일 수 있게 됩니다.

 

 


스크립터블 오브젝트 생성 스크립트

  • MonsterData.cs
[CreateAssetMenu(fileName = "MonsterData", menuName = "MonsterScriptable/CreateMonsterData", order = int.MaxValue)]
public class MonsterData: ScriptableObject
{
	[SerializeField]
	private int hp; //4Byte
	public int HP  { get { return hp; } }
	[SerializeField]
	private string monsterName; //참조형이라 그때그때 크기 달라짐
	public string Name { get { return monsterName; } }

	[SerializeField]
	private float speed; //4Byte
	public float Speed { get { return speed; } }
}

💡 CreateAssetMenu 속성에 대해서는 아래 포스팅을 참고해주세요.

 

유니티 CreateAssetMenu에 대하여

CreateAssetMenu란? CreateAssetMenu는 특정 스크립트에서 새로운 어셋을 생성할 수 있는 메뉴 옵션을 제공해줍니다. 이를 통해 사용자가 유니티 에디터의 메뉴를 통해 쉽게 새로운 인스턴스를 만들 수

wlsdn629.tistory.com

 


 에디터에서 ScriptableObject 생성하기

 

[Create] - [MonsterScriptable/CreateMonsterData] 가 있는지 확인
ScriptableObject

MonsterData.cs 를 저장한 후, 에디터로 돌아가서 프로젝트 빈 공간을 우클릭 후, 에셋의 이름이 FileName으로 설정한 Monster Data로 잘 생성되는 것을 볼 수 있습니다.

 

테스트를 위해 생성된 에셋의 이름을 Normal로 바꿔준 후 Ctrl+D를 눌러 2개 더 생성해준 다음 이름을 변경해줍니다.

마지막으로, 인스펙터창에서 Hp, Monster Name, Speed 값을 설정해줍니다.


 

MonsterData에셋을 참조할 Monster 생성하기

  • Monster.cs
public class Monster : MonoBehaviour
{
	[SerializeField]
	MonsterData monsterData;
	public MonsterData MonsterData { set { monsterData = value; } }

	public void WatchMonsterInfo()
	{
	    Debug.Log(monsterData.Name);
	    Debug.Log(monsterData.HP);
	    Debug.Log(monsterData.Speed);
	}
}

Monster

 

테스트를 위해 빈오브젝트를 하나 생성하고 Monster라고 이름을 바꿔준 후, Monster스크립트를 부착시켜줍니다.

그 다음, 해당 오브젝트를 프리팹으로 만들고 하이러키창에서 삭제해줍니다.

 


Monster 소환 스크립트

  • SpawnMonster
using UnityEngine;

public class SpawnMonster : MonoBehaviour
{
	public enum MonsterType { Normal, Tanker, Speeder};
	public List<MonsterData> MonsterDatas = new List<MonsterData>();

	public GameObject monsterPrefab;

	private void Start()
	{
	    SpawnMonsterObject();
	}

	public void SpawnMonsterObject()
	{
	    for (int i = 0; i < MonsterDatas.Count; i++)
	    {
	        var monster = SpawnMonsterFunc((MonsterType)i);
	        monster.WatchMonsterInfo();
	    }
	}

	public Monster SpawnMonsterFunc(MonsterType type)
	{
	    var newMonster = Instantiate(monsterPrefab).GetComponent<Monster>();
	    newMonster.MonsterData = MonsterDatas[(int)(type)];
	    return newMonster;
	}
}

 

MonsterDatas List에는 아까 생성한 Monster(ScriptableObject)을 집어 넣어주면 됩니다.

주의) 리스트 순서는 Enum순서에 맞게 설정해줘야 합니다.

 

MonsterPrefab에도 아까 만들어둔 프리팹을 넣어줍니다.

 


 

 

마지막 테스트 단계

결과 / 조직도

 

Monster Data(ScriptableObject) 에셋에서 설정한 값들이 잘나오는 것을 확인할 수 있습니다.

 

Monster 오브젝트는 MonsterData(ScriptableObject) 에셋으로 부터 데이터를 받는 관계이며,

Monster 오브젝트는 SpawnManager를 통해 소환되는 구조를 갖고 있습니다.