Godot: Ninguém sabe como Godot funciona. (Nó baseado em Re-MultiScript, Re-Class)

Criado em 16 out. 2018  ·  63Comentários  ·  Fonte: godotengine/godot

Este é um tópico mais informal, mas é uma questão drástica, se não a principal questão de Godot.
Ninguém sabe como os desenvolvedores do mecanismo Godot planejaram os usuários que o utilizam.

Alguns problemas relacionados: #19486 #7402 #15996 #8502
Estes são os 4 principais, mas existem muitos semelhantes que visam resolver o mesmo problema: Todo mundo está procurando um fluxo de trabalho utilizável.

Surpreendentemente, os usuários da Godot conseguiram criar fluxos de trabalho ineficientes que copiam outros mecanismos familiares. Para demonstrar isso, usarei uma classe simulada de como seria uma MeshInstance , se feita em Godot.


Existe pseudo Unity, também conhecido como nós filhos:


Os usuários Godot usam nós filhos para criar um equivalente a MultiScripts.

MeshInstance(Spatail +script)
--- Malha(Malha +script)
--- Material (nó + script) - Shader (nó + script) - Textura (nó + script)
--- Transformar (Position3D +script)

Basicamente, eles usarão o nó mais apropriado e codificarão o que precisam para criar a classe que desejam usando um script.

Problemas:
1.) É o equivalente digital de adicionar água fria a uma panela fervente; ajuda a curto prazo, mas causa mais confusão em projetos maiores.
2.) A maioria dos usuários acaba usando sinais como eventos, conectando-os apenas ao nó que os envia e usando Exportar para encontrar o destino.
3.) Os eventos podem ser interceptados antes de atingir os nós inferiores.
4.) O desempenho é lento e em torno de 50.000 objetos pode travar quando o jogo tenta carregar cenas.


Pseudo Unreal, também conhecido como controladores e intermediários:

Os usuários Godot fazem controladores e nós possuidores que manipulam todos os filhos. A marca registrada desse fluxo de trabalho são as classes derivadas com extends.

MeshWithTexturedMaterial.instanced() *somente nó na árvore
-> estende de -> MaterialTextured -> estende de -> Material -> estende de -> Shader

Este sistema requer planejamento pesado, ou você acaba com código semelhante em muitas classes. Como uma câmera, classes de personagens e veículos, todas contendo sua própria cópia de "follow target"
Problemas:
1.) Scripts grandes e confusos que são difíceis de depurar.
2.) Código duplicado em classes diferentes.
3.) Godot não trata nós como classes; forçando esses desenvolvedores a retransmitir fortemente em classes auto-codificadas.
4.) Extensões não fazem sentido, como um _sistema de combate_ estendendo um _sistema de armas_ e finalmente estendendo o jogador.


Pseudo Panda3D, também conhecido como Preload(Script):

Este replica o fluxo de trabalho de como a maioria dos mecanismos baseados em código funciona. Os desenvolvedores geralmente terão mais scripts do que nós.

MeshInstance (nó)
Pré-carregamento (Script de malha)
Pré-carregamento (Script de material)
Pré-carregamento (Script de transformação)

Estranhamente, são esses desenvolvedores que se recusam a abandonar o GDscript, mesmo quando C# é claramente melhor para essa abordagem. É por isso que eu suponho que eles estejam familiarizados com o Python.
Problemas:
1.) Confusão em como as importações devem ser chamadas, pois constantes podem ser variáveis ​​com onready; quem sabe.
2.) Raramente usa nós Godot, já vi desenvolvedores ignorarem completamente as ferramentas de interface do usuário.
3.) Dificuldade para depurar, pois não há indicação de onde um script está vinculado.


roteiro WTF:

Deixou o melhor para o final. Alguns desenvolvedores de jogos Godot conseguiram fazer bons jogos usando Sinais e Grupos.

MeshInstance (Node) com um nó vazio na parte superior permite fácil movimentação e reprojeto dos filhos.
--- Malha (Malha +Script || Sinal)
--- Material (Sprite + Script || Sinal)
--- Transformar (Position3D +Script || Signal)

Quando a árvore tiver que conectar objetos com 2 cenas ou mais, um grupo será usado. Notável sobre esse fluxo de trabalho é como ele tem árvores rasas.
Problemas:
1.) Sinais e Grupos permitem que partes inteiras do jogo simplesmente falhem, sem sequer um aviso.
2.) Pequenos scripts inúteis apenas vagando por aí. Tudo o que eles fazem é enviar um sinal e rastrear um único valor.
3.) Mover um objeto com tantos sinais anexados é no mínimo frustrante.
4.) Conflitos com o sistema de instâncias. Porque as instâncias fluem para baixo enquanto o sinal se conecta melhor para cima.

Sim, eu sei que Godot tem uma classe MeshInstance .
O ponto que isso demonstra é que a maioria dos fluxos de trabalho usados ​​pelos desenvolvedores agora pode tornar uma classe tão complexa quanto MeshInstance com vários componentes; exceto que cada fluxo de trabalho é seriamente falho.

Todos esses fluxos de trabalho compartilham o mesmo problema central. São soluções de curto prazo para desenvolver um jogo.
Nenhum deles escala bem e a depuração é falha em todos eles.

O que os desenvolvedores de jogos Godot precisam dos desenvolvedores do Engine é uma clara desaceleração do que é o fluxo de trabalho oficial para criar objetos e sistemas complexos.
Dessa forma, eles se desviam, mas sempre sabem como se destina a ser usado.

archived discussion core

Comentários muito úteis

Se a pergunta for simplesmente: "Existem várias maneiras de obter um mesmo resultado em Godot?", a resposta é sim. E tentar forçar um único fluxo de trabalho é absurdo, pois cada sistema em um jogo pode ter requisitos diferentes. Você não codifica da mesma forma um sistema que exige muitas performances e que precisa ser atualizado com frequência por um designer de jogos. Todas as soluções têm compensações, portanto, não faz sentido criar um fluxo de trabalho "oficial".

Todos 63 comentários

Se a pergunta for simplesmente: "Existem várias maneiras de obter um mesmo resultado em Godot?", a resposta é sim. E tentar forçar um único fluxo de trabalho é absurdo, pois cada sistema em um jogo pode ter requisitos diferentes. Você não codifica da mesma forma um sistema que exige muitas performances e que precisa ser atualizado com frequência por um designer de jogos. Todas as soluções têm compensações, portanto, não faz sentido criar um fluxo de trabalho "oficial".

pode tornar uma classe tão complexa quanto MeshInstance com vários componentes

Com quais componentes exatamente?

EDIT: E só para você saber, uma das questões que você citou foi encerrada com o autor afirmando "Esta ideia é realmente e totalmente uma merda e é completamente sem sentido".

Para demonstrar isso, usarei uma classe simulada de como seria uma MeshInstance, se feita em Godot.
Existe pseudo Unity, também conhecido como nós filhos:
Os usuários Godot usam nós filhos para criar um equivalente a MultiScripts.
Pseudo Unreal, também conhecido como controladores e intermediários:
Pseudo Panda3D, também conhecido como Preload(Script):
roteiro WTF:
Sim, eu sei que Godot tem uma classe MeshInstance.
O ponto que isso demonstra é que a maioria dos fluxos de trabalho usados ​​pelos desenvolvedores agora pode tornar uma classe tão complexa quanto MeshInstance com vários componentes; exceto que cada fluxo de trabalho é seriamente falho.

Não entendi muito bem o que você está tentando dizer aqui. Por que alguém criaria uma classe MeshInstance se já existe uma? E por que é um problema que Godot tenha recursos semelhantes a outros motores? Além disso, se você está tentando anexar vários scripts a um nó, você não usa OOP ou está colocando duas funcionalidades separadas em um nó, o que é facilmente corrigido usando o sistema de nós da Godot.

Se a pergunta for simplesmente: "Existem várias maneiras de obter um mesmo resultado em Godot?", a resposta é sim...

Se faço um martelo, sei para que serve, sei para que não deve ser usado, mesmo que não saiba tudo para que poderia ser usado.
Se você der um martelo para uma pessoa que não tem ideia do que é, e você nunca explicou como usá-lo; você não pode parecer surpreso quando eles começam a balançar descontroladamente.

É aqui que Godot está, os desenvolvedores estão balançando no escuro, esperando que de alguma forma isso lhes permita criar algo.

Com quais componentes exatamente?

Coisas como materiais e transformações são consideradas parte da instância original ou não?
Se criarmos componentes semelhantes, como os anexaremos ao nó?

E quanto a outras tarefas, como "seguir o alvo" ou "atirar no alvo", elas devem ser adicionadas à classe ou anexadas de alguma forma?
Como Godot nunca fez uma função Include ou Import apropriada para Godot, isso significa que nunca foi feito para ser usado dessa maneira?

Sabemos que não podemos ter tudo, então a questão é o que temos? Como foi o design para funcionar?

@MysteryGM Analogias soltas e desconectadas não são úteis.

Coisas como materiais e transforma

Transformar é uma propriedade Espacial e Materiais são uma propriedade Malha. O MeshInstance é construído em cima do Spatial, portanto, herda todas as propriedades do Spatial. É uma hierarquia simples que faz sentido para mim.

Se criarmos componentes semelhantes, como os anexaremos ao nó?

Por que você criaria seu próprio sistema Mesh quando Godot já os tem?

E quanto a outra tarefa, como "seguir o alvo" ou "atirar no alvo"

O código vai em scripts. Você pode colocá-lo no script principal do nó ou dar a ele um filho com um script se achar que seria mais útil fazê-lo dessa maneira.

Por que você criaria seu próprio sistema Mesh quando Godot já os tem?

Porque os objetos do jogo são tão complexos quanto uma malha, se notar mais. Lembre-se que os motores eram parte dos jogos originais, era apenas a parte reutilizada.

Se Godot não pode criar uma classe Mesh dentro do motor de forma eficaz, então ela não pode ser usada para fazer jogos complexos. Todos os jogos terão que ser menos complexos que o motor.
Isso, por sua vez, significa que não é útil para uma equipe profissional de desenvolvedores. A menos que essa equipe use apenas C++ com o código-fonte.

O código vai em scripts.

Mas de que maneira?
Já sei que não posso fazer um filho para cada script porque vou precisar de mais de um milhão de funções e até um milhão de nós vazios é demais para Godot.
O que isso significa, quantas funções devem ser agrupadas ou devo passar de 2 a 4 meses planejando minha herança de objetos no papel?

O que eu quero saber é como Godot lida com jogos grandes com sistemas complexos como efeitos climáticos, neblina volumétrica e grandes terrenos?

O seguinte se refere a mim, minhas opiniões e experiência, _YMMV_

Cada motor tem suas peculiaridades, e Godot não é diferente. Se estou sendo honesto, dado quanto tempo se passou desde seu primeiro lançamento estável, estou definitivamente chocado com o quão bom ele é e quão rápido ele evoluiu. Isso pode ser uma razão para alguns dos problemas que temos. O sistema de cena/nó é minha parte favorita, a simplicidade dos nós com script é realmente o que brilha para mim. Mesmo que tenha suas desvantagens para mim, não gosto de sintaxes semelhantes a python... e o sistema de pré-carregamento... não conseguia descobrir como fazer o C# funcionar.

Tomando o Unity 4/5 como exemplo (ao qual estive acorrentado por anos), ele tem _components_ tão inchados que não pode ser comparado a nenhum outro ECS que já usei. E oh, você quer fazer uma solicitação http? Claro, adicione um novo componente a um novo objeto à sua estrutura de cena porque faz muito sentido acoplar solicitações http com objetos na cena e seus componentes. O recurso "salvar uma cena sem alterações quebra todos os UUIDs" parecia ter sido criado apenas para tornar mais difícil para nossos designers não técnicos usarem o controle de versão. Eu nem quero começar em "Don't Destroy On Load" e prefabs.

Qual foi a lógica entre a maioria dessas coisas de qualquer maneira? Eu diria que provavelmente é um desenvolvimento orgânico e iterativo e algumas soluções alternativas aqui e ali (também encontradas em Godot e provavelmente em todos os outros mecanismos de jogo). Quer dizer, ele travou tanto que meu teclado Swift começou a prever as palavras "_Unity travando_" toda vez que eu digitava "_With_". Essa foi uma parte importante do meu fluxo de trabalho, travar -> reimportar todos os ativos por um minuto, trabalhar por 30', repetir.

Tenho visto tanto uso de monocomportamento blasfemo, mas quem posso culpar? O mecanismo permite que as pessoas coloquem um _GameState_ "_component_" dentro de um objeto pointlight. Devemos proibir? Como posso argumentar que os dados do estado do jogo não devem estar dentro do componente de um objeto de cena quando a comunicação http (ou praticamente qualquer trabalho assíncrono) precisa de um?

Isso me leva ao meu ponto, é difícil comparar mecanismos em seus diferentes estágios de desenvolvimento e, de fato, Godot está evoluindo rapidamente e adicionando/removendo recursos. Isso significa que nosso fluxo de trabalho terá que mudar e se adaptar de acordo. Eu tenho um fluxo de trabalho 2D decente com Godot, é definitivamente melhor do que o que eu tinha com o Unity. Sim, as melhores práticas são nebulosas. Sim, se você perguntar a três desenvolvedores, terá três fluxos de trabalho diferentes. Mas não posso dizer que seja um problema novo para mim, ou pelo menos é um presente em ambos os motores comparados.

Eu realmente não usei o Unreal (ou qualquer outro mecanismo de jogo relevante) para mais do que protótipos e projetos de teste, não posso comparar com profundidade razoável.

Mas de que maneira?
Já sei que não posso fazer um filho para cada script porque vou precisar de mais de um milhão de funções e até um milhão de nós vazios é demais para Godot.
O que isso significa, quantas funções devem ser agrupadas ou devo passar de 2 a 4 meses planejando minha herança de objetos no papel?

Colocar todas as funções em um script, talvez? Godot pode ser usado orientado a objetos muito bem, então se você já usou OOP você pode usar script ou herança de cena, criar classes e assim por diante.

O que eu quero saber é como Godot lida com jogos grandes com sistemas complexos como efeitos climáticos, neblina volumétrica e grandes terrenos?

Efeitos climáticos? Crie uma cena contendo um nó de partículas, um sol e um ambiente mundial e anexe um script à raiz. Este script pode controlar o clima. Você também pode criar um nó vazio e usá-lo como uma máquina de estado, anexando nós vazios para cada estado que você tem (como chuva, sol etc). Agora é só colocar o código de cada estado em seus nós. Essa máquina de estado pode ser controlada pelo script raiz. Esta é uma maneira muito fácil de ler de fazer as coisas.

Névoa volumétrica? Acho que já vi isso no novo FPS Demo.

Grandes terrenos? Eu tive um projeto com malhas de terreno processual uma vez e estava funcionando bem no meu laptop de alguns anos.

Essas são apenas algumas funcionalidades, e não um 'grande problema' sobre o qual você está falando no OP.

Efeitos climáticos? Crie uma cena contendo um nó de partícula...

Bem, planejamos ser um pouco mais ambiciosos do que isso :) com um mapa de região para dizer à IA onde caminhar e, em seguida, usar outro canal para zonas de exclusão de chuva, mantendo o último canal para profundidade para que a neve possa se acumular ao longo do tempo.

Grandes terrenos?

Espaço grande. Precisamos de alguma maneira de redefinir as cenas para o Vector3(0,0,0) sem congelar porque muitos nós precisam ser removidos. Física e tudo treme com grandes carros alegóricos.

ele tem componentes tão inchados que não podem ser comparados a nenhum outro ECS que já usei.

Concordo, os componentes podem ser horríveis, por isso não nos surpreenderia se Godot tivesse uma estratégia diferente em mente. No entanto, não temos ideia de qual estratégia Godot planejou ou se o fez.

2 meses de aprendizagem Godot só pensou em como fazer pequenos jogos.
Com 14 dias restantes para decidir usar Godot, espero que os desenvolvedores do mecanismo possam explicar como ele deve funcionar em grandes projetos.

A última coisa que queremos fazer é lutar contra o design dos motores enquanto tentamos desenvolver o jogo.

@MysteryGM Eu realmente não entendo por que você acha que Godot não é utilizável para grandes projetos. Seu design realmente se presta a grandes projetos porque você pode dividir tudo em cenas separadas e usar OOP para reutilizar o trabalho. Se o seu problema em usar Godot para um grande projeto é que você não sabe como atingir um objetivo, basta perguntar nos canais de ajuda do Godot Discords, você terá uma resposta muito imediata.

Física e tudo treme com grandes carros alegóricos.

Veja #288

No entanto, não temos ideia de qual estratégia Godot planejou ou se o fez.

Eu entendo que é meio estranho no começo, mas para mim o uso do nó + script é bastante direto. Eu definitivamente recomendo dar uma olhada (pelo menos) na versão hobby deste curso aqui: https://gumroad.com/gdquest
Ele usa uma estrutura de script de nó muito semelhante à minha, e definitivamente pode lhe dar uma visão melhor de como aqueles realmente envolvidos com o mecanismo o usam; o autor é um dos principais contribuintes para a Godot docs.

edit: Na verdade, você pode dar uma olhada na fonte no repositório, se não quiser o curso https://github.com/GDquest/make-pro-2d-games-with-godot

Com 14 dias restantes para decidir usar Godot, espero que os desenvolvedores do mecanismo possam explicar como ele deve funcionar em grandes projetos.

Acho que estou um pouco confuso sobre o que exatamente você quer dizer com isso. Você usou a analogia do martelo anteriormente como exemplo, mas é uma analogia falha, já que um martelo geralmente é uma ferramenta utilitária básica de uso único, e há uma compreensão intrínseca do que a ferramenta é usada devido à sua affordance.

Além disso, embora você tenha listado todos os problemas com todos esses sistemas acima, acho que a realidade de qualquer grande projeto de software é que cada 'escolha' de arquitetura que você fizer levará a algumas desvantagens no futuro, que você só precisa trabalhar mais ao longo do caminho. Então você está procurando uma sugestão de bala de prata? Porque, francamente, eu nem acho que a maioria dos projetos Unity ou Unreal seguem a estrutura exata 'recomendada' e muitas vezes bifurcam o mecanismo para se adequar a qualquer fluxo de trabalho que funcione melhor para eles. Eu chegaria ao ponto de argumentar que todo jogo precisa ter sua própria ideia única sobre arquitetura de nós. (Um jogo de simulação teria uma estrutura muito diferente de um jogo de tiro em terceira pessoa, por exemplo.)

Eu acho que um argumento poderia ser feito para mais documentação sobre exemplos de estrutura de projeto, mas acho que é apenas uma questão de mais contribuições para a documentação.

cenas separadas e use OOP para reutilizar o trabalho.

Como mencionei antes, mover objetos depois que os sinais foram anexados é uma dor. Especialmente quando eles param de funcionar sem nunca dar uma exceção ou aviso.
Decidimos usar uma ferramenta de refatoração de terceiros, depois que outro desenvolvedor a mencionou; mas mesmo assim não pode resolver os problemas únicos de Godot.
Não mover as coisas resulta neste problema (imagens do nosso "quadro de problemas"):
pawndefend
Então, para corrigir isso, criamos nós filhos. Exceto por volta de 50.000, ele começa a causar problemas, mesmo que sejam apenas Nodes.
pawnfollow

O que queremos saber é como trabalhamos com esses problemas, como Godot planejava lidar com eles; testamos todos os fluxos de trabalho que mencionei acima.

Veja #288

Obrigado por isso, estamos tão acostumados a coordenar o mundo em repouso, nunca verificamos isso.

Eu entendo que é meio estranho no começo, mas para mim o uso do nó + script é bastante direto.

O problema não é que seja alienígena, o problema é que causa um problema diferente. Principalmente que adicionar mais crianças eventualmente atrasa o jogo ou o congela quando tentamos descarregá-los.
Mesmo quando eles são apenas Nodes.

Por que você precisa de 50.000 objetos em seu jogo? Certamente isso atrasaria QUALQUER motor.

Por que você precisa de 50.000 objetos em seu jogo?

Porque usamos nós para adicionar scripts extras aos objetos. Porque as ferramentas de interface do usuário da Godot usam contêineres em contêineres em contêineres... para dimensionar as coisas em tempo real.
Nossa menor interface do usuário tem mais de 800 objetos. A maioria desses recipientes.

Temos 50.000 objetos porque um único inimigo AI é +/- 8 nós com um propósito e +/- 64 nós que estão lá apenas para que possamos anexar scripts a eles.
Porque dividindo cada tarefa em seu próprio código, podemos ver onde estão nossos problemas. Porque não há outra maneira de encontrar rapidamente uma parte específica do jogo.

Nesse caso, parece que você invadiu a zona em que os módulos personalizados são uma boa opção.
http://docs.godotengine.org/en/3.0/development/cpp/custom_modules_in_cpp.html
Você pode criar nós personalizados lá e evitar muitos aninhamentos.

edit: Embora eu argumente que 800 objetos para uma (menor?) interface do usuário aponta para um design/arquitetura ruim.

Eu realmente não consigo entender como você pode ter perto de 64 scripts para um único objeto. Isso soa mais como um problema de design do seu projeto do que um problema de Godot (novamente, provavelmente atrasará qualquer mecanismo). Consolide seu código em menos scripts. Não crie um script para cada parte da funcionalidade, mas sim para cada tipo de objeto (se um nó "Inimigo" puder fazer XYZ, adicione essa parte ao script Enemy em vez de adicionar nós filhos para a funcionalidade X e Y e Z) . Se você precisar de recursos mais avançados para fazer isso, talvez possa usar herança personalizada e/ou interfaces C#.

Nesse caso, parece que você invadiu a zona em que os módulos personalizados são uma boa opção.

Veja, essa foi uma das coisas que estamos nos perguntando, porque todos nós conhecemos C++, se o Custom Modulse for necessário, apenas editaremos o mecanismo Godot.
Sabemos que podemos usar #include com segurança onde o Godot preload() é questionável; ninguém pode nos dizer o quão estável é ou se há desvantagens.

Eu realmente não consigo entender como você pode ter perto de 64 scripts para um único objeto.

Simples, toda IA ​​pode fazer mais ou menos 64 tarefas, e não tarefas menores.
Um Script por exemplo é SquadFlightPatters e aqui estão todas as formações de vôo todas as 20 delas, então há SquadFlightPattersCosmetic que só resolve animações, sons e partículas relacionadas a padrões de vôo.

Nossa regra no momento é dividir o feedback do usuário do mecânico.

Se um nó "Inimigo" puder fazer XYZ, adicione essa parte ao script Enemy em vez de adicionar nós filhos para a funcionalidade X e Y e Z

Se você olhar as imagens e Pseudo Unreal, também conhecido como controladores e intermediários.

porque todos nós conhecemos C++, se o Custom Modulse for necessário, em vez disso, apenas editaremos o mecanismo Godot.

Acho criar módulos muito mais simples do que mudar o próprio mecanismo, pois ele é construído em cima dele, em vez de nele.

Ainda não consigo imaginar essa escala para números tão altos, especialmente UI com centenas ou milhares de nós por widget.

Em resposta aos problemas referenciados no OP:

  • 19486:

    • adicione o gerenciamento de dependência adequado com instalações de ativos em todo o sistema. Mova addons para fora do próprio projeto com uma maneira de trazê-los de volta para modificação
    • facilitar a extensão de nós personalizados, permitir herança de script entre idiomas
    • permitir que scripts sejam referenciados por nome de classe e namespace para evitar caminhos super longos no caso de ativos.

    As classes de script resolvem o último problema. Os namespaces podem ser criados criando uma classe de script de nível superior com constantes que servem como aliases para outros scripts. As mudanças que fiz no encaixe de cena do editor na versão 3.1 também facilitam MUITO a extensão de scripts personalizados agora. Quanto à herança entre linguagens, isso nunca será implementado formalmente, mas se os MultiScripts forem reintroduzidos, eles poderão falsificá-lo razoavelmente bem.

  • 7402 : Novamente, as classes de script são a solução para este problema (a "solução mais simples" que reduz havia pensado, se você ver alguns dos comentários finais deste problema).

  • 15996 : Este era eu percebendo que o que eu estava querendo era um sistema de traços (antes de entender o que eram traços) e, consequentemente, percebendo o quão terrível minha proposta inicial era, pois distorce completamente o design direcionado de cenas e nós e converte todo o coisa em um sistema de herança baseado em composição - algo mais parecido com o que o Unity realmente faz, o que é nojento (no Unity, você pode usar getComponent de qualquer COMPONENT e ele busca o componente irmão no GameObject proprietário. Os componentes são, na prática, um extensão do GameObject, empurrando suas dependências umas para as outras).

  • 8502 : MultiScript são simplesmente ferramentas para permitir que diferentes linguagens de script herdem umas das outras, semelhante à forma como os Blueprints do UE4 podem herdar diretamente de scripts C++ (o que, em Godot, não seria possível, pois a comparação é ter um GDScript estendendo um NativeScript. O VisualScript nem suporta herança em primeiro lugar, então GDScript é a comparação mais adequada aqui).

    Agora, como o MultiScript suporta essencialmente QUALQUER script que estende o tipo de mecanismo básico (para que você possa ter vários scripts de extensão de nó de diferentes linguagens que fazem coisas diferentes, mas não estão relacionados entre si), na verdade funciona quase mais como um sistema de traços de linguagem cruzada... mais ou menos. Eu acho que re-adicionar o MultiScript seria muito legal

Muitas das questões levantadas no OP giram em torno da existência de várias maneiras potenciais de resolver um problema, cada uma das quais pode ter várias ineficiências. Normalmente, quando há uma maneira específica de fazer algo que seria mais ideal, o mecanismo fornece sua própria implementação no mecanismo principal C++ (sem necessidade de scripts ou plugins) e esse é o uso sugerido.

Se essa classe existe e as pessoas não a estão usando, isso é um sinal de que 1) eles não estão verificando adequadamente a documentação para ver se suas necessidades já são atendidas pelo mecanismo / como o mecanismo sugere que seja usado ou 2) o mecanismo/organização não está fazendo um trabalho suficientemente bom para tornar a documentação altamente visível ou acessível aos usuários (já que eles não estão encontrando os recursos que existem).

A única coisa a ser feita para corrigir o problema 1 é que essas pessoas verbalizem seu problema e que outra pessoa as redirecione para os documentos ou site de perguntas e respostas para ajudá-las a encontrar a solução. Eu criei um problema (#23043) que sugere deixar as pessoas navegarem e usarem o site de perguntas e respostas diretamente do editor, o que deve ajudar muito com o problema 2. Os motivos estão descritos no link.

(Edit: se existem muitas maneiras de resolver um problema, e uma dessas maneiras é muito melhor do que qualquer outra, e Godot ainda não implementa sua própria solução nativa para isso, isso seria algo a sugerir como um novo recurso Foi assim que adicionamos o material SimplexNoise, já que as pessoas estavam escrevendo seus próprios algoritmos SimplexNoise em GDScript / código shader, etc.).


Com base no "quadro de problemas" que você descreveu, o problema que você estava tendo é que a herança múltipla não é suportada (nem uma boa ideia), então você optou por nós de componentes que concedem funcionalidade ao pai (o que parece razoável para mim). Se você está tendo problemas com o atraso do seu jogo porque ele está simplesmente criando muitos nós, então parece-me que provavelmente haverá um problema com sua abordagem geral (que é o que você parece estar reconhecendo e procurando ajuda para identificar aqui).


Quanto aos seus exemplos de fluxos de trabalho no OP...

  • Abordagem Unity, nós filhos:

    Faz sentido usar nós filhos, assumindo que se escreve lógica de emparelhamento. Isto é idealmente onde um sistema de características seria útil (para que se possa escrever a lógica de emparelhamento uma vez e apenas replicá-la em todos os lugares conforme necessário). Costumo escrever componentes de maneiras em que eles se definem automaticamente como "alvos" para seus pais quando são pais/não-parentes e auto-conectam/desconectam sinais relevantes. Você pode usar as notificações NOTIFICATION_(UN)PARENTED em _notification(what) para isso.

  • Abordagem UE4 com controladores:

    Godot 3.1 permite que você atribua classes de script para scripts, então não há mais necessidade de pré-carregá-los. Neste caso, Godot permite que você atribua nomes de tipo a nós, mas é específico para o script, então você deve ter cuidado. As cenas não recebem o mesmo tratamento, e provavelmente não terão, pois envolveria adicionar um monte de coisas ao núcleo do mecanismo (sobre o qual os desenvolvedores do núcleo podem ficar bastante sensíveis).

    Também não tenho certeza de como você está recebendo tanto código duplicado? Se várias classes exigem a mesma lógica, você agrupa essa lógica em um único Node e reproduz esse Node nas classes que precisam dele, da mesma forma que faria com Unreal (componentes, atores filhos), Unity (MonoBehaviours ou GameObjects filho) , ou praticamente qualquer outro mecanismo que mude as dependências para um objeto de propriedade para reduzir a reutilização de código.

  • Abordagem Panda3D com pré-carregamentos:

    Eu poderia entender que existem muitos problemas com essa abordagem, já que NodeRefs ainda não é uma coisa, e há problemas com a exportação de scripts de recursos no momento que espero corrigir para 3.2 (embora você provavelmente possa fazer a correção sozinho facilmente, é bem pequeno).

  • Abordagem de script WTF:

    Eu realmente não entendo todos os problemas que você está tendo aqui, provavelmente porque não temos muito contexto.

    Conflitos com o sistema de instâncias. Porque as instâncias fluem para baixo enquanto o sinal se conecta melhor para cima.

    Quando você gostaria de ter o comportamento do acionador de sinal de um pai em um descendente? Por que não apenas fazer com que o pai obtenha e chame diretamente o descendente e seu método? Não há perigo de o pai ver seu filho. É como dizer que um objeto C++ não deve ser capaz de acessar sua estrutura ou variáveis ​​de membro de classe(?).

    Pequenos scripts inúteis apenas vagando por aí. Tudo o que eles fazem é enviar um sinal e rastrear um único valor.

    Isso já é um sinal de que o desenho do projeto não é bom. É o problema de fazer com que cada interação singular no jogo seja rastreada por seu próprio objeto pessoal. Isso não é realmente ideal, de qualquer perspectiva.

    Mover um objeto com tantos sinais anexados é no mínimo frustrante.

    De que maneira? Em geral, descobri que estou codificando as conexões no arquivo de cena ou conectando e desconectando algoritmicamente os sinais para os nós, se eles forem movidos. Isso serviu bastante aos meus propósitos, mas se você tiver problemas específicos, compartilhá-los pode ajudar outras pessoas a ajudá-lo.

    Sinais e Grupos permitem que partes inteiras do jogo simplesmente falhem, sem sequer um aviso.

    Assim é o problema com qualquer booleano via design de existência. A alternativa é percorrer o objeto ALL, verificar se eles correspondem aos critérios e, em seguida, fazer a lógica se corresponderem e, se corresponderem, mas não corretamente, gerar um erro. No caso de sinais e grupos, os comportamentos são acionados em tudo dentro do conjunto automaticamente, portanto, se as coisas saírem do conjunto, não há como detectar que ocorreu um problema durante o tempo de execução. A única maneira de encontrar problemas desse tipo é durante os processos de configuração, onde os grupos/sinais estão sendo organizados em primeiro lugar.


De qualquer forma, essa foi toda a minha experiência com o material. Ajudaria muito mais para nós sabermos mais sobre seu projeto e o que ele está realmente fazendo para que possamos dar sugestões para seu caso de uso específico.

De qualquer forma, os problemas que você levantou aqui não parecem ser "novos" problemas com o design ou implementação do Godot Engine em si. Godot dá às pessoas uma API e como as pessoas usam essa API é com eles. Se você tem uma ideia de como um determinado recurso deve ser mais integrado/disponível no Godot (por exemplo, revitalizando o MultiScript), então essa seria uma boa proposta.

No entanto, a questão aqui parece ser mais "qual é a melhor maneira de projetar um sistema como o X" que... não é realmente um problema do GitHub. Parece mais apropriado no site de perguntas e respostas para um tipo de pergunta de "práticas recomendadas". Isso, ou é uma sugestão de que devemos fornecer um caminho para tornar esse tipo de informação específica de caso de uso mais clara/disponível publicamente, que é exatamente sobre o meu problema de perguntas e respostas.

As classes de script resolvem o último problema.

Em primeiro lugar, obrigado pela longa resposta, que é muito e claramente levou algum tempo para escrever.
Tenho o prazer de ouvir sobre as classes de script, não usamos 3.1; apenas para executar a demonstração do FPS.

mas se os MultiScripts forem reintroduzidos, eles poderão falsificá-lo razoavelmente bem.
É completamente compreensível que Godot nunca implemente MultiScripts. Na verdade, eu estava apenas apontando que muitos usuários do GitHub procuravam soluções de fluxo de trabalho semelhantes à medida que tentamos.

Quando você gostaria de ter o comportamento do acionador de sinal de um pai em um descendente? Por que não apenas fazer com que o pai obtenha e chame diretamente o descendente e seu método?

Eu sinto que deveria explicar isso. Na época, tínhamos scripts muito grandes, cada um com aproximadamente +/- 30 funções. Por esse motivo, queríamos evitar adicionar as funções de sinal extras ao script já grande.
O resultado foi que criamos scripts soltos para descarregar o trabalho do script grande.

Isso já é um sinal de que o desenho do projeto não é bom.

Essa é de fato a raiz do problema. Principalmente que testamos muitos designs recomendados pela comunidade Godot e alguns de tutoriais.
1.) No início tínhamos heranças insanas, rapidamente abandonadas quando ficou claro que Salvar Cena de Ramificação ou mover um objeto para outra cena desconectava os sinais.
2.) Seguimos isso com scripts grandes. Exceto os nomes abstratos desses scripts para tentar explicar o que cada um faz, dificultava a localização de problemas.
Sabíamos quais eram os nomes das funções que causavam problemas, mas não exatamente onde estavam localizadas.
3.) Então, lendo o manual, encontramos a abordagem do nó filho. Talvez fosse muito tentador porque permitia nós diretos e podíamos ver a estrutura no editor; também filtre-o para encontrar o script exato que desejávamos.

Acabando comigo aqui, e acho que a última resposta abordou muito do que eu estava pensando; Vou ter que verificar amanhã porque são 2 da manhã aqui.

"qual é a melhor maneira de projetar um sistema como o X" que... não é realmente um problema do GitHub.

Quero salientar que esgotamos a maioria de nossas outras opções. Cada um de nós perguntou nos fóruns de perguntas e respostas, fizemos amigos na comunidade e coletamos exemplos deles. Escaneou os documentos em busca de explicações.
Todos os fluxos de trabalho que descrevi são coisas que tentamos nos explicar por usuários Godot, que usam esses fluxos de trabalho. Cada um funcionaria nos motores mencionados, eles simplesmente não funcionaram tão bem em Godot.

Apenas o último fluxo de trabalho funcionou, exceto que nosso programador principal bateu a cabeça contra a mesa e fingiu estrangular alguém.

Lamentamos ler que você está tendo problemas para encontrar soluções para seus problemas. Will já lhe deu uma resposta longa, então tentarei não atrapalhar muito a conversa, mas, neste momento, parece que você precisaria de mais um consultor para ajudá-lo a resolver os desafios específicos que surgiram de suas necessidades.

Principalmente que testamos muitos designs recomendados pela comunidade Godot e alguns de tutoriais

A maioria de nós na comunidade trabalha em projetos de escala relativamente pequena. Eu uso muitos nós para ajudar a transmitir o ponto e a estrutura de um determinado sistema em tutoriais. Isso será bem dimensionado para a maioria das pessoas. Mas o que funciona para um jogo pequeno ou médio não se aplica a jogos maiores.

Seguindo o que @willnationsdev disse anteriormente, pode valer a pena considerar o código de back-end para ajudar a escalar o jogo, tanto em termos de desempenho quanto apenas para ter menos código para gerenciar no próprio editor. Não posso ajudar muito além disso pois, como muitos aqui, não tenho experiência com projetos maiores. Boa sorte!

Olá, temos apenas mais uma pergunta.

Se temos dois objetos não relacionados, como um edifício e água, mas queremos que os scripts desses objetos interajam, como fazemos isso sem nós ou pré-carregamento?
A água é uma textura, então também não pode colidir com o prédio.

@MysteryGM Você está dizendo que não quer nós representando o edifício e a água, ou simplesmente não quer scripts anexados a eles? Não há nada de errado em ter dados para processamento que não existem de alguma forma dentro da árvore de cena além de um único nó contendo dados.

Se você quiser adotar a abordagem do ECS, em vez de anexar scripts a cada instância de um tipo e processá-los individualmente, você pode ter um único nó de "sistema" que irá iterar e executar o processamento nos nós de acordo com um tipo/ grupo que você atribuiu a eles. Se você quiser evitar anexar scripts a nós para suas informações detalhadas individuais, também poderá armazenar essas informações no sistema, dependendo de quão temporal. Isso mantém seus nós mais leves e pode ser mais eficiente para você ao operar em milhares de entidades do mesmo tipo.

Com 50.000 de qualquer coisa , você excedeu o ponto em que a metáfora baseada em objetos SceneTree-and-nós de Godot é útil.

Isso não é muito diferente de outros mecanismos, com Unity você atingiria limites semelhantes com seus objetos de jogo, GC, ou com UE4 você encontraria problemas para dimensionar planos tão longe - mas acima de tudo , ter essa quantidade de qualquer coisa significa o padrão editores visuais simplesmente não são mais úteis, e as ferramentas fornecidas começam a quebrar ou pelo menos a ter um desempenho ruim.

Em todos os mecanismos, a solução é basicamente a mesma: crie suas próprias soluções. O que são isso depende mais do seu jogo, arquitetura e detalhes do que do motor.

Classes de gerenciador, barramentos de comunicação pub-sub, agentes de mensagens, gerenciadores de instância semelhantes ao que é feito para partículas, pools de objetos, shaders personalizados para descarregar o trabalho para a GPU, shaders de computação, mover o processamento para threads ou outros processos/servidores - existem toneladas de blocos de construção para possíveis soluções, e quais você precisará combinar dependem do seu conjunto de problemas específico.

O Unity facilita um pouco isso com sua nova infraestrutura ECS. Não tenho certeza sobre UE4. No final, neste nível avançado, você terá que fazer a maior parte do trabalho pesado sozinho (ou contratar alguém experiente para fazer isso por você).

UE4 e Unity só são mais fáceis na medida em que são mais antigos, mais estabelecidos e, portanto, há um número maior de pessoas com problemas de escala, o que significa mais conhecimento (e talento contratável) disponível para resolvê-lo.

Mas, na verdade, no final, nenhum motor o levará tão longe. Todo jogo ambicioso terá limitações em qualquer mecanismo. Conheço dezenas de exemplos de jogos médios a grandes no UE ou Unity que também precisavam resolver problemas semelhantes. Ou resolva-os ou reduza seu escopo.

O que os desenvolvedores de jogos Godot precisam dos desenvolvedores do Engine é uma clara desaceleração do que é o fluxo de trabalho oficial para criar objetos e sistemas complexos.

Isso depende muito do seu jogo. Não há uma resposta direta para isso em nenhum motor grande.
Você deve usar a abordagem baseada em cena de objetos de jogo no Unity? Ou o ECS híbrido? O novo ECS completo? Qual pipeline de renderização você usa?
Você usará Blueprint ou C++ em seu projeto UE4?

Todos os motores oferecem muitas opções, muitos fluxos de trabalho e muita liberdade, porque não existe uma solução de tamanho único.

Então, se você precisa de conselhos concretos sobre como abordar seu jogo específico em Godot, como estruturá-lo, qual arquitetura usar, você precisa fornecer muito mais contexto e informações.

Diga-nos o que você deseja realizar, e talvez alguém possa dar conselhos. Caso contrário, a única maneira pode ser contratar um experiente desenvolvedor Godot como consultor.

Só posso concordar com Groud:

Todas as soluções têm compensações, portanto, não faz sentido criar um fluxo de trabalho "oficial".

@mhilbrunner Apenas jogando o advogado do diabo aqui, mas um design de mecanismo melhor (como ECS adequado na maioria dos casos em que o desempenho é importante) torna muitos desses limites significativamente maiores do que quase qualquer jogo realmente experimentaria (é assim que o novo Rust Amethyst motor de jogo está se concentrando, por exemplo).

Mas sim, eu fiz uma coisa do tipo ECS em Godot (2) e funcionou muito melhor do que o estilo de instanciação de scenetree em termos de eficiência e distribuição de funcionalidade. Isso pode ser feito, apenas um pouco doloroso, pois Godot não possui alguns primitivos úteis para isso.

@OvermindDL1

Eu só posso falar por mim, não por outros desenvolvedores Godot, e só tenho experiência com UE, Unity e Godot, então não sei sobre Rust Amethyst.

Isso pode ser feito, apenas um pouco doloroso, pois Godot não possui alguns primitivos úteis para isso.

Ter uma discussão sobre onde faria sentido adicionar tais primitivos / como Godot pode acomodar melhor esses casos de uso seria muito valioso, eu acho. Talvez não nesta edição :)

Mas devemos reunir esse feedback de alguma forma.

E concordo que existem limites diferentes dependendo do motor, mas, novamente, vi pessoas atingirem barreiras semelhantes no Unity e no UE4 também. Talvez mais tarde, talvez esses fossem mais altos - mas no final, você precisará resolver os problemas que encontrar em qualquer mecanismo. :)

@MysteryGM Você está dizendo que não quer nós representando o edifício e a água, ou simplesmente não quer scripts anexados a eles?

Já tenho um script anexado ao objeto água que alimenta o sombreador de água. Portanto, não posso mais anexar um script ao nó de água.
Eu tenho um script anexado ao prédio que controla sua produção de recursos e conecta coisas como portas a ele. Portanto, ele também tem um script no qual não quero adicionar mais código.

Com ambos os objetos já tendo código, o que eu faço agora? Não consigo adicionar mais nós e ainda não está claro se o pré-carregamento é uma solução possível.

Minha pergunta se eu colocar isso como um design OOP é: Como dois scripts acessam as interfaces uns dos outros?

O problema é que o GDscript não parece ter como acessar outros scripts diretamente.
Se eu quiser que Fogo queime Madeira, eu tenho que ter Madeira->estender->Fogo ou Fogo->estender->Madeira.

@MysteryGM : Uma dica: sinais. O fogo pode ter um sinal de queima (alvo) onde o alvo é sua madeira.

Como dois scripts acessam as interfaces um do outro?

$NodeWithScript.do_function() ?

_/eu ainda estou bancando o advogado do diabo, não tome isso como uma medida do que 'deveria' ser feito em Godot, na melhor das hipóteses é bikeshedding_

Eu só posso falar por mim, não por outros desenvolvedores Godot, e só tenho experiência com UE, Unity e Godot, então não sei sobre Rust Amethyst.

O UE usa um modelo Actor SceneTree. O Unity usou um modelo EC (embora recentemente eles tenham construído um ECS e descontinuado o antigo modelo EC, ainda não está completo, mas parece promissor). E Godot usa um modelo Component SceneTree. O ECS é um subconjunto do padrão de fluxo de dados (especificamente, é uma generalização dele).

Resumo rápido sobre o ECS:

  • Uma ' Entidade ' é apenas um ID inteiro, embora a maioria dos mecanismos empacote uma geração e um índice de entidade em um único int32 (geração de 8 bits e índice de 24 bits) ou int64 (32 bits cada, int64 é significativamente mais comum, pois o ECS realmente permite que você para escalar para quantidades tão significativas de entidades).

  • Um 'componente' é uma estrutura POD na terminologia C /C++, absolutamente nunca deve conter funcionalidade. Em geral, deve ser trivialmente memcpy'able.

  • Uma 'Tabela' de Componente é o armazenamento de componentes, em sua forma mais básica pode ser apenas uma matriz redimensionável, mas em geral alguns tipos tendem a ser usados:

    • Matriz redimensionável: frequentemente usada quando um componente é extremamente comum, como uma posição.
    • Array Esparso: Geralmente usado quando um componente tende a ser usado em grupos de entidades por vez.
    • Mapeamento: Talvez um mapa de hash ou um mapa de árvore ou algo assim, dependendo das características de desempenho que você espera, mas geralmente usado para componentes menos comuns.
    • Bitsets: Usado puramente como definição de se um componente existe em uma entidade, mas não armazena nada, geralmente conhecido como Componente de Sinalização.
    • Octree ou algum outro SceneGraph (o renderizador de Godot pode caber aqui): O mapeamento de scenetree que finge ser um componente.
    • Etc...: Muitos outros tipos dependendo do acesso e das características de desempenho esperadas para um componente.
  • Um ' S ystem' é basicamente uma função que recebe um conjunto de componentes unidos, embora a maioria das bibliotecas tenha uma classe ou módulo não virtual ou algo assim, ele opera sobre esse conjunto de componentes para 'fazer' algo, o que poderia envolver alterar valores em componentes, adicionar ou remover componentes, etc... Alguns exemplos:

    • Um Sistema que pega todas as entidades com um componente de Posição e Transformação e de forma eficiente e amigável ao cache transforma todas as matrizes de posição com as transformações necessárias no tick/time dado. Quando não há mais transformação a ser feita (uma entidade se torna estática), o componente Transformação é removido da entidade e não é mais processado.
    • Um sistema de entrada escuta os eventos das entradas (mouse/teclado/gamepad/etc...) e os transforma em componentes sendo adicionados às entidades relevantes ou para realizar outras ações.
    • Um sistema de Fornalha (metáfora do Minecraft) pega entidades que possuem Inventory, Fuel, RecipeMapping, BlockPos, Cooking e outros componentes, itera sobre essas entidades e atualiza os estados relevantes conforme necessário, até que não haja mais nada para cozinhar e quando o combustível expira, ele remove o componente Cooking Flag para que ele não seja mais processado até que o inventário seja alterado novamente para definir os componentes do sinalizador.

Internamente, você pode pensar em um ECS como um banco de dados onde você pode se inscrever para definir mapeamentos de dados, embora, se bem feitos, sejam extremamente bem otimizados. Com o conhecimento de quais sistemas devem ser executados antes de quais outros sistemas e quais sistemas operam sem sobreposição (dependente de leitura ou leitura/gravação), você também pode realizar várias threads nas chamadas. (Continuo usando Amethyst e sua parte da biblioteca específica do ECS chamada specs como exemplo porque eu participei de sua criação ao portar minha antiga biblioteca C++ ECS) O livro de especificações detalha muito sobre 'Por que' ECS, ' Como', eficiência, usos, etc... Amethyst entra em ainda mais detalhes, especialmente sobre como os ECS's devem ser usados ​​com os sistemas gerais de jogos, renderização, etc...

Se você quiser ver uma biblioteca C++ ECS bem escrita, veja https://github.com/skypjack/entt como de todas as bibliotecas C++ ECS que eu vi que não fiz, parece ser a melhor feita no geral (embora as especificações ainda superem em meus testes simples, embora não muito, o que é impressionante, considerando que as especificações superam tudo que eu já comparei por margens significativas).

O 'uso' geral do ECS é que você tem uma 'Entidade' (apenas um número inteiro, sem dados), e você tem o conjunto de Tabelas que mapeiam componentes para entidades e os sistemas para realmente realizar o trabalho. No pseudo-código GDScript, eu imagino que seja uma API simples, embora com uma convenção um pouco estranha para 'integrar' na árvore de cena Godot, já que a árvore de cena não foi projetada com isso em mente.

# All of this would generally be wrapped up in one or more function calls for easy
# building.

# Create a new entity
var e = createEntity()

# Map it to some Components, starting with a godot scenetree component
# I'm using long names to be descriptive, but eh...
var eNode = scenetreeComponentTable.set(e, SomeNodeType())
# Generally things like the transformation matrix and so forth would be their own
# components, but since the godot scenetree already bakes all that in then just
# deal with it all via the node type, you definitely lose a little efficiency doing
# it this way though since nodes involve multiple virtual calls to access and
# the usual ECS patterns entirely get rid of virtual calls with potentially only
# the occasional indirect calls inside a table (maps, etc...)

# 8x4 inventory slots
inventoryComponentTable.set(e, 8, 4)
# 1 fuel slot, accepts items that have the "burn" tag
fuelStorageComponentTable.set(e, 1, "burn")
# Give this entity the furnace component that uses the "basicFurnaceRecipes" recipes
furnaceComponentTable(e, "basicFurnaceRecipes")
# Add other components

# All of the above component mappings could also be in, say, a JSON file, and
# loaded something as such:
componentTables.map(e, "res://entity_types/basicFurnace.json")
# Or maybe via a preloaded JSON object or so

# Once at startup:

# And you could make a system something like, I'll use a GDScript class for this:
val furnaceCookSystemHandler = systems.register(FurnaceCookSystem.new())
furnaceCookSystemHandler.staticTickRate(0.05) # 20 times a second exactly

# Where the `FurnaceCookSystem` could be something like:
class FurnaceCookSystem:
  def _entity_matchers():
    furnaceBurnMatcher =
      componentTables.matcher().
      write(inventoryComponentTable).
      write(fuelStorageComponentTable).
      writeEither(inventoryChangedComponentTable, furnaceCookingComponentTable)
      read(furnaceComponentTable)
    return [furnaceBurnMatcher]

  # Assume we have matching semantics here to destructure a list, I'm lazy...
  def _entities_process([furnaceBurnEntities], delta):
    # This function takes a list of entity sets in the same order as the matchers
    # returned above.
    while entity in furnaceBurnEntities:
      val furnace = furnaceComponentTable[entity] # or .get(entity) or whatever API
      val cooking = furnaceCookingComponentTable[entity]
      if cooking == null or cooking.cookTimeRemaining <= 0:
        if cooking != null:
          if inventoryComponentTable.put(item) == False: # No space, try later
            continue
        # Get next item that has a "burnable" tag, if any
        val item = inventoryComponentTable[entity].getAndRemoveFirstOf("burnable")
        if item == null:
          furnaceCookingComponentTable.remove(entity)
        else:
          cooking = furnaceCookingComponentTable.set(entity, item, furnace.cookTime * getCookTimeModifierOfItem(item))
      else:
        cooking.cookTimeRemaining -= delta

 # ... whatever other functions are useful to the system

# Then of course just with the right components on any entity it will just work
# 'as' a furnace.  You can have a whole variety of 'generic' systems that can be
# mixed and match with impunity.  If you want a random rock that can be a furnace
# then just add the proper components, or if you want an Ent that can both be
# chopped down like a tree for wood but will also attack the player then just add
# the proper components, etc.... etc....

@MysteryGM : Uma dica: sinais. O fogo pode ter um sinal de queima (alvo) onde o alvo é sua madeira.

Desculpe eu quis dizer scripts não instâncias. Eu quero que os scripts interajam sem precisar de um nó na árvore Godot.

Desculpe eu quis dizer scripts não instâncias. Eu quero que os scripts interajam sem precisar de um nó na árvore Godot.

Talvez eu esteja entendendo mal o seu problema, mas tenho certeza que você já pode fazer isso criando classes em GDScript. Você ainda precisaria de um carregamento automático ou pelo menos um script em um nó para servir como ponto de entrada.

Além disso, você já tentou C #? Se você estiver tentando criar um sistema complexo que tenha scripts interagindo e controlando nós por meio de algo diferente de anexar scripts aos nós, você provavelmente terá um tempo muito melhor com C# do que com GDScript para esse sistema.

@MysteryGM Fazer com que os scripts interajam entre si sem o uso de um nó na cena significa que você precisa obter uma versão carregada do recurso de script, no mínimo. A única maneira de fazer isso no 3.0 é preload / load o script pelo caminho do arquivo. 3.1 adiciona o recurso "classe de script" para GDScript e NativeScript onde os nomes dados aos scripts são registrados globalmente. O GDScript converte manualmente esses registros globais no mecanismo em variáveis ​​globais na linguagem.

Então, se você tiver o recurso Script , você pode chamar métodos estáticos no script ou chamar .new() para obter um ScriptInstance e então chamar funções de membro / acessar variáveis ​​de membro. Se o Script estiver derivando Objeto, Referência, Recurso ou outro tipo não-nó, basta criar uma instância do Script / ScriptInstance será tudo o que você precisa para obter o conteúdo estático/não estático. Se for um Node, o mesmo se aplica, exceto para coisas que exigem acesso à SceneTree (como get_node ) nesse caso você terá que usar add_child para adicioná-lo à SceneTree primeiro.

Todos os itens acima se aplicam a qualquer linguagem de script usada com Godot (embora o pré-carregamento seja uma operação específica para certos idiomas, acredito...).

o script por caminho de arquivo. 3.1 adiciona o recurso "classe de script" para GDScript

Quando o 3.1 será lançado oficialmente?

@MysteryGM Quando a porcentagem de conclusão do marco é alta o suficiente / quando os desenvolvedores principais julgaram que o progresso está longe o suficiente para considerar a construção "estável".

Marco: https://github.com/godotengine/godot/milestone/7

Para comparação, 2.1 e 3.0 estão atualmente com 99% de conclusão. Não tenho certeza se esse é o status em que eles estavam quando foram ao vivo.

Basicamente, a resposta é "quando estiver pronto".

Obrigado pelas respostas e pedimos desculpas por tomar seu tempo.
Parece que Godot não atende às nossas necessidades no momento. Talvez no futuro tenhamos a chance de usar o motor novamente.

Se eu quiser que Fogo queime Madeira, eu tenho que ter Madeira->estender->Fogo ou Fogo->estender->Madeira.

@MysteryGM
Veja aqui .
A solução (não importa o mecanismo ou idioma) pode ser ter um script de "sistema" que controle as interações entre incêndios e florestas. Essa apresentação se concentra em componentes, mas também é possível fazer um sistema trabalhando com objetos.

Em C# eu poderia dizer que Wood implementa IBurnable que Fire usa.

Olá, obrigado pela preocupação contínua e estamos muito gratos pelo suporte @willnationsdev . Acreditamos que os scripts como solução de recursos de exportação tem muito potencial. Conforme mencionado em #22660.

Como ainda temos 10 dias para decidir qual motor usar, estamos tentando um pouco mais com Godot.
Estamos analisando os problemas de fluxo de trabalho e acredito que nosso programador disse melhor:

"Os desenvolvedores Godot mantêm cada problema no Github em seu próprio post, sempre abrem um problema para um bug , mas não permitem o mesmo fluxo de trabalho para seu mecanismo."
O fato de termos que fazer um script E somos forçados a adicioná-lo à hierarquia.

script de "sistema" que controla as interações entre fogo e mata. Essa apresentação se concentra em componentes

Sim, é isso que queremos, como fazemos isso no GDscript?

Em C# eu poderia dizer que o Wood implementa o IBurnable que o Fire usa.

Godot tem Duck digitando para fazer a mesma coisa que Interfaces. O que queremos é que Burning seja uma classe separada para que possamos reutilizá-la, sem nos forçar a adicionar um nó à hierarquia.

O que queremos é Fogo, Queima, Madeira. Não queremos Fogo (Madeira+Queima).
A vantagem desse fluxo de trabalho é que podemos depurar o Burning por conta própria, sem a necessidade de corrigir todos os objetos que podem ser gravados.

Em C# vamos apenas declarar Burning como sua própria classe. Classe pública Burning e nosso problema está resolvido.
Em C++ incluiríamos Burning e problema resolvido.

Sim, é isso que queremos, como fazemos isso no GDscript?

@MysteryGM

Sem mergulhar nas otimizações de desempenho, tudo o que estou sugerindo é mover a resolução da interação para um script de sistema separado (não no fogo, não na madeira). O sistema no caso mais simples pode conter arrays de todos os objetos do mundo e lidar com suas interações. Nesse caso, os objetos não precisam se preocupar com tipos, apenas o sistema se importa.

Para tornar as coisas mais rápidas, pode-se apenas realizar verificações para objetos que realmente colidiram (por exemplo, enviando um signal do objeto para o sistema quando a colisão ocorrer).

Alguns exemplos específicos de GDScript para referência cruzada de script (para a versão 3.0):

Aqui Enemy atua como o tipo/interface, pode-se verificar com o operador is :

# Cache the enemy class.
const Enemy = preload("enemy.gd")

# Use 'is' to check inheritance.
if (entity is Enemy):
    entity.apply_damage()

Aqui runnerGame aponta para uma cena _autoload_ (também conhecida como singleton) com caminho /root/runner:

onready var runnerGame = get_node("/root/runner")
onready var runnerScript = preload("res://runner/runner.gd")

func _ready():
    runnerGame.setMode(runnerScript.SPAWN_TITLE)

Aqui conectamos o signal "pressionado" do botão ao manipulador (que pode estar em um objeto e script diferente, estamos usando self para nos referirmos ao mesmo):

func _button_pressed(which):
    print("Button was pressed: ", which.get_name())

func _ready():
    for b in get_node("buttons").get_children():
        b.connect("pressed", self, "_button_pressed",[b])

Veja também os documentos aqui, há mais alguns recursos disponíveis: http://docs.godotengine.org/en/3.0/getting_started/scripting/gdscript/gdscript_basics.html#inheritance

Veja também os documentos aqui, existem mais alguns recursos disponíveis:

Obrigado pela sua participação no tópico. O problema com a herança é que ela só funciona se soubermos todos os relacionamentos das classes quando as implementamos.

Aqui está um exemplo:

Etapa A.
MeshInstance+ HomingScript = HomingMissile .
Mas agora, se eu quiser uma Homing Landmine, tenho um problema.
(MeshInstance+ ProximityScript) = Landmine .
(MeshInstance+ ProximityScript) + HomingScript = ERRO mais de um script
(MeshInstance+ ProximityScript) + (childNode + HomingScript ) = FALHA porque apenas o nó invisível se move.
(MeshInstance+ ProximityScript) + (childNode + ExtendedHomingScript ) = SUCCESS, pois agora estendemos a classe Homing para que ela possa possuir nós do nó filho. Temos HomingLandmine .

Exceto agora, pode-se argumentar que tanto o Homing Missile quanto o Landmine devem se estender de um HomingClass.

Etapa B.
HomingMissile[de Homing]
HomingLandmine[de Homing] [+ ProximityScript] O script agora é copiado e colado na mina terrestre.

Mais tarde, na produção, a mesma coisa acontece com outros scripts que temos.
Etapa C.
Mina terrestre[da Proximidade]
ProximityAlarm[de Proximity] [+ AlarmScript]
// HomingLandmine[de Proximity] [+ HommingScript] // Agora nossa mina terrestre também pode caber aqui.

Portanto, temos que continuar passando pelo StepA para encontrar a herança adequada para o StepB. Ele continua repetindo esse padrão indo além de StepF etc.

Encontramos uma maneira de prolongar o StepA, apenas evitamos adicionar um script ao nó superior e sempre o tornamos um nó Espacial ou primário.
(Spatial + MeshInstance + ProximityScript) + HomingScript = HomingLandmine
Exceto que este é exatamente o mesmo problema, mas com um ParentSpatial mais caro; em vez de childNode.

Peço desculpas por quanto tempo isso é.

@MysteryGM

"Os desenvolvedores Godot mantêm cada problema no Github em seu próprio post, sempre abrem um problema para um bug , mas não permitem o mesmo fluxo de trabalho para seu mecanismo."
O fato de termos que fazer um script E somos forçados a adicioná-lo à hierarquia.
...
O que queremos é Fogo, Queima, Madeira. Não queremos Fogo (Madeira+Queima).
A vantagem desse fluxo de trabalho é que podemos depurar o Burning por conta própria, sem a necessidade de corrigir todos os objetos que podem ser gravados.
...
Em C# vamos apenas declarar Burning como sua própria classe. Classe pública Burning e nosso problema está resolvido.
Em C++ incluiríamos Burning e problema resolvido.

O que você precisa entender é que Godot não funciona de maneira diferente neste caso. Embora a solução seja fazer um sub-nó com seu próprio script (para "Burning" neste caso), você pode simplesmente definir Burning como sua própria classe e incluí-lo/usar através de funções estáticas (ou instanciar e depois usar propriedades/métodos)

  • C++

    • classe Gravando {};

    • inclua "burning.h";

    • Queima::aplicar(madeira, fogo);

    • Gravando *b = Gravando::get_singleton(); b->aplicar(madeira, fogo);

  • C# (editado para alterações de estilo)

    • classe pública Gravando {}

    • usando Game.Burning;

    • Burning.apply(madeira, fogo);

    • Burning b = Burning.Instance; b.apply(madeira, fogo);

  • GDScript (3.1)

    • estende o recurso # burning.gd

    • const Burning = preload("res://burning.gd")



      • na versão 3.0, pode usar um script comum para carregar constantes para todos os estímulos comumente usados.


        estende Referência


        const Burning = preload("res://burning.gd")


        const Molhamento = preload("res://molhagem.gd")


        estende Referência


        const Estímulos = preload("res://stimuli.gd")


        # use Estímulos.Queima ou Estímulos.Umedeça


      • em 3.1, pode apenas usar classes de script. Queima e umedecimento não requerem "inclusão", pois são globais.


        Além disso, se avesso ao uso global, poderia fazer "Stimuli" ser a classe de script com as mesmas declarações constantes, de modo que esteja sempre disponível como um pseudo-namespace.



    • Burning.apply (madeira, fogo)

    • var b = Burning.new()

      b.aplicar (madeira, fogo)

Para uma abordagem Unity/ScriptableObject, pode-se usar os scripts Resource da Godot para o mesmo propósito.

  • configurações podem ser configuradas no Inspetor.
  • "compilações" do recurso podem ser salvas em um arquivo para que certas configurações possam ser trocadas facilmente conforme necessário, mesmo em tempo de execução.
  • O editor cria automaticamente uma instância do Recurso no Nó usando a declaração de cena, portanto, nenhuma atualização manual é necessária. Uma matriz de tais recursos poderia funcionar razoavelmente bem, embora, com o sistema de dicas de tipo de matriz quebrada em 3.1 (espero até 3.2), você teria que escrever um EditorInspectorPlugin para gerar o conteúdo do Inspector corretamente (que é realmente o que estou trabalhando no FileSystemItemList do meu repositório godot-next (aviso, é um WIP inicial), para ser usado no meu repositório Godot-Builder para matrizes de arquivos/diretórios.

script de "sistema" que controla as interações entre fogo e mata. Essa apresentação se concentra em componentes

Sim, é isso que queremos, como fazemos isso no GDscript?

A maneira mais fácil de fazer isso é com um nó/cena de carregamento automático de algum tipo. A razão é que mesmo que você use apenas um nó com toneladas de recursos para todos os diferentes sistemas (para minimizar o número de nós que você está usando), você provavelmente ainda desejará ter acesso a um nó que está na árvore , então que você tenha acesso ao tempo delta, dados de entrada, operações de rendimento (especialmente combinadas com uso de sinal), nós de animação/interpolação/temporizador, a lista continua. Além disso, como um carregamento automático, o GDScript irá gerar novamente uma variável global para o nó para que os "sistemas" possam ser acessados ​​por nome em qualquer lugar em sua base de código (outra substituição adequada para usar uma classe de script neste caso).

Na verdade, tenho uma grande refatoração de um antigo plugin WIP, godot-skills , que gostaria de fazer e acredito que engloba isso e muito mais. Por favor, leia o tópico reddit (desculpe, longo) sobre o tópico. Envolve examinar a viabilidade de usar multithreading coordenado em uma arquitetura de servidor (semelhante à arquitetura subjacente de Godot) para implementar um sistema de interatividade similarmente genérico e reutilizável.

btw, se você quiser conversar em tempo real sobre o assunto, sinta-se à vontade para me enviar uma mensagem no Reddit/Discord/Twitter onde eu uso o mesmo nome de usuário.

@MysteryGM

MeshInstance+ HomingScript = _HomingMissile_.
Mas agora, se eu quiser uma Homing Landmine, tenho um problema.
(MeshInstance+ ProximityScript) = _Landmine_.
(MeshInstance+ ProximityScript) + HomingScript = ERRO mais de um script
(MeshInstance+ ProximityScript) + (childNode + HomingScript ) = FALHA porque apenas o nó invisível se move.
(MeshInstance+ ProximityScript) + (childNode + ExtendedHomingScript ) = SUCCESS, pois agora estendemos a classe Homing para que ela possa possuir nós do nó filho. Obtemos _HomingLandmine_.

Exceto agora, pode-se argumentar que tanto o Homing Missile quanto o Landmine devem se estender de um HomingClass.

Acredito que esteja faltando algo aqui. Afaik, a maneira correta de criar um nó de "comportamento de componente" é aquele que não muda a si mesmo, mas modifica diretamente um nó "destino" onde o destino padrão é o pai. Isso contorna completamente o problema que você está encontrando, se não me engano.

extends Node
var src_target
export(NodePath) onready var dst_target = get_node(dst_target) if dst_target else null
func _notification(p_what):
    match p_what:
        NOTIFICATION_PARENTED:
           src_target = get_parent()
        NOTIFICATION_UNPARENTED:
           src_target = null
func _physics_process():
    # if necessary, can manually assign src_target elsewhere to be NOT a parent
    if src_target and src_target is KinematicBody2D:
        src_target.move_and_slide(...) # do logic to get parameters that move towards dst_target

Algo assim significaria que você não precisa alterar nada simplesmente fazendo um nó com o script ser um filho da coisa que você deseja que tenha o recurso "homing". Você só precisa atribuir o valor da propriedade exportada (na cena ou em tempo de execução) para dizer a ele para onde deve ser inicializado. Outras propriedades exportadas podem ser usadas para modificar o tipo de movimento e essas coisas também podem ser terceirizadas para um Recurso se você quiser ter diferentes "compilações". Novamente, Godot permite que você seja muito flexível com o design da sua estrutura de jogo.

Algumas correções:

 - C#
-   - public class Burning {};
+   - public class Burning {}
    - using Game.Burning;
    - Burning.apply(wood, fire); // is it :: here? I forget...
-   - Burning b = Burning::GetSingleton(); b.apply(wood, fire);
+   - Burning b = Burning.GetSingleton(); b.apply(wood, fire);

O ponto e vírgula após as chaves de fechamento da classe não é necessário. Você usa um ponto para membros estáticos em vez de :: .
Como uma observação lateral, a convenção para acessar um singleton é usar uma propriedade (geralmente chamada Instance ) em vez de um método.

@neikeq Obrigado. Estou muito fora de prática com C#, lol.

Quanto à abordagem "Global Scripts", sou muito contra isso. Isso encorajaria os desenvolvedores a codificar seu jogo de maneiras ruins. Uma pergunta comum dos desenvolvedores de jogos C++ e Java anteriores, quando eles tentam Unity/Unreal/Godot/etc, é "onde está o loop de jogo principal no qual posso escrever meu código?". A adição de tal sistema permitiria que esses desenvolvedores fizessem isso, então eles podem acabar escrevendo código em scripts globais que fazem referência aos objetos que desejam modificar em vez de apenas usar um script em um objeto.

Talvez, em vez disso, pudéssemos melhorar o desempenho do nó Node de barebones para que ele não introduzisse sobrecarga para "componentes" de objetos que mantêm scripts puramente. Ou talvez até um nó simples separado "somente contém scripts".

@aaronfranke

Quanto à abordagem "Global Scripts", sou muito contra isso. Isso encorajaria os desenvolvedores a codificar seu jogo de maneiras ruins. Uma pergunta comum dos desenvolvedores de jogos C++ e Java anteriores, quando eles tentam Unity/Unreal/Godot/etc, é "onde está o loop de jogo principal no qual posso escrever meu código?".

Como mencionei, se alguém fosse avesso a fazer isso (razoavelmente em um projeto grande), não há problema em apenas criar uma classe de script global "namespace" que mantenha constantes de outros scripts para percorrer mais abaixo na hierarquia da API. Estamos falando de scripts apenas aqui, não de referências de nós reais.

A adição de tal sistema permitiria que esses desenvolvedores fizessem isso, então eles podem acabar escrevendo código em scripts globais que fazem referência aos objetos que desejam modificar em vez de apenas usar um script em um objeto.

Este sistema já pode ser implementado por qualquer pessoa na Godot via autoloads (não há "adição" de um recurso sugerido). Além disso, o problema que eles estão encontrando em primeiro lugar é que eles não querem adicionar os próprios sistemas como subnós no mundo (embora eu dê uma sugestão para isso também no comentário de acompanhamento), já que eles ter o nó lá E o script nesse nó, e potencialmente refatorar os relacionamentos entre todos os nós e scripts quando eles perceberem que as coisas devem se mover.

Talvez, em vez disso, pudéssemos melhorar o desempenho do node Node de barebones para que ele não introduza sobrecarga para "componentes" de objetos que mantêm scripts puramente.

De que maneira? A única maneira de fazer isso de forma transparente seria implementar um sistema MultiScript e há uma série de problemas que acompanham esse paradigma. A única outra alternativa que encontrei ao tentar resolver esse problema foi o sistema de características GDScript que sugeri em #23101, que limita os problemas do MultiScript a uma linguagem, mas vem com sua própria série de problemas ainda mais graves.

Ou talvez até um nó simples separado "somente contém scripts".

Assim que corrigirmos o sistema de dicas de tipo de array no 3.2, poderemos fazer isso com apenas...

extends Node
export(Array, Script) behaviors = []

Pode-se até implementar o recurso agora usando um Dicionário (para acessar os scripts pelo nome) e um EditorInspectorPlugin da versão 3.1 para definir uma interface do usuário personalizada quando esses nós são abertos no Inspetor (criar uma interface do usuário de matriz de scripts exportada, mas ter ele adiciona o script com uma chave que corresponde ao nome do arquivo sob o capô).

estende o recurso # burning.gd

Ah, acho que encontrei nosso problema. Nenhuma de nossas tentativas de pré-carregamento foi estendida do recurso. Acho que nenhum de nós sabia que poderíamos criar recursos personalizados.

Também quero salientar que ninguém que compartilhou seus jogos conosco ou que descreveu seu fluxo de trabalho estava estendendo do recurso.
Quase todo mundo estava estendendo o Node. Não faço ideia de quanta diferença isso faz, será necessário executar testes.

FileSystemItemList (aviso, é um WIP inicial)

Definitivamente terá que dar uma olhada nisso.

@MysteryGM

Acho que nenhum de nós sabia que poderíamos criar recursos personalizados.

Sim! Recentemente , adicionei uma seção aos documentos que descreve o processo. :-D

Você pode estender QUALQUER tipo de mecanismo com um script, incluindo Objeto, Referência, Recurso e, claro, Nó (ou qualquer uma das derivações dessas classes). As únicas coisas que não podem ser estendidas são singletons de mecanismo e editor (como OS, Engine ou EditorFileSystem).

Obrigado pela sua participação no tópico. O problema com a herança é que ela só funciona se soubermos todos os relacionamentos das classes quando as implementamos.

De nada. Coloquei herança no final do comentário, pois não é necessária para a implementação do sistema de lenha.
Parece que você já tem uma solução em mente usando paradigmas aos quais está acostumado, e seu problema não é como criar um sistema de lenha, mas como usar os paradigmas favoritos.
Peço desculpas então. Não estou familiarizado com herança GDScript, mas acredito que outros já responderam sua pergunta.

OK, tivemos algum tempo para testar o novo método e descobrimos que funciona perfeitamente. Já conseguimos substituir centenas de nós por scripts; melhorando muito o desempenho.

Considerando que o pré-carregamento de recursos resolve o problema de inclusão de scripts. Também pode ser usado como uma alternativa ao MultiScript e ao ScriptableObject do Unity exportando uma variável de recurso no GDscript.
Combinado com o fato de que os Documentos foram atualizados para explicar os recursos com mais detalhes.
Sem falar que o Godot 3.1 também terá classes de script que devem permitir ainda mais fluxos de trabalho.

Acho que o objetivo original deste problema foi resolvido, e este problema agora pode ser encerrado?

Mais uma vez, quero agradecer a todos por participar da discussão, e especialmente obrigado a @willnationsdev, que forneceu uma grande quantidade de informações sobre o mecanismo Godot.

@MysteryGM Acho que seus pensamentos no início e no final deste tópico podem ser bons para escrever em um blog ou em um rascunho do godot-docs. Acho que a maioria dos usuários iniciais cometem erros de desempenho ao tentar obter uma organização de script complexa, precisamos de boas anotações de "antes" versus "depois" em termos de aprendizado. As lições e padrões que aprendemos nos primeiros tutoriais não se traduzem bem em jogos de larga escala, o que para mim significa apenas que precisamos de mais blogs/conselhos sobre lições de grande escala.

@pgruenbacher , é uma ótima ideia. Há dois problemas para nossa equipe com isso, um apenas dois de nós sabemos inglês a um nível útil e o segundo é que levará muito tempo.

Mesmo assim há uma boa mudança que faremos um blog de desenvolvimento, e anotamos tudo o que descobrimos. É possível que façamos uma entrada no blog "Transição para Godot".

No momento estou trabalhando em alguns tutoriais em PDF "Godot crash course for artist", porque queremos contratar freelancers para a equipe, mas Godot ainda não é muito conhecido.
Esses tutoriais visam apresentar Godot ao artista profissional de jogos.
Assim que terminar, vou compartilhá-los com os outros usuários Godot, vou mantê-los em PDF para começar, porque é mais fácil corrigir erros enquanto ainda estou aprendendo.

@pgruenbacher @MysteryGM Embora não esteja na mesma linha de uma experiência antes/depois com Godot, este problema e algumas perguntas recorrentes relacionadas me levaram a começar a trabalhar em um artigo de práticas recomendadas de design de cena/script para godot-docs. Eu tenho uma filial no meu fork, mas é muito cedo WIP ATM.

Ler tópicos como esse é extremamente desanimador (no sentido de me fazer adivinhar se escolhemos o mecanismo certo). Nosso projeto tem mais de 15.000 LoC e está perfeitamente organizado e funciona muito bem. (não vou entrar em detalhes de pontos específicos porque outras pessoas aqui são muito mais espertas do que eu).
Com isso dito, estou feliz que você vai ficar com Godot, MysteryGM! Def ansioso para ler o blog dev

Meh, na minha opinião, jogos com lógica significativa são melhores com o código
isolado do motor de jogo de qualquer maneira, então não deveria importar o quão
o motor funciona. Meu script de nó é usado principalmente para renderização de interface
e lógica física. A lógica do jogo é uma biblioteca compartilhada compilada separadamente

Na quarta-feira, 14 de novembro de 2018, Aaron-Fleisher [email protected]
escrevi:

Ler tópicos como este é extremamente desanimador (no sentido de
fazendo-me verificar se escolhemos o motor certo). Nosso projeto está bem
mais de 15.000 LoC e organizado perfeitamente e funciona muito bem. (eu não vou
em detalhes de pontos específicos porque outras pessoas aqui são muito mais inteligentes
do que eu).
Com isso dito, estou feliz que você vai ficar com Godot, MysteryGM! Def procurando
ansioso para ler o blog dev


Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/godotengine/godot/issues/23052#issuecomment-438871197 ,
ou silenciar o thread
https://github.com/notifications/unsubscribe-auth/ADLZ9pw2-G0kE19meyi7iSkceAldfAMjks5uvLb4gaJpZM4XelSe
.

@Aaron Fleisher

... fazendo-me adivinhar se escolhemos o motor certo

Se o mecanismo que você está usando agora está funcionando para você, mesmo que você precise fazer alguma solução alternativa, não há motivo para se preocupar. Você pode fazer com que alguns jogadores (ou outros desenvolvedores) questionem sua habilidade/sanidade, mas essa é apenas a realidade do desenvolvimento de jogos. Muitas pessoas apaixonadas falando com autoridade aparente (muitas vezes muito acima de seu nível de habilidade real).

Você é aquele que conhece seus problemas, e você é aquele que terá que fazer o trabalho. Evite ficar paralisado pelo que teria comprado talvez mais 10% a 20% de produtividade. Salve-o para o próximo jogo. Ou não, já que você já investiu muito no aprendizado das ferramentas que já conhece. Sua escolha :)

Não sei, tenho a sensação de que os desenvolvedores da Godot não sabem o que estão fazendo.

Ao usar o Godot 3.0.6 estável pela primeira vez, me deparei com um "Gerente de Projetos" feio e disfuncional. Quando consigo descobrir como funciona (e não é nada intuitivo), o aplicativo trava toda vez que tento baixar um programa de exemplo da Biblioteca de ativos. Às vezes, o aplicativo simplesmente para de responder. Às vezes, o aplicativo gera erros misteriosos de "condição !conectado é verdadeiro". Às vezes, o download trava. E toda vez, um arquivo de 100 MB leva cerca de 10 minutos para ser baixado principalmente, enquanto eu posso baixar 10 GB em outros lugares no mesmo período de tempo. "Repetir" inicia todo o download do zero.

Tenho a sensação de que "estável" aqui significa "vai estragar tudo sempre".

Fale sobre uma primeira impressão decepcionante.

@dejayc Isso é estranho. Eu mesmo nunca tive problemas com o Project Manager (com o 3.0.6 estável ou mesmo o branch master) no Windows 10 ou no meu dispositivo Linux Mint. Eu recomendaria que você criasse um novo problema sobre seus problemas aqui (já que este não é realmente o problema certo para esse tópico), e espero que alguém possa oferecer melhor assistência.

@dejayc
Se todos nós doarmos ao Patreon, o projeto Godot poderia contratar o cara da usabilidade em tempo integral .

Embora eu concorde com você em pontos menores, os mecanismos devem ser escolhidos com base em postagens de marketing nas mídias sociais, quão críticas são suas desvantagens para o projeto específico. E, infelizmente, todos eles têm _muitas_ desvantagens, que são mais profundas do que o nível de superfície da interface do usuário...

Dito isso, abri uma questão de sugestões sobre o Gerente de Projetos, com algum tempo livre, vou trabalhar em algumas melhorias na área.

Eu trabalhei com Unity e Godot e achei o fluxo de trabalho geral e a estrutura muito melhor e intuitiva em Godot (especialmente o modelo de cena em vez de cena/prefab do Unity, o modelo "single-script" em vez dos componentes múltiplos, a velocidade ao baixar/iniciar o mecanismo e exportar e a capacidade de trabalhar totalmente offline).

Existem muitos fluxos de trabalho e modelos possíveis em ambos e nunca é fácil saber qual é o melhor para você.

Esta página foi útil?
0 / 5 - 0 avaliações