Se não levarmos em consideração os lançamentos para Android e uma dúzia de projetos abandonados antes de estarem prontos, então sim, é o nosso primeiro jogo apropriado para mais de uma plataforma. Como tudo começou? Muito simplesmente. Nós trabalhamos em outro projeto, vamos chamá-lo de "projeto A", e trabalhamos há muito tempo quando decidimos fazer um jogo durante alguns meses e usá-lo para treinar nossas habilidades de marketing e, em seguida, imediatamente liberar nosso "projeto A" quando teríamos mais experiência na promoção de jogos. Mas o plano falhou e o "projeto A" foi mantido intocado durante todo o ano. Mas essa história não é sobre o "projeto A", é sobre um jogo lógico chamado "Cubicity: Slide puzzle".

O primeiro rascunho foi o seguinte: gráficos mínimos, interface do usuário mínima e também o mínimo de tudo o possível, o jogo tinha que ser no estilo dos jogos casuais de hoje que inundam o mercado e o Match-3. Como resultado, nosso objetivo ficou assim: os tokens redondos são conectados à figura, sendo movidos com um furto de quatro direções. Quem já jogou o Cubicity sabe que não mudamos completamente a tarefa, mas melhoramos ferozmente outros aspectos, sendo uma equipe de apenas duas pessoas.

Se alguns dos leitores esperam encontrar aqui um segredo para o desenvolvimento bem-sucedido e rápido de jogos, não existe esse segredo. Aqui não compartilhamos ampla experiência ou conhecimento, apenas contamos a história de um projeto de pequena empresa. E ainda não sabemos se é bem sucedido ou não. Mas para muitos de vocês, nossos leitores, esta é uma mensagem do passado enviada pelos desenvolvedores.
Vamos voltar à história de como o Cubicity foi criado. Principalmente, trabalhamos apenas com o Unity e aqui está o conjunto padrão de todo desenvolvedor decente do Unity: Newtonsoft.json, Zenject, Cinemachine, Dotween etc. Como pode ser visto na foto acima, o primeiro protótipo do jogo incluía apenas cubos e batatas fritas. Depois de uma semana pensando em como melhorar o jogo e atrair jogadores, houve um momento eureka ... Procurar alguns personagens cúbicos ou redondos na loja Asset. E assim alguns pacotes de personagens foram comprados sem hesitação. A mesma situação aconteceu com os blocos nos quais os personagens se movem agora. Também uma lista de novos elementos de jogabilidade foi escrita com quase 30 novos itens, dos quais escolhemos coisas neutras, como blocos de redirecionamento / flechas, elevador e teleporte. Decidimos deixar o resto para os novos níveis e apresentá-los um a um em 30 a 35 níveis.

Para ser sincero, não podemos nem lembrar o que nos inspirou a fazer tantos níveis no primeiro passo, mas temos o que temos e, portanto, o primeiro lançamento incluiu 95 níveis. É demais, para dizer a verdade, e lamentamos. Por que se arrepender? Porque o jogo não estava completamente pronto e muitas coisas foram alteradas após o lançamento. Parecia que estávamos presos no Dia da Marmota, porque precisávamos fazer alterações em todos os níveis em 95. Dois meses de trabalho contínuo foram gastos em todos os níveis. Ainda assim, esses níveis não estavam 100% prontos, mas não estávamos longe dali. Nos dias mais produtivos, 10 níveis foram facilmente transferidos da cabeça para o papel e depois para a cena. Mas também houve dias em que você se sente como o Hank Moody, da Californication, que sofre de bloqueios de escritor, e acha que chegou ao fundo, mas o novo dia traz novas idéias.
Quanto ao componente visual, foi um pouco mais difícil. O desenho como na maioria dos jogos é realizado na superfície fora da tela com uma resolução menor que a nativa e combina com a superfície principal, mas a interface do usuário é desenhada sem nenhuma alteração na resolução para melhor clareza e legibilidade. Assim, obtemos o melhor dos dois mundos - nem uma interface do usuário embaçada e nem uma renderização pesada de desempenho no jogo. Após numerosas experiências, escolhemos 2x MSAA + FXAA para antialiasing, porque elas fornecem a melhor imagem com a menor quantidade de recursos. Concluímos razoavelmente que um jogo lógico não precisa de 60 quadros por segundo e decidimos não reinventar a roda e definir o limite de quadros para 30 fps (até os consoles costumam fazer isso). A definição do limite de quadros afeta positivamente não apenas o consumo de energia, mas também o aquecimento do telefone, o que impede que o telefone acelere devido ao superaquecimento.
Em seguida, tivemos que tomar uma decisão difícil, e esses foram os pontos de chegada. Cada vez que o nível era iniciado, os personagens eram escolhidos aleatoriamente dentre os disponíveis para o jogador, por isso seria problemático desenhar uma figura em miniatura de algum personagem. Você pode não acreditar, mas passamos muito tempo resolvendo essa tarefa depois de procrastiná-la continuamente. Cubos nos pontos de chegada não pareciam uma idéia tão terrível, e a pintura em papel ajudou a passar de nível e a trazer todos para o lugar certo. Mais tarde, decidiu-se usar os mesmos caracteres em vez de cubos, mas em tamanho menor. Tornou-se melhor, mas apenas para nós. Alguns dias depois, esses personagens foram transformados e destacados, e ficou muito mais claro quem é quem, mas ainda não satisfatório. A versão final foi adotada um mês depois, por tentativa e erro, e depois duas semanas foram gastas na criação de ícones para os acabamentos. Adeus verão, até breve novamente!

Na nossa humilde opinião, as nuvens eram de aparência bastante agradável. Mas, na verdade, esse é o truque mais simples. Quando decidimos adicionar nuvens, o primeiro pensamento foi criar um vídeo de fundo em 360 °. Essa abordagem falhou, pois para plataformas móveis é desejável ajustar o jogo no tamanho limite para download via LTE. Se quiséssemos que o vídeo não fosse supercomprimido, teríamos que conceder entre 10 e 15 MB. Combinado com a presença de níveis noturnos no jogo com suas nuvens, é demais (toda a compilação final do jogo para Android leva 61 MB). O segundo desejo era escrever nosso próprio sistema para as nuvens. Foi tentador para um desenvolvedor, mas para uma pessoa que queria terminar o jogo o mais rápido possível, não era adequado. A solução surgiu na forma de criar uma textura para a nuvem e criar um sistema de partículas com uma vida útil infinita da partícula, além de um número limitado de partículas em geral. Depois disso, adicionamos tamanhos aleatórios entre duas constantes, juntamente com rotação aleatória. O resultado foi realmente satisfatório, nosso céu estava cheio de nuvens bonitas e não nos fazia chorar olhando para elas.

Sombras no jogo (na versão móvel) consistem inteiramente de quads que são simplesmente organizados à mão, já que não queremos adicionar sombras reais à versão móvel. Um dos motivos é a ausência de sombras suaves nas plataformas móveis com o OpenGLES 2.0 e, é claro, a degradação do desempenho em dispositivos fracos.

Como foi mencionado anteriormente, usamos 2x MSAA + FXAA para anti-aliasing, mas isso não é tudo! Também adicionamos o AmplifyColor ao nosso pós-processamento, pois é um grande trunfo para um dinheiro razoável que permite aplicar diferentes Lut-s no pós-processamento. Um botão selecionado corretamente melhora a imagem. Durante o processo de desenvolvimento, tentamos abordagens diferentes, incluindo a pilha de pós-processamento de unidade padrão, mas na construção seus shaders e opções levaram muito. Algumas soluções eram muito bonitas, mas funcionavam extremamente mal em telefones não muito novos (acredite, se você acha que todo mundo agora tem pelo menos um telefone 'normal', você está enganado. Um grande número de pessoas ainda possui telefones chineses de US $ 40 e se queixa nos comentários de que seu DOOM não está indo bem no lixo deles).
O equilíbrio do jogo nem sempre é fácil de alcançar, e mesmo agora às vezes pensamos que os níveis podem ser muito difíceis, que esses níveis difíceis podem aparecer com muita frequência etc. Depois de nos equilibrarmos, decidimos introduzir ferramentas para facilitar a vida do jogador (voltando, bomba, bloco de gelo, teleporte) e, sim, ficou mais fácil viver, mas não para nós, apenas para futuros jogadores. A quantidade de trabalho e bugs aumentou para nós.
Chegamos ao cardápio do jogo, com nossos poderes diminuindo e regredindo os nervos. A criatividade pisou no freio. Francamente falando, tivemos que nos inspirar em outros jogos, pelos quais agradecemos muito. E finalmente fizemos, a interface do usuário estava pronta em layouts anteriores.

Queríamos estar na moda também. Por isso, decidimos adicionar economia ao armazenamento em nuvem e não nos arrependemos. Essa tarefa não foi a mais fácil, pois em diferentes plataformas existem diferentes provedores de armazenamento em nuvem. No Steam, há o Steamworks; para celular, é o GooglePlay e GameRoom. Então tivemos que unificar o sistema de economia para que ele pudesse substituir a plataforma desejada. Inicialmente, decidimos usar o EasyMobile para esses fins, mas logo abandonamos essa ideia. O plug-in é muito bom e tem um grande número de possibilidades, mas não gostamos muito de trabalhar com armazenamentos em nuvem nativos. Como resultado, escolhemos o Firebase Realtime Database e a autenticação do Facebook. Em resumo, tivemos que passar pelo inferno para fazer tudo funcionar (e não se trata de programação, mas de cerca de 100500 configurações que precisavam ser feitas em locais de aplicativos 100500 e no Facebook, Firebase etc.). Também no banco de dados há limites de tráfego e, para salvá-lo, toda vez que escrevemos, criamos um GUID e o gravamos no banco de dados e no dispositivo. Portanto, se observarmos que os GUIDs no dispositivo e na nuvem correspondem, podemos ter certeza de que não precisamos ler todos os dados da nuvem, mas podemos usar uma cópia local dos dados. Como resultado, a sincronização foi adicionada, mas ... Um dos erros mais estranhos para nós foi o comportamento não óbvio do Firebase Database em alguns casos. Como usamos o Json, serializamos classes para armazenar o estado, mas o Firebase às vezes se comporta de maneira estranha.
Se passarmos um objeto de dicionário para o Firebase, por exemplo:
var dict = new Dictionary<int, SlotState> { { 0, new SlotState() }, { 1, new SlotState() }, { 2, new SlotState() };
Quando o lemos do banco de dados, não obtemos um objeto Json, mas uma matriz de Json (O quê?)
Bem, ok, vamos usar listas em todos os lugares e não teremos problemas, certo? Mas parecia não estar certo.
Se escrevermos no Firebase:
var dict = new Dictionary<int, SlotState> { { 0, new SlotState() }, { 1, new SlotState() }, { 100500, new SlotState() };
Ou até:
var dict = new Dictionary<int, SlotState> { { 0, new SlotState() }, { 1, null }, { 2, new SlotState() };
Quando lemos do banco de dados, obteremos um objeto Json com chaves e valores.
Bem, a lógica dos desenvolvedores pode ser entendida, mas pode levar a erros que podem aparecer depois de um tempo (lembre-se dos GUIDs adicionados para salvar o que mencionamos acima? Como resultado, uma leitura rara do banco de dados com entradas relativamente frequentes) .
Quando é o lançamento? Esta pergunta foi ouvida com mais frequência. Mas era necessário estar bem preparado para esse dia. Tivemos que fazer uma lista de mercados, escolher uma data de lançamento, evitar grandes vendas, havia muitas nuances que atrasaram o lançamento por cerca de 2 meses. Seguindo o conselho de um artigo, escolhemos terça e quarta-feira para o lançamento. Decidimos pedir uma revisão no 4pds, contar sobre o jogo em vários fóruns e divulgá-la nas redes sociais, em particular no Instagram (é claro, por uma taxa). O que resultou de tudo isso, você descobrirá na segunda parte desta história, mas mais tarde.
O que temos no final? Criar um jogo nem sempre é um processo rápido. E é possível que o tempo esperado para o desenvolvimento do jogo tenha que ser multiplicado por 5. Obtenha pessoas que possam ajudá-lo com conselhos práticos em setores desconhecidos. Relaxe em todas as oportunidades, pois criar algo, não apenas jogos, requer muita energia. Não é certo estar próximo da liberação, sentindo-se exausto e menos útil do que no início do projeto. E dinheiro, procure dinheiro, você vai precisar. E de nós, obrigado por sua atenção, boa sorte e até o próximo artigo.