Skip to content

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() 함수 없이 싱글톤에 직접 액세스할 수 있습니다:

// Static members can be accessed by using the class name.
PlayerVariables.Health -= 10;

주의사항

  • free() or queue_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)"를 표시할 수 있습니다. 그런 다음 씬이 변경된 직후에 숨길 수 있습니다. 이는 장면이 로드되고 있음을 플레이어에게 알려주는 데 사용할 수 있습니다.

See also

Favorite site