Scriptable Object란?

데이터를 담는 Unity 전용 Asset이다. 주로 Prefab을 쉽게 관리하기 위해 쓰인다. 그러나 이렇게만 보면 어떻게 사용해야 하는지 도무지 감이 잡히지 않을 것이다. 필자도 처음에는 그랬기 때문에, 예시를 들면서 진행하겠다.


예시 상황

여러 가지 Projectile을 만들고 싶다. 그래서 Projectile 클래스를 만들었다.

 

보통의 경우, 이 시점에서 두 가지 방법을 사용하여 다양한 Projectile을 만들 수 있다.

  1. 이 Projectile 클래스를 상속하여 Wooden Arrow와 Iron Arrow 클래스를 만든다. 그렇게 상속을 통해 만들어진 클래스들을 각각의 GameObject에 붙인 뒤, Prefab으로 만든다.
  2. 또는? Projectile 클래스에 damage, speed, gravity와 같은 필드 변수를 public 또는 [SerializedField] & private으로 만든다. 그 후, Inspector 창에서 수치를 직접 조절한 뒤, Prefab으로 만든다. 

보통의 경우에는 위의 두 가지 방법이 매우 효과적인 해결책이 될 수 있다. 그러나 Scriptable Object를 알고 있는 사람의 관점에서는 그렇지 않다. 왜냐하면, Scriptable Object는 "변하는 데이터만 담아두는" Asset이기 때문이다.


Scriptable Object로 구현한 Projectile을 위한 데이터

using UnityEngine;

public enum ElementalType
{
    None,
    Fire,
    Ice,
    Spark
}

[CreateAssetMenu(fileName = "New Projectile Data", menuName = "Projectile Data")]
public class ProjectileData : ScriptableObject
{
    public Sprite texture;
    public float damage;
    public Vector2 direction;
    public float speed;
    public float gravity;
    public ElementalType elemental_type; 
}

 

위와 같은 코드를 쓴 뒤, 아래 사진과 같이 조작하면 "Projectile을 위한 Data Asset(=Projectile Data)"을 만들 수 있다;

Projectile Data 생성!

 

그 후, 각각의 데이터를 아래 사진과 같이 잘 적어내려가면 된다.

참고로 Enum을 쓰면 elemental type을 매우 편하게 설정할 수 있다!


Projectile 클래스

using UnityEngine;

public class Projectile : MonoBehaviour
{
    private Rigidbody2D rb;
    private SpriteRenderer sr;

    private float damage;
    private Vector2 direction;
    private float speed;
    private float gravity;

    [SerializeField] private ProjectileData projectile_data;

    private void Awake()
    {
        GetComponents();
        GetData();
    }

    private void Start()
    {
        rb.linearVelocity = direction.normalized * speed;
        rb.gravityScale = gravity;
    }

    private void FixedUpdate()
    {
        transform.right = rb.linearVelocity.normalized;
    }

    private void GetComponents()
    {
        rb = GetComponent<Rigidbody2D>();
        sr = GetComponent<SpriteRenderer>();
    }

    private void GetData()
    {
        sr.sprite = projectile_data.texture;
        damage = projectile_data.damage;
        direction = projectile_data.direction;
        speed = projectile_data.speed;
        gravity = projectile_data.gravity;
    }

    private void OnBecameInvisible()
    {
        Destroy(gameObject);
    }
}

 

빈 GameObject를 생성한 뒤, Sprite Renderer, Projectile (Script), Rigidbody 2D 컴포넌트를 달아주자. 이름은 Projectile로 해주자. 그 후, 이렇게 만든 Projectile Script에 Projectile Data를 Inspector 창을 통해 넣어주면 된다.


간단한 Preview

Trail은 자연스럽게 보이도록 넣었다!

 

이제 이렇게 만든 Projectile을 Prefab으로 만든 뒤에, Instantiator를 만들어주면 "매우 쉽고 편하게" 다양한 종류의 Projectile을 만들 수 있다!


읽어주셔서 감사합니다!

궁금한 점이 있다면 댓글로 문의주세요!

+ Recent posts