03. ScriptableObject 의 데이터 공유와 관련하여 - gryphus11/ScriptableObject GitHub Wiki

ScriptableObject 의 데이터 공유

    ScriptableObject
  • ScriptableObject

    ScriptableObject 는 Scene, Prefab 이외의 Unity 에디터에서 값을 조정하는 것이 가능한 오브젝트입니다. Unity 에디터 상에서 값을 조정하는 경우, ScriptableObject 와 Scene, Prefab 을 사용하면 쉽게 값의 조정 및 이용이 가능합니다.

      ScriptableObject 는 에셋이며 인스턴스이다.
    • ScriptableObject 는 에셋이며 인스턴스이다.

      ScriptableObject 의 에셋은 [에셋] 인 동시에 [인스턴스] 이기도 합니다. 이는 조금 재미있는 특징을 가집니다. 예를들어, 복수의 Prefab 과 Scene 에서 참조되는 경우에도, 임의로 복제되지 않고 단일 인스턴스로 유지됩니다.

      Scene A 와 Scene B 라는 두개의 Scene 이 있습니다. 각각 OBJ1 과 OBJ2 라고 하는 오브젝트를 가지고 있습니다. 여기서 OBJ1 과 OBJ2 가 같은 ScriptableObject 를 참조하는 경우, OBJ1 과 OBJ2 이 참조하는 ScriptableObject 는 동일한 것 입니다.

      이 구조를 이용하면 Find 나 Static 등을 일절 사용하지 않고 동적으로 컴포넌트와 컴포넌트를 연결할 수 있습니다.

      [일본어] 버튼을 누르면 소리가 나온다... 를, 가능한한 코드를 사용하지 않고 구현

  • 데이터의 공유
  • 데이터의 공유

    마음 먹으면 Static 이나 Singleton 의 대용이 가능하다 생각합니다. 굳이 차이점을 적자면

    • Find 나 Static 을 사용하지 않고 오브젝트를 참조 가능
    • 에디터에서 값을 조정 가능
    • 인스턴스의 파괴가 가능
    • UnityEvent 베이스로 여러가지 가능
    정도일 것 같습니다.

      ScriptableObject 에 를 코드에서 참조
    • ScriptableObject 를 코드에 등록하여 참조

      코드에 ScriptableObject 를 참조하는 멤버를 두어 참조하는 방법

      작성한 코드에 생성한 ScriptableObject 를 등록해 두면 컴포넌트로 등록할 때에 자동으로 참조됩니다.

    • ScriptableObject 를 Resources 로부터 Load
    • ScriptableObject 를 Resources 로부터 Load 한 인스턴스는 1개. 단, AssetBundle은 주의

      Resources 로 부터 불러들인 경우도 동일하게 단일 인스턴스로 다루어 집니다. 예를들어, 서로 다른 코드에서 Resources.Load 로 ScriptableObject 를 로드했지만, 같은 인스턴스이기 때문에 어느 한쪽에서 값을 변경하면 다른쪽의 값도 변경이 됩니다. Resources 로 부터 로드한 인스턴스는 파괴되지 않는 한 동일 이라 알고 있습니다.

    • Find Reference In Scene 으로 ScriptableObject 를 참조하는 오브젝트를 찾을 수 있음
    • Find Reference In Scene 으로 ScriptableObject 를 참조하는 오브젝트를 찾을 수 있음

      Scene 에서 ScriptableObject 에 대한 참조를 가진 에셋을 찾고싶은 경우, Find Reference In Scene 으로 찾을 수 있습니다. 다만, Prefab 화 한 오브젝트가 참조하고 있는 경우, Prefab 에 포함된 모든 오브젝트가 히트되기 때문에 사용에 주의.

  • 데이터의 갱신에 대하여
  • 에디터에서 에셋의 인스턴스의 값을 다시쓰면 파일도 갱신되어 버리는 문제

    에셋의 인스턴스를 사용해 데이터를 공유했지만, 사실 이 방법은 한가지 문제가 있습니다. 에셋의 값을 갱신한다는 것은, 파일도 갱신된다는 것이라는 점입니다. 바꾸어 말하면, Scene 의 재생을 종료해도 수치가 원래대로 돌아가지 않습니다.

    Scene 이 한번 정지되었음에도 불구하고, 다시 재생하면 도중의 수치가 가산되어집니다. 플레이어 에서는 문제가 없지만, 에디터에서 발생하는 문제입니다.

    이것을 회피하기 위한 방법으로는 private 로 [SerializeField] 가 아닌 필드나, 프로퍼티를 사용하여 OnEnable 에서 초기화 수행하는 방식입니다. 자세히 말하자면, ScriptableObject 에 Inspector 표시용의 값(private)과 실제 게임에서 사용하는 값(프로퍼티)의 2종류를 준비해 OnEnable 타이밍에 초기화 합니다.

    다른 방법으로는 ScriptableObject 가 에셋이면서 인스턴스인 점을 이용합니다. 게임의 재생 정지시에 ScriptableObject 를 Unload 해버리면, 재생중에 변경된 값은 없어지게 되어, ScriptableObject 의 값이 파일에 덮어지는 일은 없습니다. 먼저, Scene 의 재생 정지시 자신의 인스턴스를 언로드하는 것과 같은 행동을 가진 ScriptableObject 의 파생클래스를 만듭니다.

    이것을 상속하는 것으로, Scene 재생시에 ScriptableObject 의 값이 최후에 Project Save 한 지점까지 값을 되돌립니다.

⚠️ **GitHub.com Fallback** ⚠️