SceneTree(씬트리)

소개

이전 튜토리얼에서, 모든 것은 노드 개념을 중심으로 돌아갔습니다. 씬은 노드 모음집입니다. 노드는 씬 트리(scene tree)에 들어가면 활성화됩니다.

MainLoop(메인루프)

Godot가 내부적으로 작동되는 과정은 다음과 같습니다. OS 클래스는 처음에 실행되는 유일한 인스턴스 입니다. 그 이후에, 모든 드라이버, 서버, 스크립트 언어, 씬 시스템 등을 불러옵니다.

초기화를 마칠 때, OS 를 실행하기 위해 MainLoop 가 공급되어야 합니다. 여기까지, 이 모든 것이 내부 작업입니다 (어떻게 내부 작업이 이루어지는지 관심이 있으시다면, 소스 코드의 main/main.cpp 파일에서 이를 확인하실 수 있습니다).

사용자 프로그램, 게임은 MainLoop에서 시작합니다. 이 클래스는 몇 가지 메소드를 갖고 있는데, 초기화, 휴식(Idle)(프레임 동기화된 콜백), 고정된(fixed)(물리 동기화된 콜백), 그리고 입력입니다. 이것은 로우 레벨이며, Godot에서 게임을 만들 때 당신만의 MainLoop를 만드는 일은 드뭅니다.

SceneTree(씬트리)

Godot가 어떻게 작동하는지 설명하는 방법으로 이것은 로우 레벨 미들웨어에 비해 높은 수준의 게임 엔진이란 것입니다.

씬 시스템은 게임 엔진입니다, 반면에 OS 와 서버는 로우 레벨 API입니다.

씬 시스템은 고유의 메인 루프(main loop)를 운영체제로 보냅니다, SceneTree. 이것은 씬이 실행되는 동안 자동으로 인스턴스되고 설정됩니다, 다른 추가 작업은 필요가 없습니다.

이 클래스가 몇 가지 중요한 용도에 쓰이기 때문에 존재하는 것을 알아야 합니다:

  • 처음 열렸을 때 씬 트리 의 일부분이 되도록 씬이 자식으로 추가되는, 루트 Viewport 를 포함합니다, (자세한 설명은 다음에)
  • 그룹에 관한 정보를 포함하고 그룹의 모든 노드를 호출하거나 그룹의 목록을 가져옵니다.
  • 일시 정지 모드 설정이나 프로세스 종료하기와 같은, 일부 전역 상태 기능성을 포함합니다.

노드가 씬 트리의 일부분일 때, Node.get_tree()를 호출해서 SceneTree 싱글톤(Singleton)을 포함될 수 있습니다.

루트 뷰포트(Root viewport)

루트 Viewport 는 항상 씬의 맨 위에 있습니다. 노드에서, 두 가지 다른 방법으로 포함할 수 있습니다:

get_tree().get_root() # Access via scene main loop.
get_node("/root") # Access via absolute path.
GetTree().GetRoot(); // Access via scene main loop.
GetNode("/root"); // Access via absolute path.

이 노드는 메인 뷰포트를 갖고 있습니다. 모든 것이 기본적으로 Viewport의 자식으로 있습니다, 그래서 모든 노드의 꼭대기에는 이 타입의 노드가 있고 그렇지 않다면 아무것도 보이지 않을 것입니다.

반면에 다른 뷰포트는 씬에서 만들 수 있지만(분리 화면 효과와 같은 것을 위해), 사용자가 절대 만들 수 없는 유일한 것입니다. 씬 트리에서 자동으로 생성됩니다.

씬 트리

노드가 뷰포트에 연결될 때, 직접적이든 아니든, 그것은 씬 트리 의 일부분이 됩니다.

이전 튜토리얼에서 설명했듯이, 그것은 (_exit_tree()과 마찬가지로) _enter_tree()와 _ready() 콜백을 가질 것입니다.

../../_images/activescene.png

노드는 씬 트리에 들어가면 활성화됩니다. 노드는 입력을 받거나 처리하고, 2D와 3D 표현을 보여주고, 알림을 받고 보내거나, 소리를 재생하는 등을 실행하기 위한 것들 모두에 접근합니다. 노드가 씬 트리에서 제거될 때, 능력을 잃습니다.

트리 순서

2D 그리기, 프로세싱, 혹은 알림 받기와 같은 대부분의 노드 운영은 트리 순서에서 완료됩니다. 즉, 현재 노드보다 트리 순서에서 부모와 더 낮은 등급의 형제 노드들이 먼저 알림을 받는 것입니다.

../../_images/toptobottom.png

씬 트리 에 들어가서 "활성화하기"

  1. 씬은 디스크에서 불러오거나 스크립트에 의해 만들어집니다.
  2. 씬의 루트 노드 (단 하나의 루트, 기억하시나요?) 는 "루트" 뷰포트의 자식으로, 혹은 노드의 자식으로 (씬 트리에서) 추가됩니다.
  3. 새롭게 추가되는 씬의 각 노드는, 위에서 아래 순으로 "enter_tree" 알림을 (GDScript에서 _enter_tree() 콜백을) 받습니다.
  4. 추가 알림으로, 노드와 모든 자식이 활성화된 씬 안에 있을 때, "ready"가 (GDScript에서는 _ready() 콜백이) 편의로 제공됩니다.
  5. 씬(이나 일부분)이 제거될 때, 그들은 아래에서 위 순으로 "exit scene" 알림을 (GDScript에서는 _exit_tree() 콜백을) 받습니다

현재 씬 변경하기

씬이 불러온 후, 그것을 다른 씬으로 바꾸고 싶을 수 있습니다. 간단한 방법으로 SceneTree.change_scene() 함수를 사용하는 것입니다:

func _my_level_was_completed():
    get_tree().change_scene("res://levels/level2.tscn")
public void _MyLevelWasCompleted()
{
    GetTree().ChangeScene("res://levels/level2.tscn");
}

파일의 경로를 사용하기보다는, SceneTree.change_scene_to(PackedScene scene) 함수를 사용하여 이미 만들어져 있는 PackedScene 리소스를 사용합니다:

var next_scene = preload("res://levels/level2.tscn")

func _my_level_was_completed():
    get_tree().change_scene_to(next_scene)
public void _MyLevelWasCompleted()
{
    var nextScene = (PackedScene)ResourceLoader.Load("res://levels/level2.tscn");
    GetTree().ChangeSceneTo(nextScene);
}

이것들은 씬을 바꾸려고 할때 빠르고 쓸만하지만 새로운 씬이 로딩되고 실행될때 약간의 단점이 있습니다. 개발하실 때에는 프로그레스 바가 있는 로딩 화면을 만드는 것이 더 좋습니다. 이 작업은 Autoloads(다음 장을 참조하십시오) 와 :ref: `doc_background_loading' 을 사용하여 수동으로 수행해야 합니다.