Fortnite

Fortnite no Android Lançamento Publicação Técnica

06.09.2018
Por Equipe Fortnite

INTRODUÇÃO

Em 9 de agosto, lançamos o Beta do Fortnite para Android em dispositivos selecionados dos nossos parceiros da Samsung. Alguns dias mais tarde, começamos a enviar convites para um grupo de proprietários de dispositivos móveis Android abrangendo uma variedade de fabricantes de aparelhos. Aprendemos muito com o beta sobre desempenho, segurança, compatibilidade de dispositivo e sobre como disponibilizar o Fortnite no Android usando o Instalador do Fortnite. Vamos nos aprofundar nos detalhes técnicos por trás do lançamento, no que estamos trabalhando e no que vemos para o futuro próximo do Android.  

ESTATÍSTICAS

Nos primeiros 21 dias após o lançamento do Fortnite no Android, vocês mostraram muito interesse, com mais de 23 milhões de jogadores participando do beta para Android e mais de 15 milhões de jogadores instalando nosso aplicativo.  Apesar de estarmos em uma fase em que é necessário ser convidado para jogar no Android, nossa conversão de jogadores convidados para aqueles que jogam é parecida com a do beta para iOS. 
 

HARDWARE, OTIMIZAÇÃO 


Apresentação Técnica

Implementar o mesmo jogo em todas as plataformas com suporte para partidas entre plataformas diferentes foi um desafio sem igual. Geralmente, para tentar balancear um jogo para dispositivos móveis, basta simplificar o conteúdo e até mesmo o design para caber dentro dos limites de desempenho da plataforma. Por exemplo, é possível eliminar objetos mais próximos da câmera para reduzir chamadas de desenho. No Fortnite, jogadores de Android podem jogar em uma mesma partida com amigos no PC e no console, então precisamos renderizar tudo que afete a jogabilidade.

O caminho até o lançamento no Android

Desde janeiro de 2018, temos trabalhado duro na versão do BRFN para Android com uma grande equipe. Apesar termos passado boa parte do tempo renderizando desempenho, estabilidade e memória, a quantidade e variedade de hardware de Android, versões de SO e versões de drivers foi um grande obstáculo a superar.

Trabalhar com parceiros foi crucial para lançar o Fortnite para Android. Sem o conhecimento, perícia e trabalho duro deles, isso não teria sido possível.

Trabalhamos de perto com a Samsung para traçar um perfil e otimizar o Fortnite para seus dispositivos. A Samsung enviou engenheiros a vários escritórios da Epic ao redor do mundo, trabalhou diretamente com nossos engenheiros em otimizações e análises de desempenho, e contribuiu para várias mudanças no código, especialmente no renderizador Vulkan. Usando telefones de teste equipados com instrumentos e ferramentas internas de engenharia, eles puderam nos dar uma ideia de quais seriam os grandes gargalos no desempenho e na memória e como resolvê-los. Também trabalhamos com a Samsung para criar o processo de instalação mais contínuo e seguro possível para usuários de celulares Samsung.

Engenheiros do Google também nos visitaram in loco para criar um perfil e otimizar o Fortnite, nos ajudando a identificar as principais otimizações, vazamentos de memória e ajudando a determinar um bom ritmo de implementação de quadros para a OpenGL no Android. Os engenheiros do Android no Google são muito talentosos e animados em tornar o ecossistema Android incrivelmente propício para jogos e em aprimorá-lo constantemente.

Além disso, pudemos trabalhar com vários outros parceiros para testar e otimizar o Fortnite, incluindo ARM, Qualcomm, Imagination Technologies, Razer, HiSilicon e muitos outros.
 

Fragmentação

O ecossistema Android consiste em telefones produzidos por vários fabricantes diferentes. Cada telefone é projetado ao redor do Sistema-em-um-chip (SOC) que inclui uma configuração de núcleos de Processador e de GPU. Há várias famílias diferentes de SOCs comuns, como o Snapdragon da Qualcomm (71% dos dispositivos suportados atualmente) que contém uma GPU Adreno, o Exynos da Samsung, a série MT da MediaTek e a série Kirin da HilSilicon, todas contendo GPUs ARM Mali. Cada dispositivo tem uma versão ligeiramente diferente do sistema operacional Android e a maioria dos fabricantes personaliza o escalonador e os recursos de gerenciamento de energia. Dispositivos com a mesma GPU também são lançados com versões diferentes de drivers de placa gráfica. Na prática, o resultado é que dois dispositivos que compartilham o mesmo hardware estrutural podem ter características de desempenho bem diferentes e estão sujeitos a erros diferentes.

Estamos felizes em ver  que a adesão à versão mais recente do Android é muito maior do que antecipamos para dispositivos de até 2 anos. Atualmente no nosso Beta, com requisitos de dispositivo mais altos, vemos que mais de 92% dos usuários de Fortnite estão jogando no Android 8 (Oreo) ou mais recente, cerca de 8% no Android 7 (Nougat) e menos de 0,5% estão jogando uma versão do Android lançada em 2015 ou mais antiga. Há uma queda significativa de jogadores em dispositivos lançados há 2 anos ou mais. Nesses dispositivos, os fabricantes precisam lançar atualizações personalizadas e, na maioria dos casos, precisam coordenar com várias operadoras sem fio ao redor do mundo para desenvolver e lançar essas atualizações.

Para gerenciar essa diversidade, usamos o sistema hierárquico de perfil de dispositivos no Unreal Engine. Começamos criando quatro perfis de desempenho: Baixo, Médio, Alto e Épico. Esses perfis ajustam as configurações de escalonamento no engine para permitir que o jogo funcione em dispositivos com diferentes características de desempenho. O perfil Baixo reduz ao máximo a distância de visão e desabilita todos os recursos gráficos opcionais. O Épico habilita tudo: sombras, vegetação e a maior distância de visão suportada pelos dispositivos mais recentes.

Além disso, temos um conjunto de perfis de GPUs, p. ex.: Adreno 54x e Mali G72. Esses perfis de GPU escolhem o perfil de desempenho mais apropriado para as capacidades do hardware, além de permitir otimizações e soluções personalizadas para o hardware. Por fim, temos um conjunto de perfis de dispositivos específico, p. ex.: Samsung Galaxy Note 9 Adreno e Google Pixel 2 XL. Essa última camada de perfis de dispositivos nos permite habilitar ainda mais soluções e otimizações em dispositivos específicos quando necessário. Analisamos as propriedades na inicialização, como modelo do dispositivo, versão do SO e a versão do driver gráfico, para determinar qual perfil de dispositivo será aplicado.
 

Desempenho de Renderização

O custo de processador para a renderização é de longe o maior gargalo de desempenho na hora de manter uma taxa de quadros estável. Gastamos muito mais tempo de processador no driver gráfico no Android do que no PC, console e iOS. Apesar dos dispositivos Android mais recentes, como a versão Adreno do Galaxy S9, conseguirem lidar com mais de 1.500 chamadas de desenho por quadro, dispositivos mais antigos são bem mais limitados. Dispositivos com especificações médias suportados pelo Fortnite precisam lidar com uma média de 600 chamadas de desenho, enquanto que dispositivos com especificações baixas precisam lidar com uma média de quase 400.

Já havíamos reduzido a quantidade de objetos que precisamos renderizar a cada quadro até um limite prático ao lançar o jogo no iOS no começo desse ano, então foi preciso analisar outras opções. Testamos agrupar chamadas de desenho dinâmicas com chamadas de desenho instanciadas e, apesar de oferecer algum ganho, não foi o bastante para compensar a complexidade adicionada ao código.

Várias otimizações do nosso renderizador de OpenGL nos concederam pequenas vitórias, mas uma das maiores vitórias foi uma surpresa para nós e veio a partir de uma das otimizações à nossa memória: buffers uniformes emulados. Esse é um caminho de código que o UE4 suporta há anos e é usado em dispositivos OpenGL ES2 que não têm suporte nativo para buffers uniformes (ou buffers constantes). Ele funciona da seguinte maneira. No momento da compilação do sombreador, identificamos todas as constantes necessárias para sombreadores e os organizamos em um array a partir do qual o sombreador pode ler. Também armazenamos uma tabela de mapeamento que informa o engine sobre onde coletar constantes de buffers uniformes e onde colocá-los no array constante. Durante o jogo, mantemos buffers uniformes na memória acessível do processador, usamos a tabela de mapeamento para copiá-los para um buffer temporário e carregamos todos os constantes com uma única chamada de função glUniform4fv.

Apesar de não entendermos totalmente o porquê, o caminho de código do buffer uniforme emulado nos poupou bastante tempo no driver. É possível que o driver esteja fazendo algo semelhante internamente e que a nossa implementação seja mais rápida para a nossa carga de trabalho. Também é possível que, já que estamos criando e vinculando menos recursos, o driver simplesmente esteja levando menos tempo na contabilidade do gerenciamento de tempo de vida desses buffers. Seja como for, o caminho reduziu o custo do driver em 10-15% em alguns casos.
 

Vulkan

Vulkan é a mais nova API de gráficos para Android e foi projetada para proporcionar um bom desempenho e acesso de dispositivos de baixo nível. Em 2016, fizemos uma parceria com a Samsung para criar a demo ProtoStar e mostrar as possibilidades com uma API gráfica de alto desempenho no Android. Já que o Fortnite exige tantas chamadas de desenho de objetos a cada quadro, a Vulkan pareceu a escolha perfeita. Infelizmente, não foi tão simples.

O suporte à Vulkan ainda não é obrigatório no Android, então ainda não podemos contar com sua disponibilidade no ecossistema. Por visarmos apenas os hardwares mais recentes, isso não foi um impedimento, mas encontramos vários erros e problemas com o desempenho dos drivers iniciais da Vulkan e, como resultado na maioria dos dispositivos, a OpenGL é mais rápida e estável que a Vulkan. E isso não nos surpreende, visto que a indústria teve uma década para otimizar e solidificar suas implementações da OpenGL. A Vulkan é uma API complexa e levará algum tempo até que possa alcançar o mesmo nível de maturidade.

Dito isso, implementamos o suporte para a Vulkan no Samsung S9+ (Adreno) e no Note 9 (Adreno). Trabalhar em parceria com os engenheiros da Samsung nos permitiu otimizar o suporte à Vulkan no UE4 para que ficasse, em média, 20% mais rápida que a OpenGL. Daqui para frente, continuaremos trabalhando com nossos parceiros de hardware para levar o suporte de desempenho de alto nível da Vulkan a outros dispositivos, oferecendo aos jogadores do Fortnite no Android uma experiência melhor, além de aprimorar o desempenho dos drivers da Vulkan para todos os desenvolvedores.
 

Memória

Memória é um desafio constante. Além da implementação de um jogo completo de console em dispositivos móveis, estamos sempre adicionando novos conteúdos ao jogo. Por isso, estamos sempre buscando otimizações de memória. O Android nos apresenta desafios únicos quando comparado a outras plataformas.

Não podemos visar um único orçamento de memória. Cada dispositivo tem uma quantidade de memória diferente, tipos diferentes de aplicativos sendo executados em plano de fundo e, potencialmente, diferentes políticas para decidir quando encerrar um aplicativo por usar memória demais. Não existe uma API para determinar o orçamento de memória. Durante um teste de memória, iniciamos uma partida e começamos a alocar memória até que o SO encerrasse o processo. Usando telefones recém-redefinidos e sem inicializar nenhum outro aplicativo, conseguimos alocar 3GB do total de 4GB de memória antes de ser encerrado no Samsung Galaxy S8 (Mali). No Google Pixel 2, só conseguimos alocar 1,8GB do total de 3,6GB de memória.

O sistema, especialmente o driver gráfico, aloca muita memória em nosso nome. O UE4 rastreia toda a memória solicitada diretamente ao SO, incluindo uma estimativa da alocação de memória da GPU, mas não temos muita visibilidade quanto a em quê o driver está alocando. Por meio de testes, descobrimos que boa parte da memória que o driver estava alocando ao Fortnite estava sendo usada nos sombreadores.

Buscamos a otimização dos buffers uniformes emulados, mencionada anteriormente, por causa da memória. A OpenGL requer que o aplicativo possa determinar a localização de qualquer membro de buffers uniformes. Por exemplo, pode-se perguntar à OpenGL o deslocamento da matriz LocalToWorld no buffer uniforme Primitivo. Para suportar isso, o driver precisa manter parte dos metadados (p. ex.: uma tabela de deslocamento) na memória que inclui strings para o nome de todos os membros. Ele precisa fazer isso para todos os programas.

No Fortnite, temos uma ampla variedade de sombreadores. Em uma sessão de jogo padrão, o engine usa cerca de 2.000 programas sombreadores diferentes. Dentro de cada um desses programas sombreadores, o driver armazena esses metadados totalizando um gasto muito alto de memória. Economizamos mais de 400MB de memória no Fortnite usando buffers uniformes emulados!

Quando implementamos o Fortnite no Android pela primeira vez, nossos testes internos indicaram que estávamos dentro dos limites de memória dos nossos dispositivos-alvo. Fizemos testes nos quais habilitamos a navegação do Google Maps, fizemos streaming de músicas e nos certificamos de que conseguíamos jogar o Fortnite sem problemas. No entanto, quando lançamos o jogo, percebemos que muitos jogadores estavam passando por travamentos ou estavam com desempenho ruim devido à falta de memória.

Quando um telefone Android fica com pouca memória, ele tenta liberar recursos fechando aplicativos que não estão em uso. No entanto, descobrimos que há vários aplicativos e serviços que são executados em plano de fundo e simplesmente reiniciam quando o SO os fecha. Isso só piora a situação! O Android fecha o aplicativo para recuperar memória, mas ele é reiniciado e começa a consumir tanta memória quanto antes de ser fechado. Pior ainda, iniciar e interromper aplicativos consome tempo do processador, então não só ele não libera memória como acaba usando muitos recursos desnecessários do processador.

Atualizamos nossos processos de teste para instalar e executar mais aplicativos comuns que a maioria dos usuários executa para que possamos encontrar esses problemas mais rapidamente, mas ainda precisamos reduzir o uso de memória... e rápido. Conseguimos restringir o problema aos usuários executando as configurações nos perfis Alto e Épico nos dispositivos Qualcomm Snapdragon mais recentes com 4GB de memória. E como antes, a memória dos sombreadores parece ter sido a principal diferença. Uma ação provisória foi desabilitar as sombras para ajudar a aliviar o problema. Isso reduziu a quantidade de sombreadores necessários pois as variantes não precisam mais procurar e filtrar as sombras do mapa. Também adicionamos um cache LRU para os sombreadores. O cache nos permite manter na memória apenas os programas sombreadores necessários para renderizar a cena atual. Outros programas sombreadores são comprimidos e armazenados na memória. Quando necessário, descomprimimos os programas e os devolvemos ao driver.
 

Futuro: próximos passos

No momento, estamos concentrados em fazer o jogo funcionar bem em todos os dispositivos suportados e resgatar memória suficiente para aprimorar tanto a qualidade visual quanto a estabilidade. No futuro, analisaremos problemas de compatibilidade, como no lançamento do 5.40, onde corrigimos problemas de som que afetavam vários dispositivos e ampliamos o suporte a mais dispositivos. Também pretendemos conceder mais controle aos usuários na hora de ajustar seus dispositivos e pretendemos equilibrar a qualidade e o desempenho.

Continuaremos aprimorando o suporte para a Vulkan e o lançaremos em mais dispositivos ao longo do tempo. Isso significa que continuaremos trabalhando em otimizações com  fabricantes de dispositivos, tanto no UE4 quanto nos drivers deles. No longo prazo, investir em suporte e drivers para a Vulkan nos ajudará a oferecer um desempenho melhor para os jogadores e todos os jogos usando UE4 lançados no Android.

Continuaremos a explorar telefones mais antigos e mais lentos, mas é impraticável tentar suportar telefones antigos demais. A cada ano, telefones top de linha ficam 50% mais rápidos que seus predecessores. A execução do Fortnite é aceitável em telefones lançados há 2 anos, boa em telefones lançados há 1 ano e muito boa em telefones lançados neste ano. Nesse ritmo, mal podemos imaginar como o Fortnite estará em telefones lançados no ano que vem!

image2.png


Por fim, muitas otimizações de código que fizemos ao Engine já foram implementadas no UE4 4.20. As otimizações restantes serão implementadas no futuro lançamento 4.21, e continuaremos compartilhando futuras otimizações com todos os desenvolvedores do UE4.
 

A BATALHA CONTRA OS MALWARES   

Antes mesmo de anunciarmos que o Fortnite seria lançado no Android, fomos informados da existência de sites "Fortnite para Android" não autorizados. Esse tipo de site geralmente contém malwares ou golpes.  Conforme somos alertados sobre esses sites, nós nos dedicamos a removê-los entrando em contato com os próprios sites, os provedores de hospedagem relevantes e quaisquer propagandas ou vídeos que os promovam.  Independentemente de o site estar ou não distribuindo malware, todas as distribuições e supostas distribuições do Fortnite para Android são proibidas. A única fonte legítima do Fortnite para Android é diretamente pela Epic, através do Instalador oficial do Fortnite.
 
Até o momento, a Epic ajuizou ações legais contra 47 sites de "Fortnite para Android" não autorizados, e muitos deles aparentemente são gerenciados pelos mesmos infratores. Continuamos a policiar a situação com o objetivo de tirá-los do ar ou restringir acesso ao ampliar a conexão da Epic com uma rede de parceiros antifraude (incluindo ISPs, empresas de navegadores e de antivírus) que podem implementar um alerta no navegador como o a seguir: 

Image1.png
 
Agimos proativamente na busca por novos sites de malware com uma equipe interna dedicada a essa tarefa. Além disso, também contratamos um IP de terceiros e uma agência de policiamento antifraude para expandir nossos esforços de vigilância. Essa parceria nos permite detectar e monitorar novos domínios registrados com URLs suspeitas para que, caso tornem-se sites maliciosos, a Epic possa tomar as ações apropriadas, incluindo processos legais.

CONCLUSÃO

O Fortnite para Android apresenta vários pioneirismos na indústria: o primeiro jogo de console e PC a ser implementado no Android com suporte total para partidas entre plataformas diferentes e o primeiro jogo de grande sucesso a ser implementado fora da loja Google Play. O empreendimento e o processo de aprendizagem foram enormes, mas a rápida adesão por mais de 15 milhões de usuários de Android é a prova de que essa é uma boa abordagem e de que pode ser muito bem-sucedida. E, mais importante, todo o trabalho técnico que fizemos para o Fortnite no Android será disponibilizado para todos os desenvolvedores do Unreal Engine com o 4.21, para que todos possam se beneficiar desse trabalho.