Godot:AutoLoad
Singleton
싱글톤 패턴은 씬 간에 지속적으로 정보를 저장해야 하는 일반적인 사례를 해결하는 데 유용한 툴입니다. 우리의 경우 여러 싱글톤의 이름이 서로 다르기만 하면 동일한 장면이나 클래스를 여러 싱글톤에서 재사용할 수 있습니다.
이 개념을 사용해서 다음과 같은 오브젝트를 만들 수 있습니다:
- 현재 실행 중인 씬에 관계없이 항상 불러와집니다
- 플레이어 정보와 같은, 전역 변수를 저장할 수 있습니다.
- 씬을 변경하는 것과 씬 사이에서의 전환을 다룰 수 있습니다.
- GDScript가 전역 변수를 지원하지 않기 때문에 싱글톤처럼 작동합니다.
INFORMATION |
Godot는 오토로드를 싱글톤 디자인 패턴에 따르는 "진정한" 싱글톤으로 만들지 않습니다. 원한다면 사용자가 두 번 이상 인스턴스화할 수 있습니다. |
오토로드와 씬의 관계
스크립트를 오토로드할 때 Node가 생성되고 스크립트가 여기에 추가됩니다. 이 노드는 다른 씬이 로드되기 전에 루트 뷰포트에 추가됩니다.
Godot_singleton_scenetree.png
오토로드 사용 방법
씬이나 스크립트를 오토로드하려면 메뉴에서 프로젝트(Project)
-> 프로젝트 설정(Project Settings)
를 선택하고 AutoLoad
탭으로 가세요.
Godot-autoload_example.png
위의 경우 모든 노드에서 다음 코드를 사용해 "PlayerVariables" 라는 싱글톤을 접근할 수 있습니다:
var playerVariables = GetNode<PlayerVariables>("/root/PlayerVariables");
playerVariables.Health -= 10; // Instance field.
Enable 열이 선택되어 있으면(기본값) get_node()
함수 없이 싱글톤에 직접 액세스할 수 있습니다:
주의사항
-
free()
orqueue_free()
를 사용하여 런타임에 제거할 수 없다.
커스텀 씬 전환기
이 튜토리얼에서는 오토로드를 사용해 씬 전환기를 빌드하는 방법을 설명합니다.
기본적인 씬 전환은 SceneTree.change_scene()
메서드를 사용할 수 있습니다(자세한 내용은 씬 트리 (SceneTree) 항목 참조). 그러나 씬을 변경할 때 더 복잡한 동작이 필요한 경우 오토로드를 사용하면 더 많은 기능을 제공합니다.
Global Script
새로운 Global.cs
스크립트를 만들고 AutoLoad 에 등록한다.
using Godot;
using System;
public class Global : Godot.Node
{
public Node CurrentScene { get; set; }
public override void _Ready()
{
Viewport root = GetTree().Root;
CurrentScene = root.GetChild(root.GetChildCount() - 1);
}
// 씬을 변경하는 함수가 필요합니다.
// 이 함수는 현재 씬을 해제하고 요청한 씬으로 교체해야 합니다.
public void GotoScene(string path)
{
// 이 함수는 일반적으로 신호 콜백 또는 현재 장면의 다른 함수에서 호출됩니다.
// 이 시점에서 현재 장면을 삭제하는 것은 아직 코드를 실행 중일 수 있으므로 좋지 않은 생각입니다.
// 이로 인해 충돌 또는 예기치 않은 동작이 발생합니다.
// 해결 방법은 현재 장면에서 실행 중인 코드가 없다고 확신할 수 있는 나중으로 로드를 연기하는 것입니다.
CallDeferred(nameof(DeferredGotoScene), path);
}
public void DeferredGotoScene(string path)
{
// 이제 현재 장면을 안전하게 제거할 수 있습니다.
CurrentScene.Free();
// 새 장면을 로드합니다.
var nextScene = (PackedScene)GD.Load(path);
// 새 장면을 인스턴스화합니다.
CurrentScene = nextScene.Instance();
// 루트의 자식으로 활성 장면에 추가합니다.
GetTree().Root.AddChild(CurrentScene);
// 선택적으로, `SceneTree.change_scene()` API와 호환되도록 합니다.
GetTree().CurrentScene = CurrentScene;
}
}
Object.call_deferred()
를 사용하면 인자로 사용된 함수는 현재 씬의 모든 코드가 완료된 후에만 실행됩니다. 따라서 현재 씬이 사용 중인 동안에는 제거되지 않습니다(즉, 해당 코드가 계속 실행 중임).
마지막으로, 두 씬에서 비어있는 콜백 함수를 채워야 합니다:
// Add to 'Scene1.cs'.
public void OnButtonPressed()
{
var global = GetNode<Global>("/root/Global");
global.GotoScene("res://Scene2.tscn");
}
그리고
// Add to 'Scene2.cs'.
public void OnButtonPressed()
{
var global = GetNode<Global>("/root/Global");
global.GotoScene("res://Scene1.tscn");
}
프로젝트를 실행하고 버튼을 누를 때마다 씬이 바뀌는지 확인해보세요.
다음 단계
씬이 작다면 씬 전환이 빠르게 됩니다. 그러나 씬이 더 복잡한 경우 표시되는 데 상당한 시간이 걸릴 수 있습니다. 이를 처리하는 방법을 배우려면 다음 튜토리얼 백그라운드 로딩을 살펴보세요.
로딩 시간이 비교적 짧은 경우(3초 미만) 장면을 변경하기 직전에 일종의 2D 요소를 표시해서 "로딩 플라크(plaque)"를 표시할 수 있습니다. 그런 다음 씬이 변경된 직후에 숨길 수 있습니다. 이는 장면이 로드되고 있음을 플레이어에게 알려주는 데 사용할 수 있습니다.