GUI imediata - sim ou não? [fechadas]

39

Eu tenho trabalhado no desenvolvimento de aplicativos com muitos sistemas GUI "retidos" (abaixo, mais sobre o que quero dizer com isso), como MFC, QT, Forms, SWING e várias estruturas de GUI da Web há alguns anos. Eu sempre achei os conceitos da maioria dos sistemas GUI excessivamente complicados e desajeitados. A quantidade de eventos de retorno de chamada, ouvintes, cópias de dados, algo a ser entendido - conversões (e assim por diante) sempre foram uma fonte de erros e dores de cabeça em comparação com outras partes do aplicativo. (Mesmo com o uso "adequado" de modelos / associações de dados).

Agora estou escrevendo jogos de computador :). Eu trabalhei com uma GUI até agora: Miyagi (não conhecida, mas basicamente a mesma ideia que todos os outros sistemas).

Foi horrível.

Para ambientes de renderização em tempo real como Games, sinto que os sistemas GUI "retidos" são ainda mais obsoletos. As interfaces do usuário geralmente não precisam ter layout automático ou ter janelas redimensionáveis ​​dinamicamente. Em vez disso, eles precisam interagir de maneira muito eficiente com dados sempre em mudança (como posições 3D de modelos no mundo)

Há alguns anos, deparei-me com "IMGUI", que é basicamente como um modo de gráficos imediatos, mas para interfaces de usuário. Não dei muita atenção, pois ainda estava no desenvolvimento de aplicativos e o próprio cenário da IMGUI parecia não ser muito amplo nem bem-sucedido. Ainda assim, a abordagem adotada parece ser tão sexy e elegante que me fez querer escrever algo para o próximo projeto usando esse modo de interface do usuário (não consegui convencer ninguém no trabalho: (...)

deixe-me resumir o que quero dizer com "retido" e "imediato":

GUI Retida: Em uma fase de inicialização separada, você cria "controles da GUI", como Rótulos, Botões, Caixas de Texto, etc., e usa alguma maneira descritiva (ou programática) de colocá-los na tela - tudo antes de qualquer coisa ser renderizada. Os controles mantêm a maior parte de seu próprio estado na memória, como localização X, Y, tamanho, bordas, controles filho, texto da etiqueta, imagens e assim por diante. Você pode adicionar retornos de chamada e ouvintes para se informar sobre eventos e atualizar dados no controle da GUI.

GUI imediata: A biblioteca da GUI consiste nas funções "RenderButton", "RenderLabel", "RenderTextBox" de uma só vez ... (editar: não se confunda com o Renderprefixo. Essas funções também executam a lógica por trás dos controles, como pesquisar entradas do usuário, inserir caracteres, manipular a velocidade de repetição de caracteres quando o usuário mantém pressionada uma tecla e assim por diante ...) que você pode chamar para renderizar "imediatamente" um controle (não tem que ser imediatamente gravado na GPU. Geralmente é lembrado para o quadro atual e classificado em lotes apropriados posteriormente). A biblioteca não possui nenhum "estado" para eles. Se você deseja ocultar um botão ... simplesmente não chame a função RenderButton. Todas as funções do RenderXXX que possuem interação do usuário como botões ou caixa de seleção têm valores retornados que indicam se, por exemplo, o usuário clicou no botão. Então o seu "RenderGUI" A função se parece com uma grande função if / else, na qual você chama ou não as funções RenderXXX, dependendo do estado do jogo e toda a lógica de atualização de dados (quando um botão é pressionado) é entrelaçada no fluxo. Todo o armazenamento de dados está "fora" da GUI e passado sob demanda para as funções Renderizar. (Obviamente, você dividiria as grandes funções em várias ou utilizaria algumas abstrações de classe para agrupar partes da GUI. Nós não escrevemos código como em 1980, não é?

Agora eu descobri que o Unity3D realmente usa a mesma abordagem básica para seus sistemas GUI embutidos. Provavelmente existem algumas GUIs com essa abordagem também?

Ainda .. ao olhar em volta, parece haver um forte viés em relação aos sistemas GUI retidos? Pelo menos eu não encontrei essa abordagem, exceto no Unity3D, e a comunidade IMGUI original parece bastante ... silenciosa.

Então, alguém trabalhou com as duas idéias e tem uma opinião forte?

Edit: Estou mais interessado em opiniões que resultam da experiência do mundo real. Eu acho que há muitas discussões acaloradas no fórum IMGUI sobre qualquer "fraqueza teórica" ​​da abordagem imediata da GUI, mas sempre acho mais esclarecedor saber sobre as fraquezas do mundo real .

Imi
fonte
Obrigado pelo link. Eu acho que você está se referindo ao comentário de Kylotan . Interessante ..;)
Imi
1
Hah, eu estava no meio de escrever uma resposta abaixo quando noto que minha opinião já foi vista ... ainda assim, eu a publicarei de qualquer maneira.
Kylotan
2
É uma pena que essas perguntas estejam sendo encerradas! Esse é o tipo de opinião que estou procurando quando tenho a mesma pergunta.
Harald Scheirich 11/11

Respostas:

34

Não. Eu fiz um trabalho pago com gamedev em uma horrível GUI de 'modo retido' e em uma terrível GUI de 'modo imediato' e, embora ambos tenham me feito querer arrancar meus olhos, a abordagem do modo retido ainda é claramente a melhor.

As desvantagens do modo imediato são muitas:

  • eles não facilitam a configuração de layout por artistas e designers;
  • eles fazem você misturar lógica com apresentação;
  • eles tornam mais difícil ter um único modelo de entrada consistente;
  • desencorajam controles complexos de dados dinâmicos (por exemplo, exibições de lista);
  • as camadas ficam muito estranhas (por exemplo, se eu chamar RenderComboBox, a caixa suspensa ainda não pode ser renderizada porque precisa ir acima do resto da janela - o mesmo para as dicas de ferramentas) l
  • configurar o estilo de renderização acaba sendo feito com argumentos globais (ick) ou funções extras (ick);
  • o desempenho pode ser ruim porque chamar todas essas funções para consultar valores que podem ou não ter sido alterados tende a criar muitos objetos pequenos, estressando o gerenciador de memória;
  • ... e nem consigo imaginar como seria doloroso permitir que alguém arrastasse os bits da GUI e os reordenasse. Você precisaria manter uma estrutura de dados informando onde renderizar tudo - o que é como reescrever um sistema de modo retido.

As GUIs de modo imediato são tentadoras para programadores solitários que desejam um sistema rápido de HUD e, para esse efeito, são ótimos. Para qualquer outra coisa ... basta dizer não.

Kylotan
fonte
1
@ImmanuelScholz: Você considerou que talvez as GUIs retidas não sejam "tão feias"?
Nicol Bolas
1
As bibliotecas da GUI tendem a ser deselegantes porque abordam várias preocupações - entrada, renderização e acesso a dados - e cada uma delas é fortemente influenciada pelo restante do programa. Isso significa que as pessoas adicionam camadas de abstração para tornar a GUI reutilizável em diferentes programas, dispositivos de entrada e renderizadores, com o custo de torná-la mais complexa de usar.
Kylotan
2
Acrescente a isso o fato de que não há consenso sobre como criar GUIs de modo retido (MVC, MVP e MVVM são três abordagens populares) ou como apresentá-las (dos dados? Do código?) Ou como anexar o comportamento de entrada ( script embutido, como na Web? Sinais / slots nomeados? Resultados no local como IMGUIs?) e essa falta de padronização impediu o desenvolvimento de One True Way for GUIs.
Kylotan
2
A configuração do layout por um artista requer um editor, independentemente de você estar usando uma GUI retida ou imediata. Este ponto é completamente inválido. Misturar lógica e apresentação é a razão pela qual você usa a GUI de modo imediato, que não é uma falha, é o que você deseja, em oposição à bagunça que é mantida mais GUI. Você nem entende isso. A configuração não requer argumentos globais ou extras se a API for bem projetada. Todas as desvantagens mencionadas são solucionáveis ​​em uma questão limpa. Mais importante ainda, você está escrevendo uma interface do jogo, não o Photoshop.
Dreta
3
@dreta: meu argumento sobre a configuração do artista é que existem coisas que são completamente impraticáveis ​​de serem alteradas por meio de um editor sem basicamente escrever sua própria camada de modo retido sobre ela (por exemplo, o que fazer quando um botão é clicado ou reordenar elementos). IMGUI funciona bem para visuais muito simples e triviais, nada mais.
Kylotan
31

Como alguém com cinco ou seis anos de experiência real com IMGUI na área de trabalho, sinto-me obrigado a defendê-lo. Todas as respostas (e a própria pergunta) são baseadas em uma definição muito restrita de IMGUI, e parece haver muitas reivindicações questionáveis ​​sendo feitas.

Muito disso se origina da suposição de que uma biblioteca IMGUI não pode reter nenhum dado oculto. Isso não é verdade. De fato, uma sofisticada biblioteca IMGUI reterá tantos dados quanto uma biblioteca RMGUI equivalente. A diferença é que uma biblioteca IMGUI armazena em cache os resultados, enquanto uma biblioteca RMGUI mantém o estado autoritativo. No IMGUI, o aplicativo fornece uma função que pega o estado atual do modelo e produz uma GUI para esse estado. Esta é a definição oficial da GUI. A biblioteca é responsável por garantir que a GUI na tela corresponda ao resultado dessa função. Isso não significa que ele precise avaliar totalmente essa função em cada quadro e reconstruir completamente a GUI. Esse é o ponto do cache.

Com essa visão do IMGUI, é possível fazer um layout avançado e o desempenho é bastante razoável. Você também pode manter o estado autoritativo real se facilitar a interface. O objetivo da IMGUI não é fazer com que o aplicativo retenha tudo. O aplicativo provavelmente não deseja armazenar a posição de todas as barras de rolagem e o estado expandido / recolhido de cada nó da árvore. O objetivo é ser capaz de especificar procedimentalmente o conteúdo desses nós da árvore e sua própria existência.

Gostaria de responder e responder a todas as críticas da IMGUI, ponto por ponto, mas não as entendo muito. A maioria deles parece resultar de alguma crença fundamental de que o IMGUI é hackish e o RMGUI é bem estruturado, o que eu acho que deriva dos mal-entendidos acima. Não há nenhuma razão inerente para que as bibliotecas IMGUI tenham problemas com a complexidade ou tenham que estar repletas de globais ou misturar lógica com apresentação. Eu direi que as vantagens do IMGUI se tornam menos importantes quanto mais o conteúdo é direcionado ao artista, mas não sei por que seria realmente pior para o conteúdo direcionado ao artista. (Eu não uso pessoalmente conteúdo direcionado a artistas, além de folhas de estilo para coisas como cores, tamanhos de fonte / borda, etc., mas não vejo por que seria mais difícil de implementar do que para RMGUI.)

Na minha opinião, IMGUI é inquestionavelmente uma coisa boa. Ele fornece um modelo muito melhor para o raciocínio sobre sua GUI. Torna-se muito mais funcional e reativo, e você minimiza a quantidade de estado mutável sobre o qual precisa raciocinar. Por outro lado, implementar uma sofisticada biblioteca IMGUI é um grande desafio e definitivamente mais difícil do que implementar uma biblioteca RMGUI equivalente. É uma troca entre a complexidade da biblioteca e a complexidade do aplicativo. Se você planeja criar aplicativos complexos (ou mesmo muitos aplicativos simples), a troca é muito boa. Se você estiver fazendo isso para um único aplicativo, e for bastante simples, provavelmente alcançará seu objetivo mais rapidamente com o RMGUI.

De qualquer forma, boa sorte!

Tom
fonte
5
"Não há razão inerente para que as bibliotecas IMGUI devam ter problemas com a complexidade ou estar repletas de globais ou misturar lógica com apresentação". É muito difícil ver como o botão IMGUI usual chama, por exemplo. "if Button (x, y) then Action" não pode ser chamado de mistura lógica com apresentação. Se você não passar detalhes da renderização para a chamada, não poderá posicioná-la ou estilizá-la (exceto com uma global ou estática) e, se você não processar a lógica do botão imediatamente, não será realmente uma GUI de modo imediato. Você poderia dar um exemplo para explicar?
Kylotan
4
O contexto do OpenGL é uma grande fonte de erros devido à quantidade de estado compartilhado, e mesmo com essa API a mudança foi para o modo retido ao longo dos anos porque o modo imediato não ofereceu a flexibilidade ou o desempenho necessário.
Kylotan
1
Não é a simultaneidade que é o problema, é ter um grande bloco de estado que é compartilhado. As GUIs do modo retido encapsulam o estado relevante com o controle ao qual se aplicam, e esse encapsulamento geralmente é considerado bom por motivos que não precisam ser repetidos aqui. Minhas preocupações específicas estão listadas na minha resposta acima e ainda não vi nenhuma abordagem IMGUI que não sofra com todas elas.
Kylotan
3
Uma folha de estilo CSS também se qualifica como "um grande bloco de estado que é compartilhado"? De qualquer forma, não sei qual é a sua experiência específica com o IMGUI, mas se você estiver interessado em abordagens do IMGUI que não sofrem com esses problemas, recomendamos que você leia minha resposta acima e leia as Fórum IMGUI sobre Molly Rocket. É verdade que não existe uma biblioteca IMGUI pronta para o mercado que você pode baixar e começar a usar em minutos, mas se estiver interessado em criar uma, há informações disponíveis e pessoas dispostas a ajudar.
Tom
1
Folhas de estilo CSS são estado estático; bastante diferente dos contextos OpenGL que são extremamente dinâmicos!
Kylotan
12

A biblioteca da GUI consiste em funções "RenderButton", "RenderLabel", "RenderTextBox" ... que você pode chamar para renderizar "imediatamente" um controle (não precisa ser imediatamente gravado na GPU. Geralmente é lembrado para o quadro atual e classificados em lotes apropriados posteriormente).

Eu chegaria ao ponto de dizer que isso não constitui uma biblioteca de GUI. É apenas um monte de funções de renderização.

Renderizar a GUI é a parte mais fácil de criar uma GUI. Veja uma caixa de texto, por exemplo. Vou assumir o caso mais fácil possível: uma caixa de texto simples de entrada de linha única.

RenderTextBoxapenas desenhará uma caixa de texto. Ele fará uma medição simples do texto e desenhará os glifos na tela. Ele irá não

  • Detecte que o usuário clicou no mouse no controle e mova o cursor para o local apropriado na string.
  • Detecte que o usuário clicou duas vezes no mouse no controle e selecione um bloco de texto.
  • Detecte que o usuário pressionou a tecla "Início" e mova o cursor para a frente do texto.
  • Detecte que o usuário pressionou uma tecla válida e modifique a string de acordo. Se o texto foi selecionado, a parte selecionada será substituída pelo texto inserido.

Eu posso continuar, mas acho que meu argumento é claro. Se você deseja usar RenderTextBoxpara desenhar uma caixa de texto, tudo o que obterá é uma caixa de texto estática e não funcional. Qualquer funcionalidade real deve ser implementada por você.

Fazendo medição de texto e desenhando glifos? Essa é a parte mais fácil do trabalho da GUI. GUI significa "Interface Gráfica do Usuário". As duas últimas palavras, nas quais você recebe informações do usuário e faz algo com ele, são a parte mais difícil.

Os jogadores esperam que os controles da GUI funcionem razoavelmente. Em um ambiente de estilo PC (por exemplo: mouse e teclado), se os jogadores virem uma caixa de texto, eles esperam que ela funcione como uma caixa de texto comum. Eles esperam poder se movimentar nele com as teclas de seta, pular para frente e terminar com home e excluir, selecionar letras nele, etc.

Isso significa que você precisará implementar todo esse código da interface do usuário. Você precisa testar qual controle foi clicado. Você precisará fazer algo com base em qual controle foi clicado. Você precisa ter o conceito de um controle "ativo", aquele que obtém entrada do teclado. Controles diferentes devem responder de maneira diferente a diferentes tipos de interação do usuário.

Basicamente, você precisará de uma TextBoxWindowaula.

Digamos que você esteja implementando uma tela de opções de jogos. Então você tem seus diferentes grupos de opções: jogabilidade, gráficos, som, controles, etc. Então você tem uma lista de diferentes grupos no lado esquerdo da tela. Cada grupo apresenta uma série de controles que o usuário pode manipular. O que acontece quando o usuário pressiona a tecla Tab?

Bem, depende de qual controle está ativo. Se um dos controles do grupo estiver ativo (foi clicado mais recentemente), ele será movido para o próximo grupo. Se, em vez disso, um dos controles dentro do grupo estiver ativo, ele passará para o próximo controle nesse grupo. É assim que o sistema se destina a funcionar.

Portanto, não apenas uma entrada de teclado do processo de controle ativo deve agora cultivar qualquer entrada não processada no controle que a possui . Ou isso, ou os controles devem estar em algum tipo de lista vinculada, para que possa ir e voltar. Isso significa que precisa haver um comportamento padrão em cada controle.

Isso soa cada vez mais como uma GUI mantida, não é? A única diferença é que ... é você quem faz o trabalho duro. O uso de outra pessoa na GUI deve ser uma maneira de fazer menos trabalho. Mas o esforço necessário para fazer uma GUI responder como o usuário espera não é trivial.

Lembre-se: a interface do usuário não é para você, é para seus usuários . É para o jogador. Deve se comportar como eles esperam. E se não, então você falhou.

As interfaces do usuário geralmente não precisam ter layout automático ou ter janelas redimensionáveis ​​dinamicamente.

Esse é um pensamento limitado e limitador.

Eu poderia dar a lengalenga sobre jogos diferentes com diferentes necessidades de interface do usuário, que alguns jogos fazer janelas redimensionáveis precisa e assim por diante. Mas há um problema muito maior.

Seu tipo de pensamento leva ao problema das Batalhas Espaciais Gratuitas.

Se você nunca jogou esse jogo, é um jogo barato, independente e com muita GUI. A jogabilidade real é toda feita na GUI (é um tipo de jogo "configure as unidades e observe-as lutar"). O problema?

A GUI NÃO PODE SER RESCALADA!

Ah, tudo bem se você estiver usando um monitor normal ou tiver uma visão normal. Mas se você é eu, por exemplo, que administra um monitor ridiculamente grande (um tão grande que o Windows amplia o tamanho de todo o texto para poder lê-lo), isso é terrível . O texto é microscópico. Não há como alterar o tamanho da fonte.

É verdade que o GSB é um jogo baseado em GUI, portanto é absolutamente indesculpável para eles. Um jogo GUI-lite provavelmente pode se safar dele.

Nunca assuma que seu usuário está vendo o jogo exatamente como você. Fazer isso é loucura.

Ter um sistema GUI que possa se redimensionar para a resolução do usuário, uma GUI verdadeiramente independente da resolução, exige que o layout faça parte do próprio sistema GUI. Se você não fornecer isso, seu texto aparecerá minúsculo no monitor gigante de alguém. Isso não é uma coisa boa.

Então, eu diria que seu pensamento sobre esse assunto é míope. Você não precisa dessas coisas. Você precisa do que as GUIs mantidas fornecem. Ah, você pode não precisar de tudo que qualquer sistema GUI específico fornece. Mas você precisa disso.

O trabalho padronizado que você precisa fazer para obter dados para o sistema é um preço pequeno a pagar, além de ter uma garantia razoável de que o usuário pode interagir com os controles corretamente e de que ele se redimensionará para atender às necessidades do jogador.

Talvez você consiga se livrar de uma GUI de modo imediato se não receber muita entrada do usuário do player. Mas isso seria tudo.

Nicol Bolas
fonte
5
Por favor, não tome isso da maneira errada, mas posso perguntar novamente se você fala da experiência do mundo real usando realmente uma abordagem GUI imediata no desenvolvimento de um jogo (e como eu li sua opinião: provavelmente a substituindo no meio do desenvolvimento) de frustração;))? A propósito: sua funcionalidade retratada de uma caixa de texto pode ser (e é, por exemplo, no UnityGui.TextField) implementada na classe RenderTextBox. Além disso, nada na abordagem da GUI imediata proíbe o designer de bibliotecas de usar classes para controles da GUI, se apropriado. Apenas o uso seria fundamentalmente diferente.
Imi
1
@Immanuel: "A propósito: sua funcionalidade retratada de uma caixa de texto pode ser (e é, por exemplo, no UnityGui.TextField) implementada na classe RenderTextBox." Você disse que isso RenderTextBoxera uma função , não uma classe. Portanto, sua divisão entre "modo imediato" e "modo retido" parece estar em torno de onde os dados são armazenados, e não de quem os está gerenciando. Nesse caso, você precisa deixar essa distinção mais clara na sua pergunta, pois sugere que uma "GUI de modo imediato" simplesmente desenha coisas na tela. Que ele não pode receber entrada (porque isso exigiria estado persistente) e tal. Então qual é?
Nicol Bolas
1
@ImmanuelScholz: "Não vejo um argumento contra uma" abordagem imediata da GUI "neste" pensei em explicar muito bem: alguém precisa escrever o código . Alguém precisa obter informações, mover o cursor, gerenciar um controle atual, manipular o layout etc. Sua descrição de uma "GUI de modo imediato" perde tudo isso, e tudo isso é importante para qualquer coisa, exceto a mais simplificada baseada em resultados. GUI. Portanto, não vejo o seu argumento de que a "abordagem imediata da GUI" tem alguma vantagem .
Nicol Bolas
1
Desculpe minha culpa. "... implementado dentro da função RenderTextBox" (não classe). Ele é uma função e faz a entrada do usuário processo e a biblioteca fazer prender alguns estados (como o controle focado atual). Por favor, sem intenção de ofender, mas posso assumir que você conhece apenas "GUI imediata" da minha publicação aqui e nem analisou a IMGUI nem a Unity3D? Eu certamente não compreendi de maneira abrangente o que uma "GUI imediata" contém em detalhes aqui, só queria resumir, para não falar de coisas totalmente diferentes (por exemplo, para não ficar confuso com o "modo gráfico imediato").
Imi
2
@ImmanuelScholz: "Eu certamente não compreendi de forma detalhada o que uma" GUI imediata "contém em detalhes aqui". Então sua pergunta está incompleta. De fato, é bastante enganador, porque "modo imediato" implica falta de estado. O termo "retido" vem do fato de ter estado. Portanto, se uma "GUI de modo imediato" retém o estado ... não é o modo imediato.
Nicol Bolas
8

Há um tempo atrás, as IMGUIs também despertaram meu interesse, como teste, escrevi alguns tutoriais para me familiarizar com as técnicas (comece aqui se estiver interessado, mas não é muito mais do que C # / XNA + o 'tutorial' original aqui ) .

Gostei muito das IMGUIs por um curto período de tempo, porque as informações exibidas são sempre atualizadas e corretas (já que não existe um estado que você sempre alimenta com dados reais). Mas no final, perdi o interesse, então normalmente agora uso as GUIs retidas novamente.

No final, pensei que a proximidade da GUI tornava mais difícil separar a GUI dos dados e, às vezes, tentava desacoplar as coisas introduzindo algum estado, quebrando a elegância das IMGUIs. Também não acho que escrever código para GUIs retidas seja mais trabalho do que escrever código para IMGUIs e gosto que as GUIs retidas possam ser disparadas e esquecidas, e gosto muito de eventos :).

No entanto, toda vez que alguém menciona IMGUIs, algo dentro de mim quer tentar de novo e se esforçar mais para acertar, porque realmente há alguma elegância lá dentro, não tenho 100% de certeza se isso sempre facilitará seu trabalho. Eu diria que experimente, talvez tente como eu fiz e escreva alguns tutoriais (acho que a melhor maneira de aprender novas técnicas é explicando-as para outras pessoas).

Roy T.
fonte
8

Eu trabalhei muito com o sistema Unity3D GUI, que funciona exatamente como você descreveu. E devo dizer, odeio isso com paixão.

A abordagem "imediata" funciona muito bem em alguns casos. Primeiro, quando você precisa apenas de alguns botões e etiquetas - pense no atirador HUD, por exemplo. Criá-los com a abordagem "retida" não é muito difícil, mas é super fácil com o UnityGUI. O segundo caso é quando você precisa colocar muitos controles na tela, mas realmente não se importa com o layout. Especialmente quando os controles exatos são conhecidos apenas em tempo de execução. Isso não é realmente útil em nenhum jogo, mas é realmente útil ao criar ferramentas em execução no editor do Unity.

No entanto, qualquer GUI semi-complexa - para um RPG (MMO) ou um jogo de estratégia, por exemplo - inevitavelmente se transforma em uma bagunça horrível de código indecifrável, cheia de casos especiais e quebrando de várias maneiras. Ao criar uma GUI, geralmente você tem um layout bastante específico, que deve funcionar para qualquer resolução e ser capaz de mostrar quaisquer dados que você enviar. Você precisa de coisas como, por exemplo, mover alguns botões para baixo para abrir caminho para textos mais longos. Com a GUI "retida", você pode ter um controle que faz isso automaticamente. Com o modo "imediato", não há controles, então você precisa fazer tudo explicitamente.

Outro problema com o UnityGUI (não tenho certeza se isso acontece com todas as GUIs de modo imediato) é que, por exemplo, uma Button()chamada funciona sem considerar outras chamadas da GUI. Portanto, se um botão estiver em cima de outro, um clique pressionará os dois botões ao mesmo tempo. Definitivamente, não é o que o usuário espera; portanto, isso adiciona outro caso especial a ser tratado.

Para viver com tudo isso, sempre escrevi meu próprio invólucro em torno do UnityGUI que o transforma em um sistema de modo "retido": controles que armazenam seu próprio estado e apenas chamam as GUIfunções necessárias a cada quadro para mim.

Não posso dizer que o modo "imediato" seja definitivamente pior do que o "retido", mas certamente me sinto muito melhor trabalhando no modo "retido".

deixa pra lá
fonte
1
Sim, eu já experimentei todos esses problemas com a GUI do Unity e odeio isso como resultado. É ótimo para HUDs estáticos rápidos, mas é um verdadeiro aborrecimento para qualquer outra coisa.
Kylotan
7

Vou defender o IMGUI aqui porque alguns dos problemas listados anteriormente podem ser resolvidos se você estiver disposto a escrever o código para ele. Além disso, se você escrever o código para ele, terá uma biblioteca robusta que é reutilizável e raramente requer modificações.

  • carregando a GUI do esquema

talvez a princípio pareça que os artistas não tenham muita flexibilidade com o IMGUI, isso foi resolvido ou aprimorado com o carregamento do layout da GUI a partir de um esquema xml ou JSON.

  • camada de menu desenhar chamadas

Se esse problema for resolvido com a classificação, você deverá criar a classe UI Manager que classifique a ordem do sorteio. Resolvi esse problema no C # XNA com painéis móveis que podem ser clicados e desenhados um sobre o outro. Posso postar pseudo-código, se solicitado.

  • caixas de listagem

você pode desenhar strings de uma matriz? você pode definir áreas retangulares a partir da altura e largura das fontes dessas strings? você pode criar uma proporção do tamanho do botão de rolagem pela altura de todos os retângulos adicionados juntos? Então você está no meio do caminho para criar uma caixa de listagem com um botão de rolagem para mover para cima ou para baixo. Eu pensei que seria difícil, mas acabou sendo muito mais simples do que eu pensava. sem buffers, sem estados, sem retornos de chamada envolvidos.

  • separando dados da GUI

não deixe os painéis, botões e caixas individuais conterem os dados. Eu sei que na minha primeira tentativa de IMGUI foi imediata, mas apenas no sentido gráfico. Cometi o erro de reter dados na interface do usuário. Foi quase uma mudança filosófica pensar de maneira diferente sobre onde colocar e modificar dados por meio das alterações na interface do usuário.

  • GUI dos SDKs

esse é o limite e a funcionalidade do código do SDK, não o seu. Acho que a interface do SDK (Hammer, Unity, UDK) é quase um novo idioma para aprender de qualquer maneira. Na verdade, eles são semelhantes a mim como Windows.Forms, ambos são configurados para a mais ampla possibilidade e, portanto, têm um peso extra em complexidade.

e, finalmente, assista a isso> http://mollyrocket.com/861

Bixel
fonte
4

As interfaces do usuário geralmente não precisam ter layout automático ou ter janelas redimensionáveis ​​dinamicamente. Em vez disso, eles precisam interagir de maneira muito eficiente com dados sempre em mudança (como posições 3D de modelos no mundo)

Depende do gênero e do jogo em questão. Um bom sistema de gerenciamento de inventário é vital para quase todos os RPGs. Você deseja algo que lide com layouts para você, suporte barras de rolagem, arraste e solte, dicas de ferramentas e outros recursos muito mais fáceis de implementar usando a GUI retida.

Não consigo pensar em uma maneira de arrastar e soltar com uma GUI imediata que não exige muito malabarismo ou economia de estado do usuário, como alterar temporariamente o buffer Z e armazenar informações de tempo para descartar um clique que moveu um pouco.

Mas, da perspectiva do design, tenho problemas para imaginar um mundo sem os meus eventos GUI. Uma GUI imediata também não é compatível com o OOP, forçando-o a recorrer à programação procedural.

A simplicidade proporcionada pelas GUIs imediatas tem o custo de complexidade adicional no seu código, que cresce rapidamente à medida que a complexidade exigida pela interface do usuário aumenta; onde, como uma boa GUI retida, é mais complexo originalmente, mas dimensiona melhor. Portanto, abaixo de um certo ponto de complexidade, uma GUI imediata é adequada, mas para a maioria das situações, prefiro uma GUI retida.

ClassicThunder
fonte
1
Quero lhe perguntar: sua opinião vem da experiência real do mundo real ou do pensamento teórico, observando os dois sistemas? Uhm .. isso parece mais duro do que o pretendido, desculpe .. O que quero dizer é: eu compartilho sua opinião e avaliação de um aspecto teórico . Os sistemas semelhantes a IMGUI provavelmente levam a menos código OOPish (se isso é uma preocupação), eles têm problemas com controles que exigem algum estado e assim por diante. Seus sistemas GUI só ... normais também são muito grandes e complexos já por eles mesmos, então você tem um monte de complexidade para adicionar até que você sequer chegar perto de estes sistemas ..
Imi
1
Emanuel, você não precisa ter experiência em desenvolvimento no mundo real para saber que muitos jogos precisam de layout automático e janelas redimensionáveis.
Kylotan
1
@Immanuel Scholz Admito que tenho muito mais experiência com interfaces de usuário retidas; mantendo um como um OSS projeta e tendo trabalhado com eles embora meu portador (que reconhecidamente é muito jovem). No entanto, usei o sistema de interface do usuário do Unity3D e o duplicei quando mudei para o XNA. Minha interface de usuário retida foi desenvolvida porque eu me cansei de copiar e colar o mesmo hack de projeto para projeto para obter funcionalidade uniforme.
ClassicThunder
@Kylotan por "janelas redimensionáveis", quero dizer que você pode redimensionar ativamente os elementos da interface do usuário arrastando (ou outros meios) e pelo layout automático que, quando os redimensiona, a interface do usuário se adapta de maneira "agradável", como exibir barras de rolagem, alocar várias linhas para barras de botões e assim por diante. Sim, às vezes vejo isso em jogos, mas é muito mais comum em aplicativos de desktop. Além disso, acho que criar boas interfaces de usuário redimensionáveis ​​também não é a coisa mais fácil para os sistemas GUI retidos.
007 Imi
1
Janelas redimensionáveis ​​e autolayout são praticamente a mesma coisa. No modo de retenção GUIs, cada controle conhece seu tamanho (seja alterado no modo de execução ou não) e o autolayout é basicamente uma verificação de tamanho recursivo. Indiscutivelmente, é mais importante em jogos do que em aplicativos de desktop, porque esperamos GUIs em tela cheia em uma variedade de proporções e em diferentes plataformas.
Kylotan