Unity - ScriptableObject(스크립터블 오브젝트)

김도현·2023년 9월 10일
0

TIL

목록 보기
36/76

참조 사이트 - 베르의 게임 개발 유튜브
Han님의 블로그

스크립터블 오브젝트란?

유니티내에서 제공하는 데이터 저장소이다. 스크립터블 오브젝트를 사용하면 값의 사본이 생성되는 것을 방지하여 메모리 사용량을 줄일 수 있다. 이를 활용하면 Prefab에 유용하게 사용할 수 있다.
prefab을 일반 변수를 사용하면 변수의 byte(자리값) * 객체수 만큼 메모리를 소모하지만 ScriptableObject를 사용하면 변수의 byte(자리값)만큼만 소모하여 만은 이득을 챙길수 있다.

예시
int를 4자리를 사용하는 prefab이 있다고 할때 이를 객체를 100개 불렀다고 치자 그러면 메모리 소모량은 4 * 4 * 100 = 1600 byte를 소모한다.
하지만 ScriptableObject를 사용하면 4 * 4 = 16 byte를 소모한다.

하지만 단점도 있다.
ScriptableObject는 MonoBehaviour와 달리 게임 오브젝트에 컴포넌트로 부착할 수 없고 프로젝트에 에셋으로 저장된다.

스크립터블 오브젝트 만들기

기초

public class BulletData : ScriptableObject
{

}

MonoBehaviour 대신 ScriptableObject를 상속 받고 있으니 Start()와 Update(), 게임오브젝트를 사용할 수 없다.

값을 저장할 변수 생성

[SerializeField]
private int damage;
public int Damage { get { return damage; } }
[SerializeField]
private float moveSpeed;
public float MoveSpeed { get { return moveSpeed; } }

에셋 메뉴 설정

[CreateAssetMenu(fileName = "Bullet Data", menuName = "Scriptable Object/Bullet Data", order = int.MaxValue)]

CreateAssetMenu 속성은 스크립터블 오브젝트는 스크립트를 이용해서 빠르고 쉽게 에셋을 생성할 수 있게 만들어주는 속성이다.

최종본

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(fileName = "Bullet Data", menuName = "Scriptable Object/Bullet Data", order = int.MaxValue)]
public class BulletData : ScriptableObject
{
    [SerializeField]
    private int damage;
    public int Damage { get { return damage; } }
    [SerializeField]
    private float moveSpeed;
    public float MoveSpeed { get { return moveSpeed; } }
}

자세한 설명

fileName = "Bullet Data" => 이름을 "Bullet Data" 설정한다.
menuName = "Scriptable Object/Bullet Data" => 에셋 생성에 Scriptable Object안에 Bullet Data형태로 만든다.
order = int.MaxValue => 표시순서를 정한다 (int.MaxValue는 맨 뒤에 표시를 설정한다.)

prefab에 적용하기

  1. prefab에 사용될 객체를 만든다.
  2. prefab의 객체를 컨트롤할 스크립트를 만든다.
  3. 스크립트안에 스크립터블 오브젝트 받을 수 있도록 만든다.

    예시
  4. BulletController.cs
[SerializeField]
private BulletData bulletData;
public BulletData BulletData { set { bulletData = value; } }

스크립터블 오브젝트를 코드 또는 인스펙터에서 받을 수 있으면서 값을 확인할 수 있도록 코드를 작성합니다.

GameObject newBullet = Instantiate(bulletPrefab, transform.position, transform.rotation);
newBullet.GetComponent<BulletController>().BulletData = bulletData;

다른 곳에서 스크립터블 오브젝트 설정해줄 때(이를 사용하는 이유는 enum을 활용해 타입을 만들어놓고 타입에 맞는 스크립터블 오브젝트를 할당하여 값을 변경시켜 줄 수 있기 때문이다.)

끝~

0개의 댓글