Unity & C#/Scripting

Data based structure - ScriptableObject

coucou3 2020. 11. 6. 00:09
반응형

ScriptableObject

ScriptableObject는 클래스 인스턴스와는 별도로 대량의 데이터를 저장하는 데 사용할 수 있는 데이터 컨테이너입니다. ScriptableObject의 주요 사용 사례는 값의 사본이 생성되는 것을 방지하여 프로젝트의 메모리 사용을 줄이는 것입니다. 이는 첨부된 MonoBehaviour 스크립트에 변경되지 않는 데이터를 저장하는 프리팹이 있는 프로젝트의 경우 유용합니다.

이러한 프리팹을 인스턴스화할 때마다 프리팹에 이 데이터의 자체 사본이 생성되는데, 이와 같은 방법을 사용하여 중복 데이터를 저장하는 대신 ScriptableObject를 이용하여 데이터를 저장한 다음 모든 프리팹의 레퍼런스를 통해 액세스할 수 있습니다. 즉, 메모리에 데이터 사본을 하나만 저장합니다.
 

ScriptableObject - Unity 매뉴얼

ScriptableObject는 클래스 인스턴스와는 별도로 대량의 데이터를 저장하는 데 사용할 수 있는 데이터 컨테이너입니다. ScriptableObject의 주요 사용 사례는 값의 사본이 생성되는 것을 방지하여 프로젝

docs.unity3d.com

 

ScriptableObject를 이용하여 미리 저장된 Data를 활용한 구조를 만들어보자.

아래는 여러 종류의 건물이 각각의 자원을 일정 시간마다 생산하는 예시이다.

 

 

# BuildingTypeSO.cs

[CreateAssetMenu(menuName = "ScriptableObjects/BuildingType")]
public class BuildingTypeSO : ScriptableObject
{
    public string nameString;		// 건물의 이름
    public Transform prefab;		// 생성할 프리팹
}

건물의 데이터를 갖고있는 ScriptableObject다.

 

StoneHarvester와 WoodHarvester 두 종류의 건물을 ScriptableObject로 만들었다.

Wood 빌딩의 ScriptableObject

 

 

# BuildingTypeListSO.cs

[CreateAssetMenu(menuName = "ScriptableObjects/BuildingTypeList")]
public class BuildingTypeListSO : ScriptableObject
{
    public List<BuildingTypeSO> list;    
}

BuildingTypeSO를 List로 갖고 있는 SciprtableObject를 만든다.

 

BuildingTypeListSO ScriptableObject를 생성하고, 리스트에 건물 ScriptableObject(BuildingTypeSO)를 넣어준다.

BuildingTypeSO 리스트를 갖고 있는 ScriptableObject

 

 

# BuildingManager.cs

public class BuildingManager : MonoBehaviour
{
    private Camera mainCamera;
    private BuildingTypeSO buildingType;
    private BuildingTypeListSO buildingTypeList;
    
    private void Awake()
    {
        // BuildingTypeListSO 클래스 이름 자체를 파일 이름으로 사용한다.
        buildingTypeList = Resources.Load<BuildingTypeList>(nameof(BuildingTypeListSO));
        buildingType = buildingTypeList.list[0];
    }
    
    private void Start()
    {
        mainCamera = Camera.main;
    }
    
    private void Update()
    {
        // 마우스 클릭 위치에 건물 생성
        if (Input.GetMouseButtonDown(0))
        {
            Instantiate(buildType.prefab, GetMouseWorldPosition(), Quaternion.identity);
        }
        
        if (Input.GetKeyDown(KeyCode.Alpha0)
        {
            buildingType = buildingTypeList.list[0];
        }
        
        if (Input.GetKeyDown(KeyCode.Alpha1)
        {
            buildingType = buildingTypeList.list[1];
        }
    }
    
    private Vector3 GetMouseWorldPosition()
    {
        var mouseWorldPosition = mainCamera.ScreenToWorldPosition(Input.mousePosition);
        mouseWorldPosition.z = 0;
        
        return mouseWorldPosition;
    }
}

BulidingTypeListSO ScriptableObject에 접근하기 위해 해당 파일을 Resources 경로에 두고, 파일 이름을 Class 이름과 동일하게 지정한다. (단순 string 값을 파일 경로로 사용했을 때 발생할 수 있는 문제를 방지하는 용도)

 

이제 BuildingManager에서 buildingType만 바꾸어주면 그에 맞는 GameObject를 생성할 수 있다.

또한 새로운 Building을 추가하려면 BuildingTypeSO ScriptableObject만 만들어 넣어주면 된다.

 

ScriptableObject는 GameObject에 붙어있어야하는 MonoBehaviour 스크립트와 달리 독립적으로 데이터를 저장할 수 있다. 때문에 위와 같이 ScriptableObject를 이용한 데이터 기반 구조는 유지 보수가 쉬워진다.

 

반응형