씬과 스크립트 중 하나를 사용해야 하는 경우

우리는 이미 씬과 스크립트가 다르다는 것을 압니다. 스크립트는 명령형 코드, 선언형 코드로 만든 씬을 사용해 엔진 클래스 확장을 정의합니다.

각 시스템의 능력은 결과적으로는 다릅니다. 씬은 어떻게 확장된 클래스를 초기화하는 지 정의할 수 있지만, 씬은 종종 스크립트와 함께 사용되어 선언형 코드 스크립트의 확장으로 작업하기도 합니다.

익명 타입

스크립트 하나 만으로 씬의 내용을 완전히 정의하는 것은 가능합니다. 본질적으로, Godot 편집기가 하는 일은 오직 개체의 C++ 생성자에서 이루어집니다.

하지만 어떤 것을 사용해야 하는지 결정하는 것은 딜레마가 됩니다. 스크립트 인스턴스를 만드는 것은 인 게임 클래스를 만드는 것과 동일하지만 씬을 다루려면 API를 변경해야 합니다:

const MyNode = preload("my_node.gd")
const MyScene = preload("my_scene.tscn")
var node = Node.new()
var my_node = MyNode.new() # Same method call
var my_scene = MyScene.instance() # Different method call
var my_inherited_scene = MyScene.instance(PackedScene.GEN_EDIT_STATE_MAIN) # Create scene inheriting from MyScene
using System;
using Godot;

public class Game : Node
{
    public readonly Script MyNodeScr = (Script)ResourceLoader.Load("MyNode.cs");
    public readonly PackedScene MySceneScn = (PackedScene)ResourceLoader.load("MyScene.tscn");
    public Node ANode;
    public Node MyNode;
    public Node MyScene;
    public Node MyInheritedScene;

    public Game()
    {
        ANode = new Node();
        MyNode = new MyNode(); // Same syntax
        MyScene = MySceneScn.Instance(); // Different. Instantiated from a PackedScene
        MyInheritedScene = MySceneScn.Instance(PackedScene.GenEditState.Main); // Create scene inheriting from MyScene
    }
}

또한 엔진과 스크립트 코드 간의 속도 차 때문에 스크립트가 씬에 비해 조금 더 느리게 작동합니다. 노드가 크고 복잡할수록, 씬으로 작업하는 것이 더 좋습니다.

명명된 타입

몇 가지 경우에서, 사용자는 편집기 자체 내에서 스크립트를 새로운 타입으로 등록할 수 있습니다. 노드 생성 또는 리소스 생성 대화상자에서 선택한 아이콘이 있는 새 타입으로 나타납니다. 이런 경우, 스크립트를 사용하는 사용자의 능력은 훨씬 더 간소화 되었습니다. 더 이상 다음과 같이 하지 않아도 됩니다...

  1. 사용하고 싶은 스크립트의 기본 타입을 알기.
  2. 기본 타입의 인스턴스를 생성하기.
  3. 노드에 스크립트를 추가하기.
    1. (드래그 앤 드롭 방식)
      1. 파일 시스템 독에서 스크립트를 찾기.
      2. 스크립트를 씬 독의 노드로 드래그 앤 드롭하기.
    2. (속성 방식)
      1. 인스펙터의 맨 아래로 내려서 script 속성을 찾고 선택하기.
      2. 드롭다운 메뉴에서 "불러오기" 선택하기.
      3. 파일 대화 상자에서 스크립트를 선택하기.

등록된 스크립트를 사용하면, 스크립트된 타입에서 다른 시스템 내 노드와 리소스와 같은 생성 옵션이 됩니다. 위의 작업을 하지 않아도 됩니다. 생성 대화 상자는 타입을 이름으로 찾아볼 수 있는 검색 상자도 있습니다.

타입을 등록하는 데는 두 가지 시스템이 있습니다...

  • 커스텀 타입

    • 편집기만 가능. 런타임 도중 타입이름에 접근할 수 없습니다.
    • 상속된 커스텀 타입을 지원하지 않습니다.
    • 초기화 도구. 스크립트로 노드를 만듭니다. 더 이상은 없습니다.
    • 편집기는 스크립트에 대한 타입 인식이나 다른 엔진 타입이나 스크립트 간의 관계가 없습니다.
    • 사용자가 아이콘을 정의할 수 있도록 합니다.
    • 스크립트 리소스를 추상화하기 때문에 모든 스크립트 언어에서 작동합니다.
    • EditorPlugin.add_custom_type을 사용해 설정합니다.
  • 스크립트 클래스

    • 편집기와 런타임에 접근할 수 있습니다.
    • 상속 관계를 전체적으로 표시합니다.
    • 스크립트로 노드를 만듭니다, 하지만 편집기에서 타입을 바꾸거나 확장할 수도 있습니다.
    • 편집기는 스크립트, 스크립트 클래스 및 엔진 C++ 클래스 간의 상속 관계를 인식합니다.
    • 사용자가 아이콘을 정의할 수 있도록 합니다.
    • 엔진 개발자는 수동으로 언어 지원을 추가해야 합니다 (이름 표시와 런타임 접근 가능성 모두).
    • Godot 3.1+에서만 가능합니다.
    • 편집기는 프로젝트 폴더를 스캔하고 모든 스크립팅 언어의 노출된 이름을 등록합니다. 각 스크립팅 언어가 이 정보가 노출되는 것을 자체적인 지원으로 구현해야 합니다.

두 방법론 모두 생성 대화 상자에 이름을 추가할 수 있습니다, 하지만 특히 스크립트 클래스는 사용자가 스크립트 리소스를 불러오지 않고도 타입이름에 접근할 수 있습니다. 인스턴스를 만들고 상수나 정적 메서드에 접근하는 것은 어디서나 가능합니다.

이러한 기능으로, 사람들은 사용자가 사용하기 쉽도록 그들의 타입이 씬이 없는 스크립트가 되길 원합니다. 플러그인을 개발하거나 디자이너를 위한 사내 도구를 만드는 사람들에게 이러한 방식은 더 쉬운 작업 시간을 찾을 수 있을 겁니다.

단점은 명령형 프로그래밍을 주로 사용해야 하는 것입니다.

결론

마지막으로, 최선의 접근법은 다음을 고려해보는 것입니다:

  • 여러 다른 프로젝트에서 재 사용하며, ("프로그래머"라는 이름표가 없는 사람들을 포함한) 모든 실력 수준의 사람들이 사용할 수 있는 기본 도구를 만들고 싶다면, 아마 스크립트로 만들어야 할 것입니다, 커스텀 이름/아이콘을 줄 수 있으니까요.

  • 게임에 특화된 개념을 만들고 시다면, 그것은 항상 씬이 되어야 합니다. 씬이 스크립트보다 더 쉽게 연결/편집하고 더 보안이 좋습니다.

  • 씬에 이름을 주고 싶다면, 스크립트 클래스를 선언하고 상수로 씬을 지정하여 3.1에서 이 작업을 수행할 수 있습니다. 스크립트는 사실상 네임스페이스가 됩니다:

    # game.gd
    extends Reference
    class_name Game # extends Reference, so it won't show up in the node creation dialog
    const MyScene = preload("my_scene.tscn")
    
    # main.gd
    extends Node
    func _ready():
        add_child(Game.MyScene.instance())