오토로드 대 내장 노드

다른 엔진에서는 전역으로 접근 가능할 개체에 다양한 기능을 구성하는 "관리자" 클래스를 만들어 쓰는 것을 권장할 지도 모릅니다. Godot는 이러한 객체의 크기를 줄이는 방식을 지원하는 것으로 커집니다. 대신 내용물을 가능한 한 개별 노드로 이동시킵니다.

예를 들어, 한 개발자가 플랫포머 게임을 제작하면서 동전을 먹을 때 음향 효과가 나게 하려면 어떻게 해야 할까요? 글쎄요, 이를 위한 노드가 있습니다: AudioStreamPlayer. 하지만 소리가 재생되고 있는 도중 AudioStreamPlayer를 "재생(play)"하면, 새로운 소리는 첫 번째 소리가 끝나기 전에 재생하면서 방해가 된다는 것을, 테스트를 하면서 알게 됩니다.

사용자는 SoundManager 오토로드 노드를 만들어 더 똑똑한 전체 시스템을 만드는 것이 최선의 해결책이라고 생각하는 경향이 있습니다. 이것은 새로운 음향 효과 요청이 들어올 때마다 순환하는 AudioStreamPlayer들의 풀(Pool)을 만들어냅니다. 그런 다음 SoundManager를 오토로드로 만들어 어디서든 SFX.play("coin_pickup.ogg")를 가지고 접근하도록 합니다. 사용자는 거의 알지 못했습니다, 자신이 많은 복잡한 문제를 코드로 가지고 왔습니다.

  • 전역 상태: 한 객체가 이제 모든 객체의 데이터를 담당합니다. SFX가 오류가 발생하거나 AudioStreamPlayer를 사용할 수 없다면, 전부 망가집니다.
  • 전역 접근: 이제 모든 객체가 어디서든 SFX.play(sound_path)를 호출할 수 있습니다, SFX 버그가 어디서 시작했는 지를 아는 쉬운 방법은 더 이상 없습니다.
  • 전역 리소스 할당: 모든 객체의 데이터와 처리가 처음부터 중앙 집중화 된다면, 다음 중 하나를 거쳐야 합니다...
    1. 결함있는 행동으로 이어질 수 있는 자원을 과소 할당하게 됩니다.
      • 예: 객체 풀에 AudioStreamPlayer가 너무 적게 있습니다. 소리가 재생되지 않거나 다른 소리를 방해할 수 있습니다.
    2. 과다 할당한 리소스로 필요보다 많은 메모리/처리를 사용합니다.
      • 예: 임의로 많은 수의 AudioStreamPlayer가 있습니다, 이들 중 대부분이 휴식 상태이고 아무 것도 하지 않습니다.
    3. AudioStreamPlayer이 필요한 각 객체마다 얼마나 많이, 그리고 어떤 소리가 필요한지 등록하게 됩니다. 이것은 제 3자를 사용하는 목적을 없애버립니다; 이제 소리는 자식 노드처럼 각 객체에 연결되어버립니다. 누군가는 여기에 불필요한 중개자를 추가합니다.

이것과 반대로 각 씬이 필요한 만큼의 AudioStreamPlayer 노드를 유지하면 이 문제는 사라집니다.

  • 각 씬은 자체적인 상태 정보를 관리합니다. 데이터에 문제가 생기면, 해당 데이터가 있는 씬 내에서만 사고를 일으킵니다.
  • 각 씬은 자체 노드에만 접근합니다. 이제 버그가 나타나면 (아마 씬의 루트 노드이겠지만) 어떤 노드에 책임이 있는 지를 추적하기 쉬워지고, 코드에서 문제가 되는 호출 (주어진 코드를 참조하는 코드가 위치한 곳)을 훨씬 더 쉽게 찾을 수 있습니다.
  • 각 씬은 실행하기 위해 얼마나 많은 리소스가 필요한지 확실하게 압니다. 정보 부족으로 인한 메모리나 처리의 낭비가 없습니다.

오토로드의 일반적인 정당성은 이런 것입니다, "나는 여러 씬에 많은 노드가 있는 X들을 갖고 있습니다, 그리고 각 씬이 X를 갖고 있도록 하고 싶습니다."

X가 함수라면, 각 씬이나 노드 하위 트리에 기능을 제공하는 Node의 새로운 타입을 만드는 것으로 해결합니다.

X가 데이터라면, 해결 방법은 두 가지로, 1) Resource의 새로운 타입을 만들어 데이터를 공유하거나, 2) 각 노드가 접근할 수 있는 객체에 데이터를 저장하는 것입니다 (예를 들어 씬이 있는 노드는 get_owner()를 사용하여 씬 루트를 가져올 수 있습니다).

그러면 언제 오토로드를 사용해야 할까요?

  • 정적 데이터: 클래스에 반드시 연관되어야 하는 (그래서 오직 하나의 데이터 사본만 있는) 정적 데이터가 필요하다면, 오토로드가 좋은 기회입니다. 정적 데이터는 Godot의 스크립팅 API에 존재하지 않기 때문에, 오토로드 싱글톤이 차선책이 됩니다. 클래스를 오토로드로 생성하고, 씬 내에서 클래스의 사본을 생성하지 않는다면, 그것은 형식적인 싱글톤 API를 대신할 것입니다.
  • 편의: 오토로드된 노드는 GDScript에 그들의 이름으로 된 전역 변수를 갖습니다. 이것은 항상 존재해야 하지만 객체 인스턴스 정보가 필요한 객체를 정의하는 데 매우 편리합니다. 대안은 네임스페이스 스크립트를 만드는 것입니다: 스크립트는 다른 스크립트나 PackedScene 리소스에 접근하기 위해 상수를 불러오고 생성하는 것으로도, MyAutoload.MyNode.new()와 같은 결과를 낳습니다.
    • Godot 3.1에서 스크립트 클래스를 도입하면서 이런 이유의 정당성은 의문이 됩니다. 스크립트 클래스로 GDScript에서 명시적 이름을 사용해 스크립트에 접근할 수 있습니다. 오토로드를 사용하여 네임스페이스 스크립트를 갖는 행위는 불필요해졌습니다, 예시: MyScriptClass.MyPreloadedScript.new().

싱글톤이 자체 정보를 관리하고 있고, 다른 객체의 데이터에 침범하지 않는다면, 넓은 범위의 작업을 다루기 위해 "시스템" 클래스를 만드는 것이 좋은 방법입니다. 예를 들어 타겟팅 시스템, 퀘스트 시스템, 아니면 대화 상자 시스템이 대표적인 싱글톤 구현 사례입니다.