Autoloads versus nós normais

O Godot oferece um recurso para carregar automaticamente nós na raiz do seu projeto, permitindo que você os acesse globalmente, que pode cumprir o papel de um Singleton: Singletons (Carregamento Automático). Estes nós auto-carregados não são liberados quando você muda a cena pelo código com SceneTree.change_scene.

Neste guia, você aprenderá quando usar a funcionalidade Autoload e as técnicas que você pode usar para evitá-lo.

O problema do corte de áudio

Outros motores podem encorajar o uso da criação de classes de gerenciador, singletons que organizam muita funcionalidade em um objeto globalmente acessível. O Godot oferece muitas maneiras de evitar o estado global graças à árvore de nós e aos sinais.

Por exemplo, digamos que estamos construindo um jogo de plataforma e queremos coletar moedas que reproduzam um efeito sonoro. Há um nó para isso: o AudioStreamPlayer. Mas se chamarmos o AudioStreamPlayer enquanto ele já está tocando um som, o novo som interrompe o primeiro.

Uma solução é codificar uma classe de gestão de som global e auto-carregada. Ele gera um conjunto de nós AudioStreamPlayer que se movimentam à medida que cada nova solicitação de efeitos sonoros chega. Digamos que chamamos essa classe Sound, você pode utilizá-la de qualquer lugar do seu projeto chamando Sound.play("coin_pickup.ogg"). Isto resolve o problema a curto prazo, mas causa mais problemas:

  1. Estado global: um objeto agora é responsável pelos dados de todos os objetos. Se a classe Sound tem erros ou não tem um AudioStreamPlayer disponível, todos os nós que o chamam podem quebrar.

  2. Acesso global: agora que qualquer objeto pode chamar Sound.play(sound_path) de qualquer lugar, não há mais uma maneira fácil de encontrar a origem de um bug.

  3. Alocação global de recursos*: com um conjunto de nós AudioStreamPlayer armazenados desde o início, você pode ou ter muito poucos e enfrentar bugs, ou muitos e utilizar mais memória do que você precisa.

Nota

Sobre o acesso global, o problema é que qualquer código em qualquer lugar pode passar dados errados para o autoload Sound no nosso exemplo. Como resultado, o domínio a explorar para corrigir o bug abrange todo o projeto.

Quando você mantém o código dentro de uma cena, apenas um ou dois scripts podem estar envolvidos no áudio.

Contraste isto com cada cena mantendo tantos nós AudioStreamPlayer quantos forem necessários dentro de si e todos estes problemas desaparecem:

  1. Cada cena gerencia suas próprias informações de estado. Se houver um problema com os dados, isso causará problemas apenas naquela cena.

  2. Cada cena acessa apenas seus próprios nós. Agora, se houver um bug, é fácil descobrir qual nó é o culpado.

  3. Each scene allocates exactly the amount of resources it needs.

Gestão de funcionalidades ou dados compartilhados

Outra razão para usar um Autoload pode ser que você queira reutilizar o mesmo método ou dados em muitas cenas.

No caso de funções, você pode criar um novo tipo de Node que fornece esse recurso para uma cena individual utilizando a palavra-chave class_name em GDScript.

Quando se trata de dados, você pode:

  1. Cria um novo tipo de Resource para compartilhar os dados.

  2. Armazenar os dados em um objeto ao qual cada nó tem acesso, por exemplo utilizando a propriedade owner para acessar o nó raiz da cena.

Quando você deve usar um Autoload

Nós carregados automaticamente podem simplificar seu código em alguns casos:

  • Dados estáticos: se você precisa de dados exclusivos de uma classe, como um banco de dados, então um auto-carregamento pode ser uma boa ferramenta. Não há API de scripting no Godot para criar e gerenciar dados estáticos de outra forma.

  • Funções estáticas: criar uma biblioteca de funções que só retornam valores.

  • Sistemas com amplo escopo: se o singleton está gerenciando suas próprias informações e não invadindo os dados de outros objetos, então é uma ótima maneira de criar sistemas que lidam com tarefas de amplo escopo. Por exemplo, uma quest ou um sistema de diálogo.

Até o Godot 3.1, outro uso era apenas por conveniência: os autoloads têm uma variável global para seu nome gerada no GDScript, permitindo que você os chame a partir de qualquer arquivo de script em seu projeto. Mas agora, você pode usar a palavra-chave class_name para obter o preenchimento automático de um tipo em todo o seu projeto.

Nota

Autoload não é exatamente um Singleton. Nada o impede de instanciar cópias de um nó carregado automaticamente. É apenas uma ferramenta que faz um nó carregar automaticamente como um filho da raiz da sua árvore de cenas, independentemente da estrutura do seu jogo ou da cena que você executar, por exemplo, pressionando a tecla F6.

Como resultado, você pode obter o nó carregado automaticamente, por exemplo, um autoload chamado Sound, chamando get_node("/root/Sound").