Como a Fika Productions zarpou com seu sucesso multijogador ponto a ponto Ship of Fools

Quando a Fika Productions decidiu preencher a lacuna do mercado para um jogo roguelite cooperativo, eles estavam de olho no modo cooperativo local. E então 2020 aconteceu. Conversamos com o programador-chefe de gameplay, Daniel Carmichael, e o desenvolvedor Yannick Vanderloo para discutir o jogo e explorar alguns dos desafios de desenvolvimento que eles tiveram que resolver para levar Ship of Fools ao mercado em um momento complicado para a indústria.
Qual foi a inspiração por trás de Ship of Fools? Você tem algum colega com formação náutica?
Daniel: Nossa inspiração foi, antes de tudo, preencher a lacuna do mercado para um roguelight cooperativo. Somos todos fãs do gênero roguelite e, embora existam muitos jogos roguelite excelentes, sentimos que nenhum deles fez a parte cooperativa muito bem.
Tematicamente, adoramos a ideia de um barco porque se o barco afunda, todos afundam. Essa é a ideia central: trabalhar em conjunto para manter o barco flutuando. Ninguém tinha experiência náutica e não somos criaturas marinhas nem nada do tipo.
Não há polvos nem cachorros-do-mar salgados na equipe. Entendi. Como é a pesquisa de mercado para você?
Daniel: Nossa pesquisa de mercado foi apenas uma pequena atividade de pesquisa no Reddit , mas obtivemos muito proveito dela. Em 25–30 subreddits sobre co-ops e roguelites locais, fizemos a pergunta “O que você acha que é necessário para ter um jogo roguelite cooperativo bem-sucedido?” Recebemos muitas sugestões, resumimos todas em um documento e buscamos sobreposições e temas. Esse processo validou algumas de nossas ideias e também nos deu algumas novas.
Qual foi seu momento favorito trabalhando em Ship of Fools?
Daniel: Tínhamos uma pequena piada recorrente no escritório. Toda vez que lançávamos um pequeno recurso, alguém dizia: “Temos um jogo!” E, um dia, nós fundimos uma grande parte do jogo que era realmente importante, e eu testei e sempre me lembrarei de dizer à equipe: "Temos um jogo vendável !" e isso foi muito diferente. Esse foi um momento de muito orgulho para nós.
Houve algum aspecto particularmente desafiador no desenvolvimento multijogador do jogo e como você o superou?
Yannick: A rede em jogos geralmente é simples quando o host ou o cliente assume o controle total. No entanto, as coisas ficam complicadas quando o controle precisa ser dividido, como quando alguns elementos são gerenciados pelo jogador local e outros pelo host do jogo.
Projéteis eram particularmente desafiadores nessa configuração. Queríamos que eles fossem rápidos ao serem disparados, e isso envolveu vários cenários a serem considerados. Além disso, quando um inimigo atira de volta e um jogador desvia o tiro, tivemos que planejar meticulosamente as interações e garantir que elas parecessem certas para todos os jogadores, mesmo em situações de alta latência. Havia muitos casos extremos em que pensar. Especialmente como torná-lo rápido e responsivo para ambos os jogadores.
Daniel: Outro grande problema que enfrentamos foi o networking. Passamos um bom ano e meio projetando o jogo para cooperação local, sem nem pensar em jogo online. Então bum! A pandemia chegou. De repente, nosso jogo local não fazia muito sentido, já que todos estavam presos em casa, sem poder sair juntos.
Originalmente, nós queríamos aquela vibe cara a cara, no momento. Esse era o cerne do nosso jogo. Mas com a pandemia, nossa editora pensou: "Ei, precisamos entrar na internet", e nós pensamos: "Tudo bem, vamos fazer isso". E cara, parecia que tínhamos que retrabalhar um ano inteiro de coisas, ajustando cada parte do jogo para o modo online.
Então, uma pequena dica para os colegas desenvolvedores: sempre tenham o jogo online em mente desde o início, mesmo que vocês não estejam 100% envolvidos. Projetar pensando no online geralmente é uma jogada sólida, e é muito mais fácil eliminá-la mais tarde do que colocá-la em prática depois.
Conte-me mais sobre o gerenciamento de projéteis e como o Netcode for GameObjects entrou em ação aqui?
Yannick: Colocar nosso jogo em rede acabou sendo uma reviravolta única. Não temos uma configuração tradicional de Netcode for GameObjects . Em vez disso, temos objetos que existem tanto no lado do cliente quanto do host, cada um ciente das ações do outro e de quem está no controle a qualquer momento. É como se eles estivessem constantemente conversando, atualizando um ao outro sobre o que está acontecendo.
Por exemplo, em um cenário onde uma bala é disparada, se ela atingir o alvo no lado do host, o jogo espera o cliente confirmar o acerto. O cliente pode concordar, ou pode dizer: "Não, eu desviei dessa", ou até mesmo, "Eu refleti a bala!" Dependendo da resposta do cliente, o jogo ajusta o resultado, garantindo que ambos os lados estejam sincronizados.
Essa configuração permite muita flexibilidade. Os jogadores do lado do cliente podem ver reações imediatas às suas ações, como uma bala sendo desviada, fazendo com que o jogo pareça responsivo. No entanto, o resultado final pode precisar de ajustes com base na contribuição do anfitrião, o que pode anular as reações iniciais caso haja alguma discrepância.
É uma espécie de dança, com a autoridade potencialmente mudando para frente e para trás. Descobrimos que a solução mais simples era deixar cada lado fazer o que quisesse e, então, reconciliar as diferenças conforme elas surgissem, com base no feedback do outro lado. É um processo colaborativo, que garante que tanto o anfitrião quanto o cliente contribuam para o fluxo do jogo.
Aqui vai uma explicação visual para seus leitores.

Na primeira imagem, temos nossa configuração multijogador, onde estou jogando como Todd, o anfitrião à esquerda, e meu amigo é Hink, o cliente à direita.

Então, um inimigo caranguejo aparece e lança um projétil. Aqui, tudo é uma questão de coordenação: tanto o host quanto o cliente são informados por meio de uma chamada de procedimento remoto. Ambos os jogadores veem o projétil, mas se ele atinge o barco ou é desviado depende das reações dos jogadores, e o anfitrião precisa esperar a entrada do cliente para confirmar o resultado final.

Por fim, aqui vemos o que acontece quando o cliente, interpretando Hink, desvia o projétil. Há um pequeno atraso se o ping for alto, então, embora o host possa inicialmente ver o projétil atingindo o barco, ele se corrigirá quando a reação do cliente for confirmada. Dessa forma, o cliente não sente atrasos – é como se estivesse jogando em tempo real, e suas ações são espelhadas pelo host para manter o jogo sincronizado.
A ideia é garantir que, quando você estiver no calor do momento, dando um tiro ou se defendendo de um ataque, o jogo responda instantaneamente, fazendo com que a experiência multijogador pareça perfeita.
Alguma outra informação específica que você possa compartilhar? Alguma coisa que nossos leitores possam tirar como uma lição poderosa aprendida?
Daniel: Enfrentamos vários desafios, mas um dos maiores foi sobre gerenciamento de memória. Entender o Assembly e os Addressables foi uma curva de aprendizado íngreme, especialmente porque este foi o primeiro jogo multijogador para toda a equipe.
O engraçado é que nosso jogo nem tem tantos recursos, mas o tempo de carregamento chegou a dois minutos em um ponto, o que é uma loucura para um jogo menor. Isso definitivamente gerou alguma reação dos jogadores.
Então, sim, aprendemos da maneira mais difícil sobre como manter as coisas simplificadas, em termos de memória e ativos. Devíamos ter definido o básico desde o início.
E quanto aos Addressables? O que você aprendeu especificamente lá?
Yannick: O acordo com a Addressables é bem simples. Você precisa organizar seus ativos em grupos que façam sentido para serem carregados juntos ao mesmo tempo. Dessa forma, você não vai atrapalhar seu jogo com coisas que nem está usando em uma cena específica.
Por exemplo, nosso jogo tem diferentes setores, cada um com seu próprio conjunto de inimigos, cenas e cenários. Inicialmente, juntamos tudo em um grupo enorme, o que era um pesadelo para os tempos de carregamento. Para simplificar as coisas, começamos a agrupar os ativos por setor. Isso fez uma grande diferença porque agora podemos carregar apenas os inimigos ou apenas o cenário de um setor conforme necessário, tornando tudo muito mais eficiente e suave no final.
Por que você escolheu o Netcode for GameObjects (NGO) para networking?
Yannick: Optamos pela ONG para fazer networking principalmente porque ela é apoiada pela Unity. Isso significa que é provável que ele evolua junto com a plataforma e obtenha suporte de longo prazo, o que é crucial para nós. Além disso, a NGO tinha todos os recursos que precisávamos.
O principal que queríamos era uma conexão ponto a ponto para evitar custos de servidor, o que pode ser um grande problema para um jogo cujas vendas futuras e base de jogadores são incertas. Com a ONG, sentimos confiança de que estávamos fazendo uma aposta segura tanto para nossas necessidades atuais quanto para o desenvolvimento futuro. Parecia uma escolha inteligente permanecer no ecossistema Unity e garantir suporte de longo prazo para o nosso jogo.
O que vem a seguir para Ship of Fools?
Até agora, lançamos duas grandes atualizações, repletas de conteúdo novo, e lançamos dois DLCs, apresentando novos personagens para variar as coisas. Esses DLCs são totalmente opcionais, dando aos jogadores mais opções sem fazê-los se sentirem excluídos caso decidam não obtê-los. A parte legal? Essas grandes atualizações de conteúdo foram por conta da casa e, pelo que vimos, as pessoas realmente gostaram delas.
Quanto ao que vem a seguir, temos planos, mas precisamos mantê-los em segredo por enquanto. No entanto, quando estivermos prontos para revelar novidades sobre atualizações futuras, você certamente ficará por dentro.
Interessado em desenvolvimento multijogador? Explore a seção multijogador no Relatório Unity Gaming de 2024 para obter insights de estúdios de sucesso, dados atualizados sobre por que mais estúdios estão desenvolvendo jogos multijogador e muitas dicas para ajudar você e sua equipe a se manterem à frente.