<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Blog · Game Developer</title><link>https://gamedeveloper.com.br/posts/</link><description>Blog · Desenvolvimento de jogos por Bruno Cicanci</description><generator>Hugo</generator><language>pt-BR</language><copyright>© 2009–2026 Game Developer por Bruno Cicanci. Todos os direitos reservados.</copyright><lastBuildDate>Thu, 18 Dec 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://gamedeveloper.com.br/posts/rss.xml" rel="self" type="application/rss+xml"/><item><title>Minha palestra na Unite 2025 em Barcelona</title><link>https://gamedeveloper.com.br/palestra-unite-2025-reusable-technology-mobile-sdks/</link><guid>https://gamedeveloper.com.br/palestra-unite-2025-reusable-technology-mobile-sdks/</guid><pubDate>Thu, 18 Dec 2025 00:00:00 +0000</pubDate><category>Palestras</category><description>No mês passado, participei do evento anual da Unity, o Unite, em Barcelona, onde apresentei a palestra Reusable technology: Saving development time with shared Unity plug-ins and SDKs. Durante a apresentação, compartilhei dicas e melhores práticas para desenvolver, compartilhar e manter SDKs e plugins para Unity.&#10;</description><content:encoded>&lt;p&gt;No mês passado, participei do evento anual da Unity, o Unite, em Barcelona, onde apresentei a palestra &lt;em&gt;Reusable technology: Saving development time with shared Unity plug-ins and SDKs&lt;/em&gt;. Durante a apresentação, compartilhei dicas e melhores práticas para desenvolver, compartilhar e manter SDKs e plugins para Unity.&lt;/p&gt;&#10;&lt;p&gt;Hoje, a Unite publicou a gravação da palestra em seu canal oficial, junto com as &lt;a href="https://www.youtube.com/playlist?list=PLX2vGYjWbI0TBAgte6nJfL9expGYuPqUO" target="_blank" rel="noreferrer"&gt;demais apresentações&lt;/a&gt; do evento. Você pode conferir o vídeo abaixo, assim como os slides da apresentação.&lt;/p&gt;&#10;&lt;p&gt;Apresentei a palestra em inglês, mas, caso seja mais fácil, no YouTube você pode selecionar uma dublagem gerada pelo Google em português nas configurações do vídeo ou adicionar legendas geradas em inglês.&lt;/p&gt;&#10;&lt;p&gt;&lt;iframe style="width: 100%" height="400" src="https://www.youtube.com/embed/uIio5XR4qko" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/p&gt;&#10;&lt;p&gt;Abaixo estão os slides da apresentação, que publiquei no &lt;a href="https://www.slideshare.net/cicanci" target="_blank" rel="noreferrer"&gt;Slideshare&lt;/a&gt; junto com minhas outras palestras. O PDF também está disponível &lt;a href="https://gamedeveloper.com.br/downloads/unite-2025-reusable-technology-mobile-sdks.pdf" rel="nofollow"&gt;neste link&lt;/a&gt; para download.&lt;/p&gt;&#10;&lt;iframe src="//www.slideshare.net/slideshow/embed_code/key/9YbMr4RpiX389b" width="610" height="515" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="width: 100%" allowfullscreen&gt; &lt;/iframe&gt;&#10;&lt;p&gt;Comente abaixo se tiver alguma pergunta ou dúvida sobre a minha apresentação. Este é um assunto que faz parte do meu dia a dia trabalhando na Ubisoft, e tenho bastante coisa para compartilhar.&lt;/p&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/categories/palestras.webp" medium="image"/></item><item><title>Git no Unity: Como configurar um repositório do zero</title><link>https://gamedeveloper.com.br/git-no-unity/</link><guid>https://gamedeveloper.com.br/git-no-unity/</guid><pubDate>Mon, 15 Dec 2025 00:00:00 +0000</pubDate><category>Unity</category><description>Neste post você vai aprender como configurar um repositório Git em projetos Unity, seja antes de iniciar um novo projeto ou em um projeto já existente.&#10;</description><content:encoded>&lt;p&gt;Neste post você vai aprender como configurar um repositório Git em projetos Unity, seja antes de iniciar um novo projeto ou em um projeto já existente.&lt;/p&gt;&#10;&lt;p&gt;No vídeo, explico o passo a passo da configuração, compartilho boas práticas e dicas importantes para trabalhar com controle de versão e mostro como o mesmo processo funciona no GitHub, podendo ser adaptado facilmente para GitLab e Bitbucket.&lt;/p&gt;&#10;&lt;p&gt;Assista ao vídeo abaixo para acompanhar o tutorial completo.&lt;/p&gt;&#10;&lt;p&gt;&lt;iframe style="width: 100%" height="400" src="https://www.youtube.com/embed/pBfsTT2K6p4" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/p&gt;&#10;&lt;p&gt;Links mencionados no vídeo:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="https://git-scm.com" target="_blank" rel="noreferrer"&gt;Site oficial do git&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://www.sourcetreeapp.com" target="_blank" rel="noreferrer"&gt;Software visual para git: Sourcetree&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://www.gitkraken.com" target="_blank" rel="noreferrer"&gt;Software visual para git: GitKraken&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com" target="_blank" rel="noreferrer"&gt;Repositórios git: GitHub&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://gitlab.com" target="_blank" rel="noreferrer"&gt;Repositórios git: GitLab&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://bitbucket.org" target="_blank" rel="noreferrer"&gt;Repositórios git: BitBucket&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://git-lfs.com" target="_blank" rel="noreferrer"&gt;Arquivos grandes com Git LFS&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Mais conteúdo sobre git:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="https://gamedeveloper.com.br/unity-git-lfs/" target="_blank" rel="noreferrer"&gt;Git e LFS em projetos Unity&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://gamedeveloper.com.br/introducao-ao-github-guia-nao-tecnico/" target="_blank" rel="noreferrer"&gt;Introdução ao GitHub: um guia que não é técnico&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://gamedeveloper.com.br/git-usando-branches/" target="_blank" rel="noreferrer"&gt;Modelo de desenvolvimento com GIT usando branches&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://gamedeveloper.com.br/git-alias/" target="_blank" rel="noreferrer"&gt;Como criar atalhos com git alias&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/images/2025/12/titulo-unity-git.webp" medium="image"/></item><item><title>Minha participação na Unite 2025 em Barcelona</title><link>https://gamedeveloper.com.br/unity-unite-2025/</link><guid>https://gamedeveloper.com.br/unity-unite-2025/</guid><pubDate>Mon, 24 Nov 2025 00:00:00 +0000</pubDate><category>Unity</category><description>Unite é o evento anual da game engine Unity, que aconteceu este ano novamente em Barcelona, entre os dias 17 e 20 de Novembro. Foi minha primeira vez no evento, e tive a honra de participar não apenas como espectador, mas também como palestrante e Unity Insider.&#10;</description><content:encoded>&lt;p&gt;&lt;a href="https://unity.com/events/unite" target="_blank" rel="noreferrer"&gt;Unite&lt;/a&gt; é o evento anual da game engine &lt;a href="https://unity.com" target="_blank" rel="noreferrer"&gt;Unity&lt;/a&gt;, que aconteceu este ano novamente em Barcelona, entre os dias 17 e 20 de Novembro. Foi minha primeira vez no evento, e tive a honra de participar não apenas como espectador, mas também como &lt;a href="https://www.unite-registration.com/flow/unity/unite25/sessionCatalogue/page/page/session/1748860246014001ryIw" target="_blank" rel="noreferrer"&gt;palestrante&lt;/a&gt; e &lt;em&gt;&lt;strong&gt;Unity Insider&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt="Unity x Epic"&#10; src="https://gamedeveloper.com.br/images/2025/11/unity-epic.webp"&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;O título da minha palestra foi &lt;em&gt;&lt;strong&gt;Reusable technology: Saving development time with shared Unity plug-ins and SDKs&lt;/strong&gt;&lt;/em&gt;, onde compartilhei como desenvolvemos SDKs para Android e iOS, plugins para Unity, e como testamos e publicamos. Este é parte do trabalho que minha equipe realiza na Ubisoft, e foi uma experiência incrível compartilhar isso no maior evento da Unity. Vou fazer outro post sobre a minha palestra quando a gravação for publicada no canal da &lt;a href="https://www.youtube.com/@unity/" target="_blank" rel="noreferrer"&gt;Unity no YouTube&lt;/a&gt;, e comentar mais sobre o assunto.&lt;/p&gt;&#10;&lt;p&gt;Além de palestrar, também participei de um encontro com outros membros do programa &lt;a href="https://unity.com/unity-insiders" target="_blank" rel="noreferrer"&gt;Unity Insiders&lt;/a&gt;, do qual faço parte desde 2022. Também vou escrever outro post sobre este programa e os criadores de conteúdo que conheci pessoalmente no evento.&lt;/p&gt;&#10;&lt;p&gt;Neste post, quero destacar alguns anúncios do Keynote, a inesperada parceria entre Unity e Unreal, e o Roadmap da game engine para o próximo ano.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Keynote&#10; &lt;div id="keynote" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#keynote" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;O grande destaque do keynote deste ano foi a ausência de produtos e serviços baseados em Inteligência Artificial generativa, o que considero um ponto muito positivo. Tudo que foi apresentado no keynote, e depois detalhado no roadmap, mostra que a Unity está focada nos desenvolvedores de jogos e em tornar sua engine uma ferramenta sólida, ao invés de seguir o hype da I.A. para agradar acionistas.&lt;/p&gt;&#10;&lt;p&gt;Alguns jogos feitos com Unity lançados este ano foram apresentados, com destaque para &lt;a href="https://store.steampowered.com/app/2133760/Tiny_Bookshop/" target="_blank" rel="noreferrer"&gt;Tiny Bookshop&lt;/a&gt;, &lt;a href="https://store.steampowered.com/app/3405340/Megabonk/" target="_blank" rel="noreferrer"&gt;Megabonk&lt;/a&gt; e &lt;a href="https://store.steampowered.com/app/3527290/PEAK/" target="_blank" rel="noreferrer"&gt;Peak&lt;/a&gt;. Os desenvolvedores de Peak subiram ao palco para compartilhar como conseguiram criar um jogo em apenas 10 semanas, com 7 desenvolvedores, e que já vendeu mais de 10 milhões de cópias. Eles enfatizaram a facilidade de prototipar e iterar utilizando a engine.&lt;/p&gt;&#10;&lt;p&gt;Outro dado interessante apresentado foi que 70% dos jogos para dispositivos móveis são feitos utilizando Unity, o que demonstra a dominância desta game engine nesta plataforma. Além disso, 33% dos jogos no Steam são feitos com Unity, e na web o número é de aproximadamente 50%. Não foram mostrados dados para consoles, mas acredito que sejam inferiores aos do Steam, caso contrário teriam sido apresentados.&lt;/p&gt;&#10;&lt;p&gt;&lt;iframe style="width: 100%" height="400" src="https://www.youtube.com/embed/MXsKt7JqX5M" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/p&gt;&#10;&lt;p&gt;Durante o keynote, foi apresentado que a Unity consolidou seus esforços em três categorias que representam o ciclo de vida de um projeto: &lt;em&gt;Develop&lt;/em&gt; (Desenvolver), &lt;em&gt;Deploy&lt;/em&gt; (Lançar), e &lt;em&gt;Grow&lt;/em&gt; (Crescer). Cada novo serviço, funcionalidade ou melhoria apresentada durante o evento está dentro destas categorias. Abaixo, fiz um resumo de algumas novidades que estão por vir.&lt;/p&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Develop&#10; &lt;div id="develop" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#develop" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;Em parceria com a Konami, a Unity desenvolveu e lançou um jogo para Switch 2, o &lt;a href="https://www.konami.com/games/survival_kids/" target="_blank" rel="noreferrer"&gt;Survival Kids&lt;/a&gt;, o que permitiu observar de perto a utilização da engine para criar um jogo do início ao fim, além de adicionar suporte ao Switch 2 no lançamento.&lt;/p&gt;&#10;&lt;p&gt;Este jogo foi desenvolvido pela Unity Studios, e mais jogos serão lançados para ajudar a aprimorar a engine. Levou quase 20 anos para a Unity perceber que, ao utilizar sua própria engine, poderiam entender melhor as necessidades dos desenvolvedores. Isso também faz parte de outra iniciativa da Unity, chamada &lt;em&gt;Production Verification&lt;/em&gt;, onde garantem que uma versão da Unity foi utilizada e verificada por eles mesmos em produção (ou seja, lançaram um jogo).&lt;/p&gt;&#10;&lt;p&gt;Ao que tudo indica, a Unity 7 (ou o que estava sendo chamado de Unity 7 até então) foi &amp;quot;cancelada&amp;quot;. Em vez de uma nova versão, a Unity lançará versões incrementais da Unity 6 (semelhante ao ciclo de lançamento da Unreal). A Unity 6.3 LTS acabou de ser lançada, e no final de 2026 teremos a Unity 6.7 LTS, sendo que as versões lançadas entre estas duas (6.4, 6.5, 6.6) trarão melhorias, mas sem o &lt;em&gt;Long Time Support&lt;/em&gt; (LTS).&lt;/p&gt;&#10;&lt;p&gt;Outras novidades incluem uma nova ferramenta para utilizar modelos 3D em jogos 2D (não é 2.5D), a validação de pacotes instalados pelo &lt;em&gt;Package Manager&lt;/em&gt; com uma assinatura que garante a autenticidade deles, entre outras melhorias detalhadas no vídeo do roadmap.&lt;/p&gt;&#10;&lt;p&gt;Outro destaque é a migração do .Net para o Core CLR, que deve melhorar várias áreas da engine, como redução do tempo de compilação (projetos com mais de 50% de redução), suporte a versões mais novas do C#, e maior estabilidade para o editor. A migração está prevista para começar na versão 6.4 e ser concluída na versão 6.7.&lt;/p&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Deploy&#10; &lt;div id="deploy" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#deploy" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;O principal destaque aqui foi o &lt;em&gt;Platform Toolkit&lt;/em&gt;, um novo pacote da Unity que promete acelerar a publicação de jogos em diversas plataformas. Os desenvolvedores precisarão de apenas uma API para cada funcionalidade específica das plataformas, como conquistas, e a Unity garantirá que isso funcione em todas as plataformas suportadas, sem necessidade de alterações no código.&lt;/p&gt;&#10;&lt;p&gt;Outra promessa é que isso deve ajudar no processo de certificação dos jogos para lançamento em consoles, um processo complexo e exigente. Com este novo pacote, a Unity busca facilitar o lançamento de jogos em mais plataformas, reduzindo ou até eliminando complexidades específicas de cada uma.&lt;/p&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Grow&#10; &lt;div id="grow" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#grow" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;A Unity apresentou uma nova ferramenta chamada &lt;em&gt;Vector AI&lt;/em&gt;, que analisa o mercado e os dados do jogo para oferecer direções e sugestões para aumentar o engajamento dos jogadores. Esta foi provavelmente a única menção a uma ferramenta utilizando I.A., e parece ser uma ideia promissora, especialmente para pequenos estúdios e desenvolvedores independentes que não possuem equipes dedicadas para coleta e análise de dados.&lt;/p&gt;&#10;&lt;p&gt;Outra novidade é uma ferramenta para &lt;em&gt;In-App Purchase&lt;/em&gt; (compras dentro do jogo), que permite a utilização de meios de pagamento de terceiros, como Stripe e Coda, além de uma ferramenta para gerenciar o inventário do jogador. Graças ao processo da Epic contra o monopólio da Apple e Google em suas lojas digitais, o suporte a meios de pagamento de terceiros está se tornando mais comum em jogos para dispositivos móveis.&lt;/p&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Unity x Epic&#10; &lt;div id="unity-x-epic" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#unity-x-epic" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;&lt;iframe style="width: 100%" height="400" src="https://www.youtube.com/embed/eDdWSJ5A04E" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/p&gt;&#10;&lt;p&gt;O momento mais surpreendente do evento foi, sem dúvidas, o anúncio da inédita parceria entre Unity e Epic, com os CEOs de cada empresa no palco. A parceria permitirá que desenvolvedores na Unreal utilizem a nova ferramenta de &lt;em&gt;In-App Purchase&lt;/em&gt; da Unity, provavelmente disponibilizando um plugin para Unreal e permitindo o acesso ao serviço.&lt;/p&gt;&#10;&lt;p&gt;Além disso, foi anunciado que jogos feitos com a Unity poderão ser lançados dentro do ecossistema do Fortnite. Detalhes ainda não foram anunciados, mas estou curioso para saber como isso funcionará. Sem dúvidas, isso abre um novo mercado para jogos feitos com Unity, beneficiando desenvolvedores e jogadores.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Roadmap&#10; &lt;div id="roadmap" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#roadmap" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;Além do keynote, por enquanto o único vídeo publicado do evento foi o roadmap abaixo, que mostra em detalhes tudo que foi mencionado no keynote.&lt;/p&gt;&#10;&lt;p&gt;&lt;iframe style="width: 100%" height="400" src="https://www.youtube.com/embed/rEKmARCIkSI" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/p&gt;&#10;&lt;p&gt;Como o vídeo acima aborda basicamente o mesmo assunto do keynote, porém com muito mais detalhes, não vou escrever sobre a apresentação em si.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Conclusão&#10; &lt;div id="conclusão" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#conclus%c3%a3o" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;Fiquei feliz pela ausência de I.A. generativa e por ver que a Unity está levando a sério melhorias na engine com os desenvolvedores em mente. Após o fiasco do &lt;em&gt;runtime fee&lt;/em&gt; (cancelado) e a troca de CEO, a Unity parece estar focada em tornar sua engine mais estável, com funcionalidades e serviços alinhados às necessidades dos desenvolvedores.&lt;/p&gt;&#10;&lt;p&gt;Esta foi minha primeira vez no Unite, e também a primeira vez apresentando uma palestra em Inglês. Fiquei feliz de participar do evento como palestrante, insider, e por reencontrar amigos e colegas de trabalho. Isso me faz lembrar que a indústria de jogos é &amp;quot;pequena&amp;quot; e sempre reencontramos pessoas ou conhecemos alguém com contatos em comum.&lt;/p&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/categories/unity.webp" medium="image"/></item><item><title>Minha participação no Ludum Dare #58</title><link>https://gamedeveloper.com.br/ludum-dare-58/</link><guid>https://gamedeveloper.com.br/ludum-dare-58/</guid><pubDate>Fri, 10 Oct 2025 00:00:00 +0000</pubDate><category>Jogos</category><description>Apesar de participar da game jam Ludum Dare há mais de uma década, ainda continuo aprendendo como finalizar um projeto em um tempo tão curto.&#10;</description><content:encoded>&lt;p&gt;Apesar de participar da game jam Ludum Dare há mais de uma década, ainda continuo aprendendo como finalizar um projeto em um tempo tão curto.&lt;/p&gt;&#10;&lt;p&gt;Lembro da primeira vez que participei de uma game jam, lá em 2015. Na época eu já trabalhava na indústria de jogos há cerca de cinco anos, com nomes como Glu e Electronic Arts no currículo, mas as game jams sempre me ensinaram algo novo sobre desenvolvimento de jogos.&lt;/p&gt;&#10;&lt;p&gt;Como mencionei no meu &lt;a href="https://gamedeveloper.com.br/esta-semana-comeca-o-ludum-dare-58" &gt;artigo anterior&lt;/a&gt;, decidi participar da última edição da game jam &lt;a href="https://ldjam.com/" target="_blank" rel="noreferrer"&gt;Ludum Dare&lt;/a&gt;. Desta vez, o tema escolhido pelos participantes foi &lt;strong&gt;Collector&lt;/strong&gt;.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Conceito do jogo&#10; &lt;div id="conceito-do-jogo" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#conceito-do-jogo" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;Assim que o tema foi revelado, começou a contagem regressiva de 48 horas. &lt;strong&gt;Collector&lt;/strong&gt; foi o tema mais votado de uma lista que os participantes geram e votam durante a semana anterior à game jam. Como essa lista é divulgada antes, costumo me preparar pensando no que poderia fazer com base nas 16 possibilidades.&lt;/p&gt;&#10;&lt;p&gt;Minha ideia original era criar um jogo &lt;strong&gt;roguelike&lt;/strong&gt; em que o jogador coletaria cartas deixadas pelos inimigos e as usaria para melhorar seus poderes e habilidades. Antes de cada novo nível, o jogador escolheria algumas das cartas coletadas e usaria as habilidades dessas cartas para avançar e conquistar mais cartas ao final.&lt;/p&gt;&#10;&lt;p&gt;Como dá pra ver na imagem abaixo, rascunhei a ideia no papel, listando tudo o que veio à cabeça, sem pensar muito na viabilidade naquele momento. Esse processo ajuda bastante a tirar as ideias da cabeça e colocá-las no papel, deixando tudo mais claro e fácil de visualizar.&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2025/10/ld58-game-concept.webp"&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Do papel ao Unity&#10; &lt;div id="do-papel-ao-unity" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#do-papel-ao-unity" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;Assim que a ideia ficou um pouco mais concreta, comecei a desenvolver na minha &lt;strong&gt;game engine&lt;/strong&gt; de escolha: Unity. Uso o Unity desde 2009, quando a versão 3.0 foi lançada, então é sempre minha escolha segura.&lt;/p&gt;&#10;&lt;p&gt;Meu conselho pra quem quer participar de uma game jam, seja iniciante ou profissional, é: use uma engine que você já conheça e tenha alguma experiência. Fazer um jogo em tão pouco tempo, com um tema que você só descobre na hora, já é difícil o bastante — então é importante eliminar qualquer complicação desnecessária do processo.&lt;/p&gt;&#10;&lt;p&gt;Costumo preferir fazer jogos 2D nas game jams, porque é mais fácil pra eu desenhar algo simples e colocar no jogo (até porque não tenho nenhuma habilidade artística). Porém, dessa vez decidi fazer um jogo 3D. Sabendo das minhas limitações, optei por usar apenas objetos geométricos básicos do Unity e criar materials diferentes pra mudar as cores. Também adicionei alguns &lt;strong&gt;spotlights&lt;/strong&gt; nos objetos pra dar mais destaque.&lt;/p&gt;&#10;&lt;p&gt;Comecei criando uma cena de testes — algo que sempre faço pra experimentar ideias. Na imagem abaixo dá pra ver a cena: basicamente um &lt;strong&gt;plane&lt;/strong&gt; servindo de chão e quatro cubos esticados formando as paredes. O jogador é um cilindro amarelo e os inimigos são cubos vermelhos e azuis — tudo bem simples, pra eu conseguir focar na jogabilidade.&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2025/10/ld58-unity-editor.webp"&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;Conforme comecei a programar, também fui ajustando a ideia e reduzindo bastante o escopo, pra garantir que conseguiria terminar algo dentro do prazo.&lt;/p&gt;&#10;&lt;p&gt;A jogabilidade mudou pra algo mais simples: inimigos surgem na cena e perseguem o jogador. Quando colidem, ambos causam dano ao longo do tempo até que um deles morra ou o jogador se afaste.&lt;/p&gt;&#10;&lt;p&gt;Mantive o conceito de coletar cartas, mas na nova versão do jogo os inimigos deixam cair cartas das suas respectivas cores (que chamei de cartas de Fogo e Gelo). Quando o jogador coleta uma carta, sua vida é restaurada para 5 pontos.&lt;/p&gt;&#10;&lt;p&gt;Esse é o &lt;strong&gt;core loop&lt;/strong&gt; do jogo: o jogador precisa atacar os inimigos, mas também fugir quando mais de um começa a persegui-lo. Os inimigos vermelhos e azuis têm valores diferentes de ataque, vida e velocidade — assim como o jogador.&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2025/10/ld58-game.webp"&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;A imagem acima mostra a versão final que fiz upload no site do Ludum Dare dentro das 48 horas. Não tive muito tempo pra balancear o jogo, então as partidas acabaram ficando mais curtas do que eu esperava se acumular muitos inimigos na tela.&lt;/p&gt;&#10;&lt;p&gt;Apesar de o resultado final ser bem mais simples do que o conceito inicial, consegui desenvolver um jogo durante o fim de semana. Por causa dos inimigos e cartas vermelhas e azuis, o nome que escolhi foi Fire &amp;amp; Ice.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Lições de uma game jam&#10; &lt;div id="lições-de-uma-game-jam" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#li%c3%a7%c3%b5es-de-uma-game-jam" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;Depois de mais uma game jam, acho que meus conselhos e aprendizados continuam praticamente os mesmos das participações anteriores. Aqui vão algumas coisas que fiz e que funcionaram bem:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Pense em ideias de jogos com base na lista de possíveis temas antes da game jam começar.&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Use uma game engine que você já conheça e tenha experiência.&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Faça rascunhos da sua ideia pra ter uma visão mais clara do que vai criar.&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;É normal mudar o conceito do jogo depois que começar, mas tente fechar o core loop o quanto antes pra poder melhorar o jogo a partir daí.&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Exporte o jogo para web (se possível), assim outras pessoas conseguem jogar sem precisar fazer download.&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;E aqui vão as coisas que fiz errado e quero evitar da próxima vez:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Ter que criar tudo do zero em 48 horas já é difícil o bastante, então fazer um jogo 3D não ajuda. Na próxima, vou ficar no 2D — é mais fácil deixar visualmente agradável e com menos problemas de colisão.&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Falando em colisão, tive vários problemas que só percebi depois de enviar o jogo. Usando 2D, boa parte disso nem teria acontecido.&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Como sempre, participar da game jam foi uma ótima experiência. Sou um grande fã do Ludum Dare e fico feliz de ter algo completo o suficiente pra compartilhar. Ainda estou aprendendo a fazer melhor a cada edição, e tenho certeza de que na próxima vai sair ainda melhor.&lt;/p&gt;&#10;&lt;p&gt;Você pode jogar Fire &amp;amp; Ice &lt;a href="https://ldjam.com/events/ludum-dare/58/fire-ice" target="_blank" rel="noreferrer"&gt;aqui&lt;/a&gt;. O código-fonte está disponível no meu &lt;a href="https://github.com/cicanci/game-unity-ld58" target="_blank" rel="noreferrer"&gt;GitHub&lt;/a&gt; (um dos requisitos do modo Compo).&lt;/p&gt;&#10;&lt;p&gt;Se você perdeu esta edição do &lt;a href="https://ldjam.com/" target="_blank" rel="noreferrer"&gt;Ludum Dare&lt;/a&gt;, recomendo ficar de olho na próxima, que vai acontecer em abril de 2026.&lt;/p&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/images/2025/10/ld58-game.webp" medium="image"/></item><item><title>Esta semana começa o Ludum Dare #58</title><link>https://gamedeveloper.com.br/esta-semana-comeca-o-ludum-dare-58/</link><guid>https://gamedeveloper.com.br/esta-semana-comeca-o-ludum-dare-58/</guid><pubDate>Wed, 01 Oct 2025 00:00:00 +0000</pubDate><category>Notícias</category><description>Nesta sexta começa a edição de número 58 da game jam Ludum Dare, o melhor game jam! Uma ótima oportunidade para criar um jogo para o seu portfólio, colocar em prática algo que está aprendendo, ou apenas se divertir fazendo um jogo durante o fim de semana.&#10;</description><content:encoded>&lt;p&gt;Nesta sexta começa a &lt;a href="https://ldjam.com/events/ludum-dare/58" target="_blank" rel="noreferrer"&gt;edição de número 58 da game jam Ludum Dare&lt;/a&gt;, o melhor game jam! Uma ótima oportunidade para criar um jogo para o seu portfólio, colocar em prática algo que está aprendendo, ou apenas se divertir fazendo um jogo durante o fim de semana.&lt;/p&gt;&#10;&lt;p&gt;Conseguir um primeiro emprego na indústria de jogos não requer apenas conhecimento - ter um portfólio para demonstrar suas habilidades ajuda bastante. Game jams são uma ótima maneira de conseguir fazer um jogo em um tempo e tema pré-determinados, o que também ajuda a focar e não perder muito tempo pensando no que fazer.&lt;/p&gt;&#10;&lt;p&gt;Existem muitas game jams online e presenciais, mas para mim a Ludum Dare é a melhor para quem está começando a fazer jogos, ou mesmo se está querendo participar de algo mais casual do conforto de casa, sozinho ou em grupo.&lt;/p&gt;&#10;&lt;p&gt;O tema da Ludum Dare é anunciado antes do seu início na sexta-feira, e é o resultado de uma votação aberta que acontece durante a semana que antecede o evento.&lt;/p&gt;&#10;&lt;p&gt;Você pode participar de dois formatos, e cada um tem suas características e audiência:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Compo: 24 horas para fazer um jogo do zero e &lt;strong&gt;sozinho&lt;/strong&gt; - você não pode usar nada que já esteja pronto. Este é o modo mais &lt;em&gt;hardcore&lt;/em&gt; que vai forçar a sua criatividade, e as pessoas não vão julgar sua arte se o &lt;em&gt;gameplay&lt;/em&gt; for bem feito e divertido.&lt;/li&gt;&#10;&lt;li&gt;Jam: 72 horas para fazer um jogo sozinho ou em grupo, e você pode usar qualquer coisa que já esteja pronta para ajudar a criar o jogo. Este é um formato mais tranquilo, onde você tem menos pressão e mais ajuda para terminar seu jogo. É tão de boas que também permite submeter um jogo fora do tema, desde que você tenha feito ele durante o Ludum Dare.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Se esta é a primeira vez que você está participando de uma game jam, eu recomendo o formato Jam que é mais tranquilo, mesmo se você já tem alguma experiência desenvolvendo jogos. Mas, se você estiver confiante, participe do Compo e faça o seu melhor.&lt;/p&gt;&#10;&lt;p&gt;A minha primeira participação foi no &lt;a href="https://gamedeveloper.com.br/ludum-dare-32" &gt;Ludum Dare #32&lt;/a&gt;, dez anos atrás, e desde então participei de mais de 10 edições no formato Compo. Consegui terminar o jogo em algumas, em outras falhei, mas isso tudo é parte do aprendizado que uma game jam pode te dar.&lt;/p&gt;&#10;&lt;p&gt;Aqui estão algumas dicas que podem te ajudar:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Quando começar a rodada de votação final na sexta-feira, você vai ter uma lista dos possíveis temas - tente pensar qual jogo consegue fazer dentro do tema no final de semana.&lt;/li&gt;&#10;&lt;li&gt;Utilize uma &lt;em&gt;game engine&lt;/em&gt; ou &lt;em&gt;framework&lt;/em&gt; que você já conhece e se sente confortável em utilizar para poder focar em fazer o jogo.&lt;/li&gt;&#10;&lt;li&gt;Se você quiser participar do modo &lt;em&gt;ultra hardcore&lt;/em&gt; (inventei isso), utilize uma &lt;em&gt;game engine&lt;/em&gt; ou &lt;em&gt;framework&lt;/em&gt; que você nunca utilizou antes - isso aumenta o desafio e também é uma oportunidade de experimentar algo novo.&lt;/li&gt;&#10;&lt;li&gt;Pegue leve e descanse - planeje o seu final de semana, quantas horas vai focar no seu jogo, e lembre-se de que você precisa sobreviver para enviar seu jogo no final.&lt;/li&gt;&#10;&lt;li&gt;Coloque uma roupa confortável e sua melhor &lt;em&gt;playlist&lt;/em&gt;, tente focar especialmente no primeiro dia para conseguir um bom progresso.&lt;/li&gt;&#10;&lt;li&gt;Divirta-se! Lembre-se de que isso faz parte de um game jam.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Eu pretendo participar do formato Compo e espero que possa compartilhar meu jogo e minha experiência na próxima semana.&lt;/p&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/images/2019/04/ld44.webp" medium="image"/></item><item><title>SDL3 com Visual Studio, git submodule, e GitHub Workflow</title><link>https://gamedeveloper.com.br/sdl3-git-submodule-github-workflow/</link><guid>https://gamedeveloper.com.br/sdl3-git-submodule-github-workflow/</guid><pubDate>Sun, 13 Jul 2025 00:00:00 +0000</pubDate><category>Como Programar Jogos</category><description>Após minha graduação em Ciência da Computação, iniciei uma pós-graduação em Produção e Programação de Jogos com o objetivo de mudar minha carreira e entrar na indústria de jogos. Isso foi em 2009, e uma das primeiras ferramentas de desenvolvimento de jogos que tive contato foi o SDL2, onde fiz o meu primeiro projeto de game com SDL e C++ em uma disciplina da pós-graduação. De lá pra cá utilizei o SDL em diversos projetos, principalmente game jams e para aprender a programar homebrew para Nintendo DS e PSP, e sempre foi um framework fácil de usar e bem completo para jogos 2D.&#10;</description><content:encoded>&lt;p&gt;Após minha graduação em Ciência da Computação, iniciei uma pós-graduação em Produção e Programação de Jogos com o objetivo de mudar minha carreira e entrar na indústria de jogos. Isso foi em 2009, e uma das primeiras ferramentas de desenvolvimento de jogos que tive contato foi o SDL2, onde fiz o meu &lt;a href="https://gamedeveloper.com.br/primeiro-projeto-de-game-com-sdl-e-c/" &gt;primeiro projeto de game com SDL e C++&lt;/a&gt; em uma disciplina da pós-graduação. De lá pra cá utilizei o &lt;a href="https://www.libsdl.org/" target="_blank" rel="noreferrer"&gt;SDL&lt;/a&gt; em diversos projetos, principalmente game jams e para aprender a programar &lt;a href="https://gamedeveloper.com.br/hello-world-no-nintendo-ds/" &gt;homebrew para Nintendo DS&lt;/a&gt; e PSP, e sempre foi um framework fácil de usar e bem completo para jogos 2D.&lt;/p&gt;&#10;&lt;p&gt;Criar um projeto novo utilizando Visual Studio e configurar o SDL2 era um pouco mais trabalhoso, e inclusive &lt;a href="https://gamedeveloper.com.br/hello-world-sdl-visual-studio/" &gt;escrevi este tutorial&lt;/a&gt; pra mim mesmo por que eu sempre esquecia de algum passo. Alguns meses atrás, o SDL3 foi oficialmente lançado, e trouxe algumas mudanças para simplificar o desenvolvimento de jogos e sua configuração. Neste post vou mostrar como criar um projeto novo no Visual Studio, adicionar o SDL3 como uma dependência usando &lt;code&gt;git submodule&lt;/code&gt;, configurar o projeto para compilar um &lt;em&gt;Hello World&lt;/em&gt;, e como automatizar builds em cada commit utilizando &lt;em&gt;GitHub Workflows&lt;/em&gt;.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;SDL como dependência usando git submodule&#10; &lt;div id="sdl-como-dependência-usando-git-submodule" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#sdl-como-depend%c3%aancia-usando-git-submodule" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;A parte mais importante de todo este post é este primeiro passo, pois aqui vamos configurar o projeto como um repositório &lt;a href="https://git-scm.com/" target="_blank" rel="noreferrer"&gt;git&lt;/a&gt; e adicionar o &lt;a href="https://github.com/libsdl-org/SDL" target="_blank" rel="noreferrer"&gt;SDL3&lt;/a&gt; como um &lt;a href="https://git-scm.com/book/en/v2/Git-Tools-Submodules" target="_blank" rel="noreferrer"&gt;submodule&lt;/a&gt;. Existem diversos conteúdos muito bons sobre git, então não vou alongar muito com uma introdução, e vamos direto ao ponto. Caso não tenha git na sua máquina, você pode &lt;a href="https://git-scm.com/downloads" target="_blank" rel="noreferrer"&gt;instalar aqui&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Primeiro, precisamos criar um repositório local. Os comandos abaixo são os mesmos em qualquer sistema operacional, mas como vamos utilizar o Visual Studio neste tutorial, pode assumir que estou utilizando Windows. Criei um novo diretório no seu computador com o nome &lt;code&gt;HelloWorldSDL3&lt;/code&gt;. Após criar o diretório, abra o prompt de comandos do Windows (&lt;em&gt;cmd&lt;/em&gt; ou &lt;em&gt;power shell&lt;/em&gt;), nave até a nova pasta criada e, dentro dela, execute o comando abaixo:&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Este commando vai criar uma pasta invisível chamada &lt;code&gt;.git&lt;/code&gt;. Caso algum erro aconteça, como comando não encontrado, certifique-se que o git foi instalado e está adicionado no &lt;code&gt;path&lt;/code&gt; do Windows. Em seguida, vamos adicionar o repositório do SDL como um submodule usando os comandos abaixo:&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;submodule&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="p"&gt;//&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;libsdl-org&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;SDL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;git&lt;/span&gt; &lt;span class="n"&gt;SDL&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Este comando vai adicionar um arquivo &lt;code&gt;.gitmodules&lt;/code&gt; com uma referência do SDL no repositório local, e baixar o projeto em uma pasta chamada SDL. Se tudo der certo, seu diretório deverá estar com esta estrutura abaixo:&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HelloWorldSDL3/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── .git/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── SDL/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── .gitmodules&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Neste momento você pode criar um repositório no &lt;a href="https://github.com/" target="_blank" rel="noreferrer"&gt;GitHub&lt;/a&gt; (necessário criar uma conta gratuita se não tiver). No meu exemplo abaixo, estou criando um repositório público com o nome &lt;code&gt;hello-world-sdl&lt;/code&gt;, e não selecionei nenhuma opção para inicializar o repositório com algum arquivo.&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2025/05/github-repository.webp"&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;Depois de criar o repositório, volte para o prompt de comandos e digite os seguintes comandos (substitua &lt;code&gt;USERNAME&lt;/code&gt; pelo seu usuário no github):&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;commit&lt;/span&gt; &lt;span class="n"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;SDL submodule&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;branch&lt;/span&gt; &lt;span class="n"&gt;-M&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;remote&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="n"&gt;origin&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="p"&gt;//&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;USERNAME&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;hello-world&lt;/span&gt;&lt;span class="n"&gt;-sdl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;git&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt; &lt;span class="n"&gt;-u&lt;/span&gt; &lt;span class="n"&gt;origin&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;E, após executar os comandos acima com sucesso, o seu repositório estará parecido com o meu na imagem abaixo:&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2025/05/github-push.webp"&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;Isso é tudo que precisamos por agora, mas vamos voltar ao github no final deste post para configurar a automação de compilação no GitHub Workflow.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Criação de um projeto no Visual Studio&#10; &lt;div id="criação-de-um-projeto-no-visual-studio" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#cria%c3%a7%c3%a3o-de-um-projeto-no-visual-studio" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;O SDL3 tem uma documentação bem simples e fácil de seguir. A configuração do projeto no Visual Studio pode ser vista &lt;a href="https://github.com/libsdl-org/SDL/blob/main/docs/INTRO-visualstudio.md" target="_blank" rel="noreferrer"&gt;aqui&lt;/a&gt;, porém vou adicionar os passos em português abaixo com algumas modificações que fiz.&lt;/p&gt;&#10;&lt;p&gt;A principal diferença é que, ao invés de fazer o download do código fonte, nós vamos usar o submodule que configuramos no passo anterior em nosso repositório git.&lt;/p&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Novo projeto no Visual Studio&#10; &lt;div id="novo-projeto-no-visual-studio" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#novo-projeto-no-visual-studio" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;O Visual Studio 2022 (ou mais novo) pode ser baixado &lt;a href="https://visualstudio.microsoft.com/" target="_blank" rel="noreferrer"&gt;aqui&lt;/a&gt;, e a versão &lt;em&gt;Community&lt;/em&gt; é gratuita para desenvolvedores solo, uso acadêmico, ou projetos &lt;em&gt;open source&lt;/em&gt;. Siga os passos do instalador e lembre de marcar as opções para adicionar &lt;em&gt;Desktop Development with C++&lt;/em&gt; (você também pode marcar as opções de Unity e game development mas não são necessárias para o SDL).&lt;/p&gt;&#10;&lt;p&gt;Depois de instalado, selecione a opção &lt;em&gt;Create a new project&lt;/em&gt; e procure por &lt;em&gt;Empty Project&lt;/em&gt; com C++, como na imagem abaixo. Se você não estiver vendo essa opção, volte no instalador e veja se as opções de suporte ao C++ foram instaladas no Visual Studio.&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2025/05/vs_cpp_empty_project.webp"&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;Após selecionar &lt;em&gt;Empty Project&lt;/em&gt; com C++, na próxima janela digite &lt;code&gt;HelloGame&lt;/code&gt; em &lt;em&gt;Project name&lt;/em&gt;, e no campo &lt;em&gt;Location&lt;/em&gt; selecione o caminho em que está o repositório que criamos no início deste post. As configurações do novo projeto devem estar iguais a imagem abaixo.&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2025/05/vs_hello_game.webp"&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;Depois de criar o novo projeto no Visual Studio, esta é a estrutura do nosso repositório atualizada:&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HelloWorldSDL3/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── .git/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── HelloGame/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── SDL/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── .gitmodules&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Adicionando código&#10; &lt;div id="adicionando-código" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#adicionando-c%c3%b3digo" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;Agora que temos um projeto em branco, vamos adicionar um arquivo de C++ e configurar o projeto para utilizar o SDL que está no mesmo diretório. É importante adicionar um arquivo de código fonte em C++ antes de continuar por que isso vai habilitar as opções que vamos configurar mais pra frente.&lt;/p&gt;&#10;&lt;p&gt;Clique com o botão direito no projeto &lt;em&gt;HelloGame&lt;/em&gt; e, em seguida, selecione a opção &lt;em&gt;Add | New Item...&lt;/em&gt; e digite &lt;code&gt;main.cpp&lt;/code&gt;. No novo arquivo criado, copie e cole o código abaixo. Não se preocupe com os erros de compilação agora, nós ainda vamos configurar o projeto para localizar o SDL e poder compilar com sucesso.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define SDL_MAIN_USE_CALLBACKS 1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;SDL3/SDL.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;SDL3/SDL_main.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;SDL_Window&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;SDL_Renderer&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;renderer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;SDL_AppResult&lt;/span&gt; &lt;span class="nf"&gt;SDL_AppInit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;appstate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;SDL_CreateWindowAndRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello World&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SDL_WINDOW_MAXIMIZED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SDL_Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Couldn&amp;#39;t create window and renderer: %s&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SDL_GetError&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;SDL_APP_FAILURE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;SDL_APP_CONTINUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;SDL_AppResult&lt;/span&gt; &lt;span class="nf"&gt;SDL_AppEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;appstate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SDL_Event&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;SDL_EVENT_KEY_DOWN&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;SDL_EVENT_QUIT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;SDL_APP_SUCCESS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;SDL_APP_CONTINUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;SDL_AppResult&lt;/span&gt; &lt;span class="nf"&gt;SDL_AppIterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;appstate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Hello World!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;4.0f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SDL_GetRenderOutputSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SDL_SetRenderScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SDL_strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SDL_SetRenderDrawColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SDL_RenderClear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SDL_SetRenderDrawColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SDL_RenderDebugText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SDL_RenderPresent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;SDL_APP_CONTINUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;SDL_AppQuit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;appstate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SDL_AppResult&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;O código acima é uma variação do &lt;a href="https://github.com/libsdl-org/SDL/blob/main/docs/hello.c" target="_blank" rel="noreferrer"&gt;hello.c&lt;/a&gt; disponibilizado no repositório do SDL. As mudanças que fiz foram mudar a extensão para &lt;code&gt;.cpp&lt;/code&gt;, remover os comentários para não ficar tão longo aqui, e configurar a janela usando &lt;code&gt;SDL_WINDOW_MAXIMIZED&lt;/code&gt; (modo janela) ao invés do original que criava a janela em modo tela cheia.&lt;/p&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Adicionando SDL como dependência&#10; &lt;div id="adicionando-sdl-como-dependência" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#adicionando-sdl-como-depend%c3%aancia" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;Agora vamos adicionar o SDL no Visual Studio junto com o nosso projeto. Para isso, clique com o botão direito na &lt;em&gt;Solution 'HelloGame'&lt;/em&gt;, selecione &lt;em&gt;Add | Existing Project&lt;/em&gt; e, na nova janela navegue até &lt;code&gt;SDL/VisualC/SDL&lt;/code&gt; (dentro do nosso repositório), e selecione o arquivo &lt;em&gt;SDL.vcxproj&lt;/em&gt;. Depois de adicionar o projeto SDL junto ao nosso projeto HelloGame, você deve ter a estrutura abaixo no Visual Studio:&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2025/05/vs_solution_exporer.webp"&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;O próximo passo agora é adicionar o SDL como uma referência no projeto HelloGame. Cliquei com o botão direito no projeto &lt;em&gt;HelloGame&lt;/em&gt;, selecione &lt;em&gt;Add | Reference...&lt;/em&gt; e, na nova janela, selecione o projeto SDL e clique em &lt;em&gt;OK&lt;/em&gt;. Isso vai garantir que o nosso projeto use o SDL como uma dependência para compilar o código.&lt;/p&gt;&#10;&lt;p&gt;Por fim, vamos adicionar os &lt;em&gt;headers&lt;/em&gt; do SDL na configuração do nosso projeto. Para isso, clique com o botão direto no projeto &lt;em&gt;HelloGame&lt;/em&gt; e selecione a opção &lt;em&gt;Properties&lt;/em&gt;. Na nova janela, mude o filtro acima para &lt;code&gt;All Configurations&lt;/code&gt; e &lt;code&gt;All Platforms&lt;/code&gt; (se já não estiver assim). Em seguida, expanda a opção &lt;em&gt;C/C++&lt;/em&gt; no menu da esquerda, selecione &lt;em&gt;General&lt;/em&gt;, e no primeiro campo &lt;em&gt;Additional Include Directories&lt;/em&gt;, selecione &lt;em&gt;Edit&lt;/em&gt; e adicione o caminho &lt;code&gt;SDL/includes&lt;/code&gt; (dentro do nosso repositório).&lt;/p&gt;&#10;&lt;p&gt;A imagem baixo mostra como a configuração deste janela deve estar depois dos passos acima:&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2025/05/vs_settings.webp"&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Rodando o projeto&#10; &lt;div id="rodando-o-projeto" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#rodando-o-projeto" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;Se tudo deu certo, agora basta rodar o projeto no Visual Studio utilizando o botão play verde ou pressionando F5, e você deverá ver a tela abaixo:&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2025/05/sdk_hello_game.webp"&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;Caso encontre algum erro, dê uma revisada nos passos anteriores e compare as imagens que adicionei no post para ajudar. Se mesmo assim tiver dúvidas ou problemas, deixe um comentário que tentarei ajudar assim que possível.&lt;/p&gt;&#10;&lt;p&gt;Nós temos um repositório configurado no GitHub com o SDL adicionado como uma dependência e também o nosso projeto configurado para rodar no Visual Studio. O próximo passo agora é um extra, mas que com certeza vai ajudar o desenvolvimento ao médio e longo prazo.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Automação com GitHub Workflow&#10; &lt;div id="automação-com-github-workflow" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#automa%c3%a7%c3%a3o-com-github-workflow" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;Automação é algo muito comum e essencial em empresas, não só em jogos. A automação pode ser desde rodar alguns testes unitários, compilar o projeto, e até rodar o jogo em um teste pré-definido. Para isso, muitas vezes precisamos de outras máquinas ou até servidores dedicados a rodar nosso projeto sempre que precisar de um teste, ou até mesmo a cada alteração.&lt;/p&gt;&#10;&lt;p&gt;É ai que entra o &lt;a href="https://docs.github.com/en/actions/concepts/workflows-and-actions/about-workflows" target="_blank" rel="noreferrer"&gt;GitHub Workflow&lt;/a&gt;, onde podemos automatizar muita coisa no nosso repositório utilizando servidores Windows, Linux e macOS do GitHub. Existem alguns &lt;a href="https://docs.github.com/en/actions/concepts/overview/usage-limits-billing-and-administration" target="_blank" rel="noreferrer"&gt;limites&lt;/a&gt;, mas mesmo uma conta gratuita tem o suficiente para bastante coisa em projetos pequenos e até médios. Você também pode registrar uma máquina sua como servidor e não se preocupar com limites (já fiz isso com um raspberry pi e funcionou bem para projetos pequenos!).&lt;/p&gt;&#10;&lt;p&gt;Não vou entrar em muitos detalhes sobre o GitHub Workflow em si, por que é algo muito grande e complexo de explicar tudo, mas recomendo dar uma olhada na documentação e pesquisar sobre também.&lt;/p&gt;&#10;&lt;p&gt;Para adicionar suporte a automação em nosso projeto, precisamos apenas adicionar um arquivo no repositório. No repositório, cria uma nova pasta &lt;code&gt;.github&lt;/code&gt; e outra pasta dentro dela chamada &lt;code&gt;workflows&lt;/code&gt;. Dentro da pasta &lt;code&gt;workflows&lt;/code&gt;, adicione um novo arquivo chamado &lt;code&gt;msbuild.yml&lt;/code&gt;. Seu repositório deve estar assim:&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HelloWorldSDL3/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── .git/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── .github/workflows/msbuild.yml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── HelloGame/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── SDL/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── .gitmodules&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Por fim, abra o arquivo &lt;code&gt;msbuild.yml&lt;/code&gt; em qualquer editor e copie e cole o conteúdo abaixo:&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;MSBuild&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;main&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pull_request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;main&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;SOLUTION_FILE_PATH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./HelloGame&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;BUILD_CONFIGURATION&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Release&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;read&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;windows-latest&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v4&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;submodules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;recursive&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Add MSBuild to PATH&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;microsoft/setup-msbuild@v1.0.2&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Restore NuGet packages&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;working-directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{env.GITHUB_WORKSPACE}}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;nuget restore ${{env.SOLUTION_FILE_PATH}}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Build&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;working-directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{env.GITHUB_WORKSPACE}}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} ${{env.SOLUTION_FILE_PATH}}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Upload a Build Artifact&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/upload-artifact@v4.6.2&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;hellogame-x64-release&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./HelloGame/x64/Release/&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;O arquivo acima parece um pouco confuso, mas se você ler cada linha vai começar a fazer sentido:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Este &lt;em&gt;workflow&lt;/em&gt; roda quando commits forem adicionados no branch &lt;code&gt;main&lt;/code&gt; ou quando tiver um &lt;em&gt;pull request&lt;/em&gt; para ele.&lt;/li&gt;&#10;&lt;li&gt;O nosso &lt;em&gt;env&lt;/em&gt; está configurado com o caminho do projeto &lt;code&gt;HelloGame&lt;/code&gt; e a build &lt;code&gt;Release&lt;/code&gt;.&lt;/li&gt;&#10;&lt;li&gt;O &lt;em&gt;job&lt;/em&gt; vai rodar em máquinas &lt;code&gt;windows&lt;/code&gt;.&lt;/li&gt;&#10;&lt;li&gt;Estamos utilizando &lt;code&gt;msbuild&lt;/code&gt; para compilar o projeto pela linha de comando (já que é um servidor sem interface).&lt;/li&gt;&#10;&lt;li&gt;Depois de compilar, a build do jogo vai ficar arquivada como um artefato deste workflow.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Assim que adicionarmos esse arquivo no repositório e fizermos um commit para o branch &lt;code&gt;main&lt;/code&gt;, este &lt;em&gt;workflow&lt;/em&gt; vai rodar em gerar uma build que podemos baixar e testar, e vai estar no menu &lt;code&gt;Actions&lt;/code&gt; do repositório no GitHub.&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2025/05/github-workflow.webp"&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;Além disso, é possível ver todo o processo de compilação e os &lt;em&gt;logs&lt;/em&gt; do servidor. Caso algum erro aconteça, é lá que você vai entender o por que.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Conclusão&#10; &lt;div id="conclusão" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#conclus%c3%a3o" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;Este post demorou um pouco mais do que planejei para escrever, e ficou mais longo do que imaginei, mas acho que no fim é uma boa introdução de como criar um projeto novo usando SDL3, configurar o Visual Studio, e ainda como usar git submodule e GitHub Workflows para automação.&lt;/p&gt;&#10;&lt;p&gt;Tudo que fiz neste post pode ser visto no meu repositório público &lt;a href="https://github.com/cicanci/hello-world-sdl3" target="_blank" rel="noreferrer"&gt;hello-worlds-sdl3&lt;/a&gt;. Fique a vontade para usar este repositório como um template ou base para o seu projeto, este é um dos motivos que fiz para mim mesmo.&lt;/p&gt;&#10;&lt;p&gt;Muito obrigado se você leu até o final, e espero que tenha sido útil. Qualquer dúvida, problemas no passo-a-passo, ou sugestões deixe um comentário abaixo.&lt;/p&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/categories/como-programar-jogos.webp" medium="image"/></item><item><title>Adeus Jekyll, olá Docusaurus</title><link>https://gamedeveloper.com.br/ola-docusaurus/</link><guid>https://gamedeveloper.com.br/ola-docusaurus/</guid><pubDate>Sun, 04 May 2025 00:00:00 +0000</pubDate><category>Blog</category><description>Mês passado foi o aniversário de 16 anos deste blog que, desde 2009, já passou por diferentes tecnologias e servidores para publicar o conteúdo. Chegou a hora de mais uma mudança, e desta vez escolhi migrar o blog do Jekyll para o Docusaurus.&#10;</description><content:encoded>&lt;p&gt;Mês passado foi o aniversário de 16 anos deste blog que, desde 2009, já passou por diferentes tecnologias e servidores para publicar o conteúdo. Chegou a hora de mais uma mudança, e desta vez escolhi migrar o blog do &lt;a href="https://jekyllrb.com/" target="_blank" rel="noreferrer"&gt;Jekyll&lt;/a&gt; para o &lt;a href="https://docusaurus.io/" target="_blank" rel="noreferrer"&gt;Docusaurus&lt;/a&gt;.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Evolução do blog&#10; &lt;div id="evolução-do-blog" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#evolu%c3%a7%c3%a3o-do-blog" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;Em 2009 eu comecei o meu blog utilizando o bom e velho &lt;a href="https://wordpress.com/" target="_blank" rel="noreferrer"&gt;Wordpress&lt;/a&gt;, que ainda é uma das maneiras mais rápidas e fáceis de se criar um blog que pode ser totalmente customizado. Depois de um tempo utilizando Wordpress, eu decidi levar o blog para um próximo nível que me daria mais flexibilidade, e decidi ter o meu próprio servidor para hospedar o blog.&lt;/p&gt;&#10;&lt;p&gt;Passei por diversos servidores de hospedagem, sempre procurando um melhor custo benefício já que pagava um valor mensal para manter o blog no ar. Em 2016, comecei a procurar por alternativas para reduzir meu custo e aumentar a performance do blog, já que um dos gargalos era a constante conexão do PHP com o bando de dados MySQL usado pelo Wordpress. Foi então que eu fiz uma primeira migração de framework do blog, dando &lt;a href="https://gamedeveloper.com.br/ola-ghost/" &gt;adeus ao Wordpress, e olá ao Ghost&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;O &lt;a href="https://ghost.org/" target="_blank" rel="noreferrer"&gt;Ghost&lt;/a&gt; é um pouco parecido com Wordpress - você pode ter um blog hospedado por eles ou sua própria hospedagem. Porém, uma vantagem, que também foi uma gambiarra, era que eu podia rodar o servidor local, e &amp;quot;compilar&amp;quot; o site em páginas estáticas, e ai então publicar essas páginas no &lt;a href="https://pages.github.com/" target="_blank" rel="noreferrer"&gt;GitHub Pages&lt;/a&gt;. Consegui eliminar o meu custo mensal e ainda fazer o site ficar incrivelmente rápido já que conteúdo estático não precisa de conexão com banco de dados.&lt;/p&gt;&#10;&lt;p&gt;Depois que me acostumei com o blog em formato estático, comecei a ficar incomodado em ter que rodar um servidor local toda vez que ia publicar algo no blog. A interface do Ghost era bem legal, porém não uma necessidade. Foi então que, em 2017, dei &lt;a href="https://gamedeveloper.com.br/ola-jekyll/" &gt;adeus ao Ghost, e olá ao Jekyll&lt;/a&gt;. Diferente to Ghost (e do Wordpress), o Jekyll não tem uma interface por padrão, apenas arquivos em um repositório que são &amp;quot;compilado&amp;quot; para gerar um site estático. Isso reduziu a necessidade de rodar um servidor local, pois para publicar posts eu não precisava disso - apenas escrever e fazer um commit no git, e então o site era atualizado já que o GitHub pages consegue fazer essa &amp;quot;compilação&amp;quot;.&lt;/p&gt;&#10;&lt;p&gt;Minha última mudança foi em 2018, quando decidi dar &lt;a href="https://gamedeveloper.com.br/ola-netlify/" &gt;adeus ao GitHub Pages, e olá ao Netlify&lt;/a&gt;. Na época o GitHub Pages era um pouco limitado, e além disso era possível ter apenas um site estático por conta no GitHub, e eu queria publicar um novo site para o meu portfólio, também utilizando Jekyll. Foi então que migrei de plataforma, indo para o Netlify, que além de ter muito mais do que preciso, também é gratuito e suporta diversos sites ao mesmo tempo.&lt;/p&gt;&#10;&lt;p&gt;Foram 8 anos utilizando Jekyll no blog, e aos poucos comecei a encontrar alguns problemas que me fizeram pensar em outras opções, inclusive voltar para o Ghost, porém encontrei a solução perfeita pra mim: Docusaurus.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Mudança para Docusaurus&#10; &lt;div id="mudança-para-docusaurus" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#mudan%c3%a7a-para-docusaurus" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;Jekyll é um framework incrível para criar sites estáticos, desde um simples blog ou documentação de um sistema, até sites completos com E-commerce. Existem muitos layouts (themes) gratuitos e pagos, a flexibilidade nele é imensa. Porém, é um framework um pouco velho que já está mostrando sinais de que precisa se modernizar. Um dos maiores problemas que eu tinha era depender de versões específicas de &lt;a href="https://www.ruby-lang.org/en/" target="_blank" rel="noreferrer"&gt;Ruby&lt;/a&gt; para compilar o blog, e sempre tinha problemas de incompatibilidade entre as dependências em diferentes computadores. Além disso, a maioria das dependências não eram atualizadas e eu ficava cada vez mais preso em coisas antigas.&lt;/p&gt;&#10;&lt;p&gt;Eu descobri o Jekyll no trabalho, pois era como a documentação era feita na época, e a mesma coisa aconteceu quando descobri o Docusaurus. Muitos dos meus problemas estão listados na &lt;a href="https://docusaurus.io/docs#jekyll" target="_blank" rel="noreferrer"&gt;comparação do Jekyll com Docusaurus&lt;/a&gt;, o que foi mais um incentivo para mudar. Docusaurus é uma plataforma &lt;a href="https://github.com/facebook/docusaurus" target="_blank" rel="noreferrer"&gt;open source&lt;/a&gt; desenvolvida pela Meta, e é feita com &lt;a href="https://react.dev/" target="_blank" rel="noreferrer"&gt;React&lt;/a&gt;, também mantido pela mesma empresa.&lt;/p&gt;&#10;&lt;p&gt;Por utilizar frameworks mais modernos, como React, o Docusaurus não possui problemas de dependências e tem uma melhor consistência entre diferentes sistemas operacionais. Configurar um site nele é bem rápido e fácil, e publicar ele no Netlify foi ainda mais fácil e rápido do que o Jekyll.&lt;/p&gt;&#10;&lt;p&gt;Porém, nem tudo é perfeito, e existem algumas limitações no Docusaurus que podem ser um problema. A customização nele é bem menos flexível do que o Jekyll, e não existe tantos layouts disponíveis para ele. Além disso, o foco do Docusaurus é documentação, e o blog é um sistema secundário nele e bem limitado. A customização nele é mais fechada, e requer o uso de &lt;a href="https://docusaurus.io/docs/swizzling" target="_blank" rel="noreferrer"&gt;swizzling&lt;/a&gt;, onde você pode expandir ou &amp;quot;ejetar&amp;quot; um componente dele para customizar. Nem todo componente é customizável, e os que são possuem um alerta dizendo que podem deixar de funcionar em atualizações futuras.&lt;/p&gt;&#10;&lt;p&gt;Eu tive que &lt;a href="https://docusaurus.io/docs/blog#blog-only-mode" target="_blank" rel="noreferrer"&gt;desativar a parte de documentação&lt;/a&gt;, fazer algumas mudanças no blog e customizar alguns componentes, e apesar das limitações estou bem feliz com o resultador. Vai demorar um pouco para me acostumar com o Docusaurus, mas por enquanto ele está cumprindo todos meus requisitos para um blog:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Simples, rápido e fácil de usar&lt;/li&gt;&#10;&lt;li&gt;Boa performance, moderno e fácil de manter&lt;/li&gt;&#10;&lt;li&gt;Me permite focar em escrever&lt;/li&gt;&#10;&lt;li&gt;Sem custo adicional&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Apesar da limitação em customização e layouts disponíveis (comparando com o Jekyll), acho que o Docusaurus é o que eu estava procurando para este momento do blog. Provavelmente irei atrás de um layout melhor no futuro, mas por enquanto este layout básico e comum já está muito bom.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Novas funcionalidades&#10; &lt;div id="novas-funcionalidades" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#novas-funcionalidades" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;Uma das coisas que sempre tentei adicionar no blog, e sempre sem sucesso, foi uma ferramenta de busca. É uma limitação para sites estáticos, e é necessário algo externo para poder funcionar. Felizmente, o Docusaurus tem suporte nativo para uma ferramenta de busca chamada &lt;a href="https://www.algolia.com/" target="_blank" rel="noreferrer"&gt;Algolia&lt;/a&gt;, e como você pode ver ali no canto superior direito, funciona muito bem. Tive que ajustar algumas configurações e aprender como funcionar a indexação, mas valeu o trabalho e fiquei feliz com o resultado.&lt;/p&gt;&#10;&lt;p&gt;Um pouco menos importante, mas também uma novidade, é poder mudar o tema do blog entre &lt;em&gt;dark&lt;/em&gt; e &lt;em&gt;light&lt;/em&gt; (botão à esquerda da busca ali no topo). Isso também era algo que queria adicionar ao blog, mas ficava preso os layouts do Jekyll que não tinham esse suporte porém eram gratuitos.&lt;/p&gt;&#10;&lt;p&gt;Outra mudança significativa pra mim foi abandonar o Google Analytics em favor do &lt;a href="https://www.cloudflare.com/en-gb/web-analytics/" target="_blank" rel="noreferrer"&gt;Cloudflare Analytics&lt;/a&gt;, que é bem mais leve e menos intrusivo, com foco em privacidade ao invés de capturar dados para publicidade. Eu utilizava o Google Analytics desde ~2010, quando movi meu blog do Wordpress para um servidor próprio, e por mais que tenho anos de dados lá, não vai fazer falta. Costumo utilizar esse tipo de ferramenta para ver quais posts são mais acessados e como leitores chegam no blog.&lt;/p&gt;&#10;&lt;p&gt;O Docusaurus também tem uma ferramenta que valida links quebrados e impede a publicação do site (esse comportamento é configurável). Isso ajuda demais a não deixar passar links que não funcionam, mas também foi um dos maiores trabalhos que tive quando migrei - corrigir todos links quebrados ao longo dos últimos 16 anos.&lt;/p&gt;&#10;&lt;p&gt;Por fim, por ser moderno e utilizar React, isso também me possibilita estudar algo novo, como o irmão &lt;a href="https://reactnative.dev/" target="_blank" rel="noreferrer"&gt;React Native&lt;/a&gt;, muito utilizado para aplicativos.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Conclusão&#10; &lt;div id="conclusão" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#conclus%c3%a3o" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;Já estava na hora de uma atualização na tecnologia por trás do blog, e apesar do Docusaurus parecer menos flexível do que o Jekyll, ele é mais moderno e fácil de manter. Agora é arrumar detalhes que possam estar quebrados e focar em publicar mais conteúdo por aqui, e também migrar meu &lt;a href="https://cicanci.com" target="_blank" rel="noreferrer"&gt;portfólio&lt;/a&gt; para Docusaurus.&lt;/p&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/categories/blog.webp" medium="image"/></item><item><title>Como implementar o padrão Message Queue no Unity</title><link>https://gamedeveloper.com.br/message-queue-pattern-unity/</link><guid>https://gamedeveloper.com.br/message-queue-pattern-unity/</guid><pubDate>Mon, 03 Feb 2025 00:00:00 +0000</pubDate><category>Unity</category><description>O padrão Message Queue é uma maneira simples e eficiente de desacoplar o código no seu projeto de jogo. Uma das formas mais fáceis e eficazes de desacoplar o código em um jogo é implementando o padrão Message Queue, também conhecido como Event Queue.&#10;</description><content:encoded>&lt;p&gt;O padrão Message Queue é uma maneira simples e eficiente de desacoplar o código no seu projeto de jogo. Uma das formas mais fáceis e eficazes de desacoplar o código em um jogo é implementando o padrão Message Queue, também conhecido como &lt;a href="https://gameprogrammingpatterns.com/event-queue.html" target="_blank" rel="noreferrer"&gt;Event Queue&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Esse padrão consiste em enviar mensagens quando você deseja atualizar algo na interface do jogo, por exemplo, sem precisar manter uma referência direta ao objeto da interface ou utilizar um padrão Singleton para expor acesso a ele. Em vez disso, a interface escutará o tipo de mensagem necessário para atualizar a interface, e essa mensagem será enviada apenas quando um sistema do jogo precisar atualizar a interface.&lt;/p&gt;&#10;&lt;p&gt;Vamos dividir o padrão Message Queue em três partes: o gerenciador da fila, responsável pela fila em si; a mensagem, que contém o que queremos enviar; e os ouvintes, que ficam esperando a mensagem para executar alguma ação assim que a receberem.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;O gerenciador Message Queue&#10; &lt;div id="o-gerenciador-message-queue" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#o-gerenciador-message-queue" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;O núcleo do padrão Message Queue é uma classe responsável por armazenar uma lista de ouvintes, além de adicionar e remover ouvintes e enviar mensagens para cada ouvinte que estiver escutando um tipo específico de mensagem.&lt;/p&gt;&#10;&lt;p&gt;No código abaixo, criamos nossa classe MessageQueue e definimos um Dictionary para armazenar nossos ouvintes, organizando-os por tipo. Cada Type possui uma List de Delegate, que são callbacks executados quando um tipo específico de mensagem é recebido.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cs" data-lang="cs"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MessageQueue&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Delegate&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_listeners&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;MessageQueue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;_listeners&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Delegate&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Em seguida, adicionamos métodos à nossa classe MessageQueue. O primeiro é o AddListener, que tem o tipo genérico T para o parâmetro listener.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cs" data-lang="cs"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;AddListener&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_listeners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TryGetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Delegate&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;listeners&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Delegate&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;_listeners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;O próximo método é o RemoveListener, que remove um ouvinte da lista e, caso a lista fique vazia, a remove do Dictionary.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cs" data-lang="cs"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;RemoveListener&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_listeners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TryGetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Delegate&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;_listeners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Por fim, o método SendMessage encontra uma lista de ouvintes aguardando um tipo de mensagem e chama cada um como callback, passando a mensagem como parâmetro.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cs" data-lang="cs"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;SendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_listeners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TryGetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetType&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Delegate&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;DynamicInvoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&#10;&lt;h2 class="relative group"&gt;O objeto Message&#10; &lt;div id="o-objeto-message" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#o-objeto-message" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;O objeto mensagem pode ser qualquer classe. No exemplo abaixo, criamos uma classe que representa uma mensagem contendo uma propriedade NewColor.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cs" data-lang="cs"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UpdateColorMessage&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt; &lt;span class="n"&gt;NewColor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&#10;&lt;h2 class="relative group"&gt;O uso dos ouvintes&#10; &lt;div id="o-uso-dos-ouvintes" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#o-uso-dos-ouvintes" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;A classe MessageQueueExample é um MonoBehaviour que pode ser adicionado a qualquer GameObject no Unity. Ela usa o MessageQueue para adicionar e remover um callback.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cs" data-lang="cs"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MessageQueueExample&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MonoBehaviour&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;MessageQueue&lt;/span&gt; &lt;span class="n"&gt;_messageQueue&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;MessageQueue&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;OnEnable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;_messageQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddListener&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UpdateColorMessage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;UpdateColor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;OnDisable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;_messageQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RemoveListener&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UpdateColorMessage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;UpdateColor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;UpdateColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UpdateColorMessage&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Use o message.NewColor para atualizar a cor&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Os métodos OnEnable e OnDisable são executados uma vez pelo Unity, garantindo que os ouvintes sejam sempre adicionados e removidos corretamente.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Enviando mensagens&#10; &lt;div id="enviando-mensagens" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#enviando-mensagens" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;Abaixo estão três métodos que enviam mensagens para mudar a cor para vermelho, verde e azul.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cs" data-lang="cs"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;ChangeColorToRed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;UpdateColorMessage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;NewColor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;red&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;_messageQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;ChangeColorToGreen&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;UpdateColorMessage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;NewColor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;green&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;_messageQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;ChangeColorToBlue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;UpdateColorMessage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;NewColor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blue&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;_messageQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Cada método cria uma instância de UpdateColorMessage e define a propriedade NewColor antes de enviar a mensagem aos ouvintes.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Conclusão&#10; &lt;div id="conclusão" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#conclus%c3%a3o" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;O padrão Message Queue é muito poderoso para desacoplar o código e facilitar a comunicação entre sistemas usando mensagens. Espero que este artigo tenha ajudado você a entender como implementá-lo usando C# no Unity.&lt;/p&gt;&#10;&lt;p&gt;O código deste artigo, assim como um exemplo completo implementado no Unity, pode ser encontrado no meu &lt;a href="https://github.com/cicanci/game-programming-patterns/tree/main/Assets/Scripts/DecouplingPatterns/MessageQueue" target="_blank" rel="noreferrer"&gt;repositório do GitHub&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Você já utilizou esse padrão em algum projeto? Compartilhe sua experiência nos comentários e me avise se tiver alguma dúvida!&lt;/p&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/categories/unity.webp" medium="image"/></item><item><title>Meu primeiro livro: Criando um Jogo RTS na Unity 2023</title><link>https://gamedeveloper.com.br/creating-an-rts-game-in-unity/</link><guid>https://gamedeveloper.com.br/creating-an-rts-game-in-unity/</guid><pubDate>Sun, 01 Oct 2023 00:00:00 +0000</pubDate><category>Unity</category><description>Fiquei sem atualizar o blog nos últimos meses, e hoje posso compartilhar o motivo: escrevi meu primeiro livro!&#10;Da concepção à publição foram meses dedicando meu tempo livre para escrever um livro que combinasse minha experiência profissional de quase 14 anos desenvolvendo jogos, sendo 10 anos utilizando Unity como minha principal engine. Foi uma oportunidade incrível e que não seria possível sem a editora Packt para me apoiar e fornecer o suporter necessário para revisão de textos, código, e muito mais.&#10;</description><content:encoded>&lt;p&gt;Fiquei sem atualizar o blog nos últimos meses, e hoje posso compartilhar o motivo: escrevi meu primeiro livro!&lt;/p&gt;&#10;&lt;p&gt;Da concepção à publição foram meses dedicando meu tempo livre para escrever um livro que combinasse minha experiência profissional de quase 14 anos desenvolvendo jogos, sendo 10 anos utilizando Unity como minha principal engine. Foi uma oportunidade incrível e que não seria possível sem a &lt;a href="https://www.packtpub.com/product/creating-an-rts-game-in-unity-2023/9781804613245" target="_blank" rel="noreferrer"&gt;editora Packt&lt;/a&gt; para me apoiar e fornecer o suporter necessário para revisão de textos, código, e muito mais.&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/book/book-cover.webp"&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;Com pouco mais de 550 páginas, em Inglês, o livro vai te ensinar a fazer um jogo RTS na Unity 2023 utilizando C#. O foco do livro é criar um jogo RTS do início ao fim, porém, todo conteúdo do livro é facilmente aplicável a praticamente qualquer outro tipo jogo, já que muitos conceitos e algoritmos são os mesmos. Apesar de ter sido um desafio ainda maior pra mim, escrever o livro em Inglês possibilita que mais pessoas tenham acesso ao seu conteúdo.&lt;/p&gt;&#10;&lt;p&gt;O livro já está em pré-venda, e será lançado no próximo dia 13 de Outubro na &lt;a href="https://a.co/d/3FenKy3" target="_blank" rel="noreferrer"&gt;Amazon Brasil&lt;/a&gt; em todas as outras, inclindo algumas livrarias nos EUA e Reino Unido, e no próprio &lt;a href="https://www.packtpub.com/product/creating-an-rts-game-in-unity-2023/9781804613245" target="_blank" rel="noreferrer"&gt;side da editora&lt;/a&gt;. O livro estará disponível em formato digital (Kindle) e físico.&lt;/p&gt;&#10;&lt;p&gt;Abaixo está uma descrição do livro sobre o conteúdo. Ficarei feliz de responder qualquer pergunta sobre o livro e seu conteúdo, e agradesço desde já se você puder adquirir o livro.&lt;/p&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Descrição do Livro&#10; &lt;div id="descrição-do-livro" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#descri%c3%a7%c3%a3o-do-livro" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;Construir um jogo de estratégia em tempo real de sucesso é desafiador, devido às mecânicas complexas e à necessidade de equilibrar diferentes elementos, garantindo que os jogadores desfrutem de criar e executar estratégias contra a inteligência artificial do jogo. &amp;quot;Creating an RTS game in Unity 2023&amp;quot; irá ensinar você a instalar e configurar o motor de jogo Unity, criar um novo projeto 3D e construir um editor de níveis para facilitar a modificação e adição de mapas ao jogo.&lt;/p&gt;&#10;&lt;p&gt;Ao longo do livro, o seu RTS começará a ganhar forma à medida que você aprender a implementar sistemas centrais, como batalhas corpo a corpo e à distância, geradores de unidades, controles de câmera, geração dinâmica de mapas, IA básica de inimigos e o algoritmo de pathfinding. Você também dominará a implementação de unidades de comando para executar ações, produção e gestão de recursos, física básica e detecção de colisões, tudo isso enquanto constrói um jogo de estratégia em tempo real do zero, utilizando C# e as últimas funcionalidades da Unity.&lt;/p&gt;&#10;&#10;&lt;h3 class="relative group"&gt;O Que Você Irá Aprender&#10; &lt;div id="o-que-você-irá-aprender" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#o-que-voc%c3%aa-ir%c3%a1-aprender" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Configuração do Unity e criação de projetos 3D.&lt;/li&gt;&#10;&lt;li&gt;Desenvolvimento de um editor de níveis personalizado.&lt;/li&gt;&#10;&lt;li&gt;Implementação de mecânicas de combate e unidades.&lt;/li&gt;&#10;&lt;li&gt;Controles de câmera envolventes para o jogador.&lt;/li&gt;&#10;&lt;li&gt;Geração dinâmica de mapas e IA de inimigos.&lt;/li&gt;&#10;&lt;li&gt;Algoritmo de pathfinding para movimentação eficiente das unidades.&lt;/li&gt;&#10;&lt;li&gt;Comandos de unidades para execução de ações estratégicas.&lt;/li&gt;&#10;&lt;li&gt;Gestão de recursos e produção de unidades.&lt;/li&gt;&#10;&lt;li&gt;Física e detecção de colisões para um gameplay realista.&lt;/li&gt;&#10;&lt;li&gt;Construção completa de um RTS usando C# e Unity.&lt;/li&gt;&#10;&lt;li&gt;Ao final deste livro, você estará apto a criar jogos de estratégia em tempo real profissionais e de alta qualidade, utilizando as melhores práticas e técnicas da indústria de jogos.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;PS: Comenta se você reconheceu a imagem da capa do livro, e se inscreva no meu &lt;a href="https://www.youtube.com/c/BrunoCicanci" target="_blank" rel="noreferrer"&gt;canal no YouTube&lt;/a&gt; por que muito contéudo novo está por vir!&lt;/p&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/book/book-banner-post.webp" medium="image"/></item><item><title>Desenvolvimento de jogos em Unity com TDD</title><link>https://gamedeveloper.com.br/unity-tdd/</link><guid>https://gamedeveloper.com.br/unity-tdd/</guid><pubDate>Sat, 04 Mar 2023 00:00:00 +0000</pubDate><category>Unity</category><description>Desenvolver jogos é um processo complexo e desafiador, mas o uso de técnicas de desenvolvimento de software pode ajudar a tornar esse processo mais eficiente e eficaz. Um desses métodos é o Test-Driven Development (TDD), que pode ser aplicado ao desenvolvimento de jogos com Unity.&#10;</description><content:encoded>&lt;p&gt;Desenvolver jogos é um processo complexo e desafiador, mas o uso de técnicas de desenvolvimento de software pode ajudar a tornar esse processo mais eficiente e eficaz. Um desses métodos é o Test-Driven Development (TDD), que pode ser aplicado ao desenvolvimento de jogos com Unity.&lt;/p&gt;&#10;&lt;p&gt;O TDD é um processo iterativo de desenvolvimento de software que consiste em escrever testes automatizados antes de escrever o código final. O processo começa com a escrita de um teste automatizado que falha e, em seguida, a escrita de código que faça o teste passar. Isso ajuda a garantir que o código escrito atenda aos requisitos definidos pelos testes e reduz o risco de erros e defeitos.&lt;/p&gt;&#10;&lt;p&gt;Ao usar o TDD no desenvolvimento de jogos com o Unity, é importante seguir algumas boas práticas recomendadas para garantir que o processo seja eficaz e eficiente.&lt;/p&gt;&#10;&#10;&lt;h4 class="relative group"&gt;Escreva testes para cada nova funcionalidade&#10; &lt;div id="escreva-testes-para-cada-nova-funcionalidade" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#escreva-testes-para-cada-nova-funcionalidade" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h4&gt;&#10;&lt;p&gt;Cada nova funcionalidade que você adiciona ao seu jogo deve ter seus próprios testes automatizados. Isso ajudará a garantir que o código funcione como esperado e que não há efeitos colaterais indesejados em outras partes do jogo.&lt;/p&gt;&#10;&#10;&lt;h4 class="relative group"&gt;Escreva testes para cada cenário de uso&#10; &lt;div id="escreva-testes-para-cada-cenário-de-uso" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#escreva-testes-para-cada-cen%c3%a1rio-de-uso" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h4&gt;&#10;&lt;p&gt;Além de testar cada nova funcionalidade, é importante testar cada cenário de uso do jogo. Por exemplo, se o jogo tiver uma fase em que o personagem precisa coletar moedas, é importante testar se todas as moedas são coletadas corretamente. Isso ajuda a garantir que o jogo seja jogável e livre de bugs.&lt;/p&gt;&#10;&#10;&lt;h4 class="relative group"&gt;Escreva testes para detectar erros comuns&#10; &lt;div id="escreva-testes-para-detectar-erros-comuns" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#escreva-testes-para-detectar-erros-comuns" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h4&gt;&#10;&lt;p&gt;Alguns erros são comuns no desenvolvimento de jogos com Unity, como erros de colisão e de controle de personagens. Escreva testes para detectar esses erros comuns e corrigi-los antes que eles se tornem problemas maiores.&lt;/p&gt;&#10;&#10;&lt;h4 class="relative group"&gt;Escreva testes antes de implementar o código final&#10; &lt;div id="escreva-testes-antes-de-implementar-o-código-final" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#escreva-testes-antes-de-implementar-o-c%c3%b3digo-final" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h4&gt;&#10;&lt;p&gt;O TDD requer que os testes sejam escritos antes do código final ser implementado. Isso ajuda a garantir que o código final atenda aos requisitos definidos pelos testes e ajuda a evitar a introdução de erros no código.&lt;/p&gt;&#10;&#10;&lt;h4 class="relative group"&gt;Execute testes automaticamente durante o processo de construção&#10; &lt;div id="execute-testes-automaticamente-durante-o-processo-de-construção" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#execute-testes-automaticamente-durante-o-processo-de-constru%c3%a7%c3%a3o" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h4&gt;&#10;&lt;p&gt;Os testes automatizados devem ser executados automaticamente durante o processo de construção do jogo. Isso ajuda a garantir que todas as alterações no código sejam testadas e que nenhum erro seja introduzido no código existente.&lt;/p&gt;&#10;&#10;&lt;h4 class="relative group"&gt;Refatore o código à medida que novos testes são adicionados&#10; &lt;div id="refatore-o-código-à-medida-que-novos-testes-são-adicionados" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#refatore-o-c%c3%b3digo-%c3%a0-medida-que-novos-testes-s%c3%a3o-adicionados" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h4&gt;&#10;&lt;p&gt;À medida que novos testes são adicionados, pode ser necessário refatorar o código existente para que ele atenda aos requisitos dos novos testes. Isso ajuda a garantir que o código seja fácil de manter e que não haja erros ou problemas de desempenho.&lt;/p&gt;&#10;&lt;p&gt;O uso do TDD no desenvolvimento de jogos com Unity pode ajudar a garantir que o jogo seja jogável, livre de erros e fácil de manter. Ao seguir as práticas recomendadas acima, você pode maximizar os benefícios do TDD e tornar o processo de desenvolvimento de jogos mais eficiente e eficaz.&lt;/p&gt;&#10;&lt;p&gt;Devo admitir que TDD é algo que está na minha lista para me aperfeiçoar a anos, e ainda não saí do básico que é criar os testes na Unity e tentar lembrar de rodar eles. Por isso automatizar os testes com Integração Contínua (CI) ou adicionar um script que obrigue rodar os testes antes de um &lt;code&gt;git push&lt;/code&gt; pode ajudar a introduzir o uso do TDD cada vez mais ao dia-a-dia.&lt;/p&gt;&#10;&lt;p&gt;Mas cuidado, o TDD não pode ser visto como uma barreira que atrasa o desenvolvimento - apenas entendendo e usando o TDD pensando sempre na qualidade do código pode fazer ver seu uso mais como uma garantia bem-vinda do que um empecílio.&lt;/p&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/categories/unity.webp" medium="image"/></item><item><title>Como criar atalhos com git alias</title><link>https://gamedeveloper.com.br/git-alias/</link><guid>https://gamedeveloper.com.br/git-alias/</guid><pubDate>Wed, 17 Aug 2022 00:00:00 +0000</pubDate><category>Game Dev</category><description>O comando git alias é um recurso muito poderoso do git que permite customizar comandos e ganhar tempo combinando uma sequencia de operações. Desde que aprendi a usar o git alias há alguns anos não consigo trabalhar sem algumas combinações de comandos que uso diáriamente.&#10;</description><content:encoded>&lt;p&gt;O comando &lt;a href="https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases" target="_blank" rel="noreferrer"&gt;git alias&lt;/a&gt; é um recurso muito poderoso do git que permite customizar comandos e ganhar tempo combinando uma sequencia de operações. Desde que aprendi a usar o &lt;code&gt;git alias&lt;/code&gt; há alguns anos não consigo trabalhar sem algumas combinações de comandos que uso diáriamente.&lt;/p&gt;&#10;&lt;p&gt;Todos &lt;code&gt;alias&lt;/code&gt; criados ficam na configuração local do &lt;code&gt;git&lt;/code&gt; na sua máquina. Para criar um &lt;code&gt;alias&lt;/code&gt;, basta usar o comando abaixo substituindo o &lt;code&gt;NAME&lt;/code&gt; pelo nome do seu &lt;code&gt;alias&lt;/code&gt; (sem espaços ou acentos) e substituindo o &lt;code&gt;COMMAND&lt;/code&gt; pelo comando que quer executar.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config --global alias.NAME COMMAND&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;No exemplo abaixo estamos criando um &lt;code&gt;alias&lt;/code&gt; com nome &lt;code&gt;s&lt;/code&gt; para o comando &lt;code&gt;status&lt;/code&gt;. Então, ao invés de usar &lt;code&gt;git status&lt;/code&gt; podemos usar &lt;code&gt;git s&lt;/code&gt; para o mesmo comando, como um atalho.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config --global alias.s status&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Caso você não queira mais o &lt;code&gt;alias&lt;/code&gt; criado, basta utilisar o comando abaixo com o nome criado para que ele seja removido das configurações:&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config --global --unset alias.s &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Agora que já sabemos criar um &lt;code&gt;alias&lt;/code&gt; vamos ver o poder real dele: a combinação de comandos. Para poder combinar os comandos precisamos:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Iniciar a sequencia de comandos com exclamação &lt;code&gt;!&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;Separar os comandos por e comercial duplo &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;Por fim, todos os comandos deve ficar dentre de aspas simples&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;No exemplo abaixo estamos criar um &lt;code&gt;alias&lt;/code&gt; com o nome &lt;code&gt;s&lt;/code&gt; que irá executar, em sequencia, os comandos &lt;code&gt;git status&lt;/code&gt; e &lt;code&gt;git pull&lt;/code&gt;.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config --global alias.s &lt;span class="s1"&gt;&amp;#39;!git status &amp;amp;&amp;amp; git pull&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Incrível, não? Confesso que uso e abuso deste recurso, e isso me ajuda demais no dia-a-dia. Abaixo vou deixar meus &lt;code&gt;alias&lt;/code&gt; preferidos: o &lt;code&gt;git pizza&lt;/code&gt; que limpa e atualiza o repositório; e o &lt;code&gt;git nuke&lt;/code&gt; que faz a mesma coisa porém descarta tudo que está no &lt;code&gt;gitignore&lt;/code&gt;, como se o repositório tivesse sido clonado sem nada além do que está no &lt;code&gt;remote&lt;/code&gt;.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config --global alias.pizza &lt;span class="s1"&gt;&amp;#39;!git clean -fd &amp;amp;&amp;amp; git reset --hard &amp;amp;&amp;amp; git fetch -fp &amp;amp;&amp;amp; git pull&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config --global alias.nuke &lt;span class="s1"&gt;&amp;#39;!git clean -fdx &amp;amp;&amp;amp; git reset --hard &amp;amp;&amp;amp; git fetch -fp &amp;amp;&amp;amp; git pull&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Um dos motivos de escrever este post foi ter estes comandos fáceis de achar quando eu precisar, além de compartilhar algo que acho bem interessante e produtivo no uso do &lt;code&gt;git&lt;/code&gt;. Se você tem alguma dica legal para usar o &lt;code&gt;git&lt;/code&gt; deixe aqui nos comentários.&lt;/p&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/images/2022/08/git.webp" medium="image"/></item><item><title>O Futuro do Game Design: Palestra de Mark Venturelli</title><link>https://gamedeveloper.com.br/futuro-game-design-venturelli/</link><guid>https://gamedeveloper.com.br/futuro-game-design-venturelli/</guid><pubDate>Mon, 08 Aug 2022 00:00:00 +0000</pubDate><category>Game Dev</category><description>O game designer e fundador da Rogue Snail, Mark Venturelli, apresentou uma brilhante palestra no Big Festival 2022 sobre sua visão para o futuro do game design e da indústria de games.&#10;</description><content:encoded>&lt;p&gt;O game designer e fundador da &lt;a href="https://roguesnail.com/games/" target="_blank" rel="noreferrer"&gt;Rogue Snail&lt;/a&gt;, &lt;a href="https://twitter.com/markventurelli" target="_blank" rel="noreferrer"&gt;Mark Venturelli&lt;/a&gt;, apresentou uma brilhante palestra no &lt;a href="https://www.bigfestival.com.br/homeen.html" target="_blank" rel="noreferrer"&gt;Big Festival 2022&lt;/a&gt; sobre sua visão para o futuro do game design e da indústria de games.&lt;/p&gt;&#10;&lt;p&gt;Apesar da qualidade baixa, é possível assistir a palestra na íntegra no vídeo abaixo. Esta é a primeira vez que não quero comentar o conteúdo da palestra para não dar &lt;em&gt;spoilers&lt;/em&gt;, pois recomendo assistir para entender onde Mark leva o espectador com sua apresentação. Posso adiantar que concordo com ele.&lt;/p&gt;&#10;&lt;p&gt;&lt;iframe style="width: 100%" height="400" src="https://www.youtube.com/embed/GzTj60CWhQo" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/p&gt;&#10;&lt;p&gt;O vídeo acima foi publicado no &lt;a href="https://www.youtube.com/user/msventurelli" target="_blank" rel="noreferrer"&gt;canal do Mark&lt;/a&gt;, e ele também disponibilizou os slides da apresentação &lt;a href="https://docs.google.com/presentation/d/1a8dMxaqyjWl4G6NO7mXF30CICHOJLkJxuP2Xrpky9rA/edit#slide=id.g34d3eed41a_0_45" target="_blank" rel="noreferrer"&gt;neste link&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/images/2022/08/mark.webp" medium="image"/></item><item><title>Como exibir um README na Unity ao abrir o projeto</title><link>https://gamedeveloper.com.br/unity-readme/</link><guid>https://gamedeveloper.com.br/unity-readme/</guid><pubDate>Sat, 16 Apr 2022 00:00:00 +0000</pubDate><category>Unity</category><description>Uma forma interessante de exibir uma mensagem de boas vindas ou informações sobre o projeto ao ser carregado é exibir um conteúdo similar à um arquivo README que pode ser customizado e exibido na janela do inspector dentro do editor da Unity. Neste vídeo eu mostro como criar um ScriptableObject, alterar sua visualização utilizando um CustomEditor e, por fim, colocar o foco do projeto e do inspector neste arquivo ao carregar o projeto na Unity.&#10;</description><content:encoded>&lt;p&gt;Uma forma interessante de exibir uma mensagem de boas vindas ou informações sobre o projeto ao ser carregado é exibir um conteúdo similar à um arquivo README que pode ser customizado e exibido na janela do inspector dentro do editor da Unity. Neste vídeo eu mostro como criar um &lt;code&gt;ScriptableObject&lt;/code&gt;, alterar sua visualização utilizando um &lt;code&gt;CustomEditor&lt;/code&gt; e, por fim, colocar o foco do projeto e do inspector neste arquivo ao carregar o projeto na Unity.&lt;/p&gt;&#10;&lt;p&gt;&lt;iframe style="width: 100%" height="400" src="https://www.youtube.com/embed/dKD4PXOdcyE" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/p&gt;&#10;&lt;p&gt;Abaixo estão os códigos das duas classes criadas no vídeo como referência, &lt;code&gt;Readme&lt;/code&gt; e &lt;code&gt;ReadEditor&lt;/code&gt;, respectivamente.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cs" data-lang="cs"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;[CreateAssetMenu(fileName = &amp;#34;Readme&amp;#34;, menuName = &amp;#34;Create Readme&amp;#34;)]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Readme&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ScriptableObject&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Sections&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cs" data-lang="cs"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEditor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;[CustomEditor(typeof(Readme))]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;[InitializeOnLoad]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReadmeEditor&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Editor&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;ReadmeEditor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;EditorApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delayCall&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;SelectReadme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;SelectReadme&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;EditorApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delayCall&lt;/span&gt; &lt;span class="p"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;SelectReadme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;readmeObject&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Resources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Readme&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Readme&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readmeObject&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;EditorUtility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FocusProjectWindow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Selection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activeObject&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;readmeObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kd"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;OnHeaderGUI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Readme&lt;/span&gt; &lt;span class="n"&gt;readme&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Readme&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;GUILayout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BeginHorizontal&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;label&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fontSize&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;GUILayout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;GUILayout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EndHorizontal&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;OnInspectorGUI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Readme&lt;/span&gt; &lt;span class="n"&gt;readme&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Readme&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;section&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;readme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sections&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;label&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fontSize&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;18&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wordWrap&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;GUILayout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;section&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;GUILayout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Space&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;18&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Veja a playlist do canal com mais vídeos sobre Unity &lt;a href="https://www.youtube.com/playlist?list=PLIDWyOQe6ONuhQrhN6YmTASLNlzRPuraR" target="_blank" rel="noreferrer"&gt;clicando aqui&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Dúvidas, comentários ou sugestões para futuros vídeos deixem aqui no post ou lá no vídeo no YouTube.&lt;/p&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/images/2022/04/unity-readme.webp" medium="image"/></item><item><title>Como adicionar e utilizar botões na Unity</title><link>https://gamedeveloper.com.br/unity-ui-button/</link><guid>https://gamedeveloper.com.br/unity-ui-button/</guid><pubDate>Sat, 15 Jan 2022 00:00:00 +0000</pubDate><category>Unity</category><description>Neste vídeo demonstro como criar um botão na interaface da Unity, algumas customizações que podem ser aplicadas nele, e como executar um script a partir do evento OnClick. Além de um script, também mostro como executar métodos de outros objetos da Unity no OnClick.&#10;</description><content:encoded>&lt;p&gt;Neste vídeo demonstro como criar um botão na interaface da Unity, algumas customizações que podem ser aplicadas nele, e como executar um script a partir do evento OnClick. Além de um script, também mostro como executar métodos de outros objetos da Unity no OnClick.&lt;/p&gt;&#10;&lt;p&gt;&lt;iframe style="width: 100%" height="400" src="https://www.youtube.com/embed/rgoSnyu5bF0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/p&gt;&#10;&lt;p&gt;Veja a playlist do canal com mais vídeos sobre Unity &lt;a href="https://www.youtube.com/playlist?list=PLIDWyOQe6ONuhQrhN6YmTASLNlzRPuraR" target="_blank" rel="noreferrer"&gt;clicando aqui&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Dúvidas, comentários ou sugestões para futuros vídeos deixem aqui no post ou lá no vídeo no YouTube.&lt;/p&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/images/2022/01/unity-ui-button.webp" medium="image"/></item><item><title>Utilizando Object Pool pattern na Unity</title><link>https://gamedeveloper.com.br/object-pool-unity/</link><guid>https://gamedeveloper.com.br/object-pool-unity/</guid><pubDate>Fri, 24 Dec 2021 00:00:00 +0000</pubDate><category>Unity</category><description>Neste vídeo mostro um exemplo de como utilizar o design patter Object Pool para reutilizar game objects em situações onde várias cópias são necessárias, como tiros ou inimigos, porém utilizando este design pattern para garantir um bom uso de memória.&#10;</description><content:encoded>&lt;p&gt;Neste vídeo mostro um exemplo de como utilizar o &lt;a href="https://gameprogrammingpatterns.com/object-pool.html" target="_blank" rel="noreferrer"&gt;design patter Object Pool&lt;/a&gt; para reutilizar game objects em situações onde várias cópias são necessárias, como tiros ou inimigos, porém utilizando este design pattern para garantir um bom uso de memória.&lt;/p&gt;&#10;&lt;p&gt;A ideia do Object Pool é ter um conjunto de objetos na memória que podem ser reutilizados. Na sua inicialização, um número pré-determinado de objetos são instanciados e ficam disponíveis porém não habilitados. Quando um objeto é requisitado, ele é habilitado e fica indisponível neste conjunto. E, quando não é mais necessário, ele fica desabilitado ao invés de ser destruído para que possa ser utilizado novamente.&lt;/p&gt;&#10;&lt;p&gt;&lt;iframe style="width: 100%" height="400" src="https://www.youtube.com/embed/0--XpK0NdKs" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/p&gt;&#10;&lt;p&gt;O projeto do vídeo está &lt;a href="https://github.com/cicanci/unity-object-pool-sample" target="_blank" rel="noreferrer"&gt;disponível neste repositório no meu GitHub&lt;/a&gt;. Dúvidas, comentários ou sugestões para futuros vídeos deixem aqui no post ou lá no vídeo no YouTube.&lt;/p&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/images/2021/12/object-pool-unity.webp" medium="image"/></item><item><title>Como fazer um sistema de build na Unity</title><link>https://gamedeveloper.com.br/sistema-build-unity/</link><guid>https://gamedeveloper.com.br/sistema-build-unity/</guid><pubDate>Sat, 18 Dec 2021 00:00:00 +0000</pubDate><category>Unity</category><description>A Unity possui um sistema de build onde você pode exportar seu projeto para diferentes plataformas e otimizaçoes. Este sistema é um pouco limitado quando utilizado através da interface do Editor, porém ele possui uma excelente API que pode ser utilizada para criar sistemas de build bem flexíveis e robustos.&#10;</description><content:encoded>&lt;p&gt;A Unity possui um sistema de build onde você pode exportar seu projeto para diferentes plataformas e otimizaçoes. Este sistema é um pouco limitado quando utilizado através da interface do Editor, porém ele possui uma excelente API que pode ser utilizada para criar sistemas de build bem flexíveis e robustos.&lt;/p&gt;&#10;&lt;p&gt;Neste vídeo eu demonstro como utilizar a API BuildPipeline da Unity e como gerar uma build através da linha de comando sem precisar abrir o projeto - o que pode ser utilizado em conjunto com sistemas de integraçao contínua, como o Jenkins. Apesar de não mostrar detalhes de como configurar, ao final do vídeo mostro como o Jenkins pode ser utilizado para gerar a build do exemplo do vídeo.&lt;/p&gt;&#10;&lt;p&gt;&lt;iframe style="width: 100%" height="400" src="https://www.youtube.com/embed/oiAWZxeOzmA" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/p&gt;&#10;&lt;p&gt;Alguns links mencionados no vídeo:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="https://docs.unity3d.com/ScriptReference/BuildPipeline.html" target="_blank" rel="noreferrer"&gt;Unity BuildPipeline&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://docs.unity3d.com/Manual/EditorCommandLineArguments.html" target="_blank" rel="noreferrer"&gt;Unity Editor command line arguments&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://gamedeveloper.com.br/raspberry-pi-zero-w-jenkins/" &gt;Rodando Jenkins em um Raspberry Pi Zero W&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Abaixo está a linha de comando executada para gerar as builds no vídeo. Os caminhos nesta linha de comando são do meu computador e podem não funcionar no seu, modifique de acordo com o seu ambiente de desenvolvimento.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;#34;C:\Program Files\Unity\Hub\Editor\2020.3.23f1\Editor\Unity.exe&amp;#34; \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -quit \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -batchmode \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -projectPath &amp;#34;C:\Projects\unity-build-system-sample&amp;#34; \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -executeMethod BuildSystem.BuildAll \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -logFile &amp;#34;C:\Projects\unity-build-system-sample\BuildLog.txt&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;O projeto do vídeo está &lt;a href="https://github.com/cicanci/unity-build-system-sample" target="_blank" rel="noreferrer"&gt;disponível neste repositório no meu GitHub&lt;/a&gt;. Dúvidas, comentários ou sugestões para futuros vídeos deixem aqui no post ou lá no vídeo no YouTube.&lt;/p&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/images/2021/12/sistema-build-unity.webp" medium="image"/></item><item><title>Unreal Engine 5 está disponível em Early Access</title><link>https://gamedeveloper.com.br/unreal-engine-5/</link><guid>https://gamedeveloper.com.br/unreal-engine-5/</guid><pubDate>Mon, 31 May 2021 00:00:00 +0000</pubDate><category>Unreal</category><description>Quase um ano após seu anúncio a Unreal Engine 5 já está disponível para testes através do programa de Early Access da Epic Games. Na prática isso quer dizer que desenvolvedores podem começar a utilizar a nova versão da engine para estudar e desenvolver protótipos, porém ela não está pronta para ser utilizada em um jogo comercial no momento.&#10;</description><content:encoded>&lt;p&gt;Quase um ano após seu &lt;a href="https://www.unrealengine.com/en-US/blog/a-first-look-at-unreal-engine-5" target="_blank" rel="noreferrer"&gt;anúncio&lt;/a&gt; a Unreal Engine 5 já está disponível para testes através do programa de &lt;a href="https://www.unrealengine.com/en-US/blog/unreal-engine-5-is-now-available-in-early-access" target="_blank" rel="noreferrer"&gt;Early Access&lt;/a&gt; da Epic Games. Na prática isso quer dizer que desenvolvedores podem começar a utilizar a nova versão da engine para estudar e desenvolver protótipos, porém ela não está pronta para ser utilizada em um jogo comercial no momento.&lt;/p&gt;&#10;&lt;p&gt;Para ter acesso ao Early Access da UE5 basta relizar o download ou atualizar o &lt;a href="https://www.epicgames.com/store/en-US/" target="_blank" rel="noreferrer"&gt;launcher da Epic Games&lt;/a&gt;, ir na sessão Unreal Engine do menu esquerdo e selecionar UE5 no menu superior. O download tem cerca de 10GB e a após a instalação o espaço ocupado é de aproximadamente 31GB (praticamente o mesmo espaço ocupado pela UE4).&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2021/05/ue5-launcher.webp"&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;Assim como na versão anteriore da engine, o seu código-fonta também está &lt;a href="https://github.com/EpicGames/UnrealEngine/releases/tag/5.0.0-early-access-1" target="_blank" rel="noreferrer"&gt;disponível no GitHub&lt;/a&gt;. A Epic Games também disponibilizou dois cursos em sua plataforma online para quem quiser começar a estudar a UE5. &lt;a href="https://www.unrealengine.com/en-US/onlinelearning-courses/ue5-early-access-quickstart" target="_blank" rel="noreferrer"&gt;UE5 Early Access Quickstart&lt;/a&gt; é um curso de 2 horas que serve como uma introdução a nova versão da engine, enquando que o curso &lt;a href="https://www.unrealengine.com/en-US/onlinelearning-courses/upgrading-to-ue5-early-access" target="_blank" rel="noreferrer"&gt;Upgrading to UE5 Early Acess&lt;/a&gt; possui apenas 20 minutos e tem como objetivo mostrar como importar um projeto feito na UE4.&lt;/p&gt;&#10;&lt;p&gt;O vídeo abaixo é uma pequena introdução do que está presente na Unreal Engine 5 Early Access.&lt;/p&gt;&#10;&lt;p&gt;&lt;iframe style="width: 100%" height="400" src="https://www.youtube.com/embed/qC5KtatMcUw" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/p&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/images/2021/05/unreal-engine-5-animation.webp" medium="image"/></item><item><title>Download de modelos 3D para jogos</title><link>https://gamedeveloper.com.br/download-modelos-3d-jogos/</link><guid>https://gamedeveloper.com.br/download-modelos-3d-jogos/</guid><pubDate>Fri, 09 Apr 2021 00:00:00 +0000</pubDate><category>Game Dev</category><description>Há um tempo atrás escrevi este post sobre sites para baixar sprites e modelos de jogos. Por mais que seja legal utilizar artes dos nossos jogos favoritos, existem leis de copyright que não permitem que um jogo seja feito e comercializado com propriedade intelectual de outras empresas.&#10;</description><content:encoded>&lt;p&gt;Há um tempo atrás escrevi este post sobre &lt;a href="https://gamedeveloper.com.br/download-sprites-jogos" &gt;sites para baixar sprites e modelos de jogos&lt;/a&gt;. Por mais que seja legal utilizar artes dos nossos jogos favoritos, existem leis de copyright que não permitem que um jogo seja feito e comercializado com propriedade intelectual de outras empresas.&lt;/p&gt;&#10;&lt;p&gt;Pensando nisso montei a lista de links abaixo, que são de sites onde artistas e animadores disponibilizam seu trabalho. Existe muito conteúdo gratuito mas lembre de sempre creditar o autor em seu jogo. Mesmo que não seja necessário para alguns casos, é um tipo de reconhecimento e divulgação muito bem vinda para alguem que dedicou horas (e até dias) criando uma arte ou animação, e depois disponibilizando gratuitamente.&lt;/p&gt;&#10;&lt;p&gt;Existem artes e animações que são pagas, muitas com preço bem acessível. Se você está fazendo um prótipo ou apenas testando algo, o conteúdo gratuito deve ser o suficiente para te ajudar em seu projeto. Porém, se você está desenvolvendo um jogo para ser lançado, recomendo dar uma olhada nas artes pagas pois existem muitas tão incríveis que vão deixar seu jogo ainda mais profissional, além de ajudar um artista talentoso.&lt;/p&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Sketchfab&#10; &lt;div id="sketchfab" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#sketchfab" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;Conteúdo: Modelos 3D e animações (pagos e gratuitos). Possui &lt;a href="https://sketchfab.com/importers" target="_blank" rel="noreferrer"&gt;plugins&lt;/a&gt; para Unity, Unreal e Godot.&lt;/p&gt;&#10;&lt;p&gt;Site: &lt;a href="https://sketchfab.com/3d-models/popular" target="_blank" rel="noreferrer"&gt;https://sketchfab.com&lt;/a&gt;&lt;/p&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Turbo Squid&#10; &lt;div id="turbo-squid" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#turbo-squid" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;Conteúdo: Modelos 3D e animações (pagos e gratuitos).&lt;/p&gt;&#10;&lt;p&gt;Site: &lt;a href="https://turbosquid.com/Search/3D-Models" target="_blank" rel="noreferrer"&gt;https://turbosquid.com&lt;/a&gt;&lt;/p&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Unity Asset Store&#10; &lt;div id="unity-asset-store" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#unity-asset-store" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;Conteúdo: Modelos 3D e animações (pagos e gratuitos).&lt;/p&gt;&#10;&lt;p&gt;Site: &lt;a href="https://assetstore.unity.com/3d" target="_blank" rel="noreferrer"&gt;https://assetstore.unity.com&lt;/a&gt;&lt;/p&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Unreal Marketplace&#10; &lt;div id="unreal-marketplace" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#unreal-marketplace" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;Conteúdo: Modelos 3D e animações (pagos e gratuitos).&lt;/p&gt;&#10;&lt;p&gt;Site: &lt;a href="https://unrealengine.com/marketplace/en-US/showcase?count=20&amp;amp;sortBy=effectiveDate&amp;amp;sortDir=DESC&amp;amp;start=0" target="_blank" rel="noreferrer"&gt;https://unrealengine.com/marketplace&lt;/a&gt;&lt;/p&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Kenny&#10; &lt;div id="kenny" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#kenny" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;Conteúdo: Modelos 3D (pagos e gratuitos).&lt;/p&gt;&#10;&lt;p&gt;Site: &lt;a href="https://kenney.nl/assets?q=3d" target="_blank" rel="noreferrer"&gt;https://kenney.nl&lt;/a&gt;&lt;/p&gt;&#10;&#10;&lt;h3 class="relative group"&gt;Open Game Art&#10; &lt;div id="open-game-art" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#open-game-art" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h3&gt;&#10;&lt;p&gt;Conteúdo: Modelos 3D (gratuitos).&lt;/p&gt;&#10;&lt;p&gt;Site: &lt;a href="https://opengameart.org/art-search-advanced?keys=&amp;amp;field_art_type_tid%5B%5D=10&amp;amp;sort_by=count&amp;amp;sort_order=DESC" target="_blank" rel="noreferrer"&gt;https://opengameart.org&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;Conhece algum que não está a lista? Deixe um comentário abaixo pra eu poder incluir na lista.&lt;/p&gt;&#10;&lt;p&gt;Modelo 3D da capa: &lt;a href="https://sketchfab.com/3d-models/the-lighthouse-1a85945dd2a840f594bf6cb003176a54" target="_blank" rel="noreferrer"&gt;The Lighthouse&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/images/2021/04/lighthouse3d.webp" medium="image"/></item><item><title>Hello World usando SDL no Visual Studio</title><link>https://gamedeveloper.com.br/hello-world-sdl-visual-studio/</link><guid>https://gamedeveloper.com.br/hello-world-sdl-visual-studio/</guid><pubDate>Sun, 21 Mar 2021 00:00:00 +0000</pubDate><category>Como Programar Jogos</category><description>A SDL é uma biblioteca para desenvolvimento de jogos cross-platform com código aberto que existe desde 1998. Diversos jogos foram publicados utilizando SDL, como por exemplo, Half-Life 2, Left 4 Dead 2, Dying Light, Factorio, FTL, entre muitos outros. Sua linguagem de programação principal é C e C++, porém existem alguns bindings que permitem programar em outras linguagens como C#, Go, Lua, Rust e Python. Por ser "apenas" uma biblioteca, não possui uma interface gráfica como a Unity ou Unreal. Neste post vou demonstrar o passo a passo para criar um projeto utilizando o Visual Studio no Windows.&#10;</description><content:encoded>&lt;p&gt;A &lt;a href="https://libsdl.org/" target="_blank" rel="noreferrer"&gt;SDL&lt;/a&gt; é uma biblioteca para desenvolvimento de jogos &lt;em&gt;cross-platform&lt;/em&gt; com &lt;a href="https://github.com/libsdl-org/SDL" target="_blank" rel="noreferrer"&gt;código aberto&lt;/a&gt; que existe desde 1998. Diversos jogos foram publicados utilizando SDL, como por exemplo, Half-Life 2, Left 4 Dead 2, Dying Light, Factorio, FTL, entre muitos outros. Sua linguagem de programação principal é C e C++, porém existem alguns &lt;a href="https://libsdl.org/languages.php" target="_blank" rel="noreferrer"&gt;bindings&lt;/a&gt; que permitem programar em outras linguagens como C#, Go, Lua, Rust e Python. Por ser &amp;quot;apenas&amp;quot; uma biblioteca, não possui uma interface gráfica como a Unity ou Unreal. Neste post vou demonstrar o passo a passo para criar um projeto utilizando o Visual Studio no Windows.&lt;/p&gt;&#10;&lt;p&gt;Para começar &lt;a href="https://libsdl.org/download-2.0.php" target="_blank" rel="noreferrer"&gt;faça o download&lt;/a&gt; do &lt;em&gt;runtime binaries&lt;/em&gt; da sua plataforma. Se você está utilizando Windows 10, pode fazer download da versão 64-bit Windows. Também é possível utilizar o código fonte, mas o runtime binaries é o suficiente para iniciar um projeto. Para referência, a versão da SDL utilizada é 2.0.14.&lt;/p&gt;&#10;&#10;&lt;h4 class="relative group"&gt;Configuração no Visual Studio&#10; &lt;div id="configuração-no-visual-studio" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#configura%c3%a7%c3%a3o-no-visual-studio" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h4&gt;&#10;&lt;p&gt;Estou utilizando o Visual Studio 2019 Community Edition que pode ser &lt;a href="https://visualstudio.microsoft.com/" target="_blank" rel="noreferrer"&gt;baixado aqui&lt;/a&gt;. Apesar das imagens abaixo serem da versão 2019 a configuração é a mesma em outras versões do Visual Studio.&lt;/p&gt;&#10;&lt;p&gt;Após realizar o &lt;a href="https://libsdl.org/download-2.0.php" target="_blank" rel="noreferrer"&gt;download da SDL&lt;/a&gt; faça a extração em algum local do seu computador &lt;strong&gt;sem espaços&lt;/strong&gt; no nome dos diretórios. Eu gosto de colocar meus projetos em &lt;code&gt;C:\Projects&lt;/code&gt; e qualquer biblioteca ou dependência (como os arquivos da SDL) em &lt;code&gt;C:\Dev&lt;/code&gt;.&lt;/p&gt;&#10;&lt;p&gt;Vamos criar um projeto novo do tipo &lt;em&gt;Console App&lt;/em&gt;. Este projeto vai ter apenas um arquivo &lt;em&gt;cpp&lt;/em&gt;, onde vamos adicionar o código do Hello World. O nome deste arquivo não importa, mas gosto de renomeá-lo para &lt;code&gt;main.cpp&lt;/code&gt;.&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2021/03/vs-new-project-sdl.webp"&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;Com o projeto criado basta clicar com o botão direito no &lt;em&gt;Project&lt;/em&gt; (dentro da &lt;em&gt;Solution&lt;/em&gt;) e selecionar a última opção chamada &lt;em&gt;Properties&lt;/em&gt;. A seguir iremos adicionar o caminho para as pastas &lt;code&gt;include&lt;/code&gt; e &lt;code&gt;lib\x64&lt;/code&gt; em &lt;em&gt;VC++ Directories&lt;/em&gt;, e as libs &lt;code&gt;SDL2.lib&lt;/code&gt; e &lt;code&gt;SDL2main.lib&lt;/code&gt; em &lt;em&gt;Linker/Input&lt;/em&gt;, conforme as imagens abaixo. Lembre-se de selecionar &lt;em&gt;All Platforms&lt;/em&gt; antes de iniciar a configuração.&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2021/03/vs-sdl-include.webp"&gt;&#10;&lt;/figure&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2021/03/vs-sdl-libs.webp"&gt;&#10;&lt;/figure&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2021/03/vs-link-sdl-libs.webp"&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;Por fim, precisamos copiar o arquivo &lt;code&gt;SDL2.dll&lt;/code&gt; que está em &lt;code&gt;lib\x64&lt;/code&gt; para dentro do projeto, junto com o nosso arquivo &lt;em&gt;cpp&lt;/em&gt;. Esta é a última etapa para configurar o Visual Studio e compilar o projeto com a SDL.&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2021/03/sdk-dll.webp"&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;Como realizamos toda a configuração utilizando a &lt;code&gt;lib\x64&lt;/code&gt; lembre de selecionar &lt;code&gt;x64&lt;/code&gt; na Visual Studio antes de compilar e executar o projeto.&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2021/03/vs-build-x64.webp"&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;h4 class="relative group"&gt;Hello World&#10; &lt;div id="hello-world" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#hello-world" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h4&gt;&#10;&lt;p&gt;Um projeto com SDL segue uma sequência bem definida de métodos, os quais devem ser executados para que tudo funcione corretamente. O código abaixo é a base que iremos utilizar, contendo a importação do SDL, o tamanho da tela e da imagem que vamos exibir e o método principal da aplicação. Este código não faz nada, mas pode ser executado para testar se a SDL está configurada corretamente no projeto do Visual Studio.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;SDL.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define WINDOW_WIDTH 640&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define WINDOW_HEIGHT 480&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define IMAGE_WIDTH 256&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define IMAGE_HEIGHT 256&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Os trechos de código a seguir estão dentro do método &lt;code&gt;main()&lt;/code&gt;. Em primeiro lugamos vamos inicializar a SDL e verificar se foi inicializada com sucesso. Caso algum erro seja retornado, iremos exibir a mensagem de erro no console utilizando &lt;code&gt;SDL_Log()&lt;/code&gt; e finalizar a aplicação. Mais detalhes do método de &lt;a href="https://wiki.libsdl.org/SDL_Init" target="_blank" rel="noreferrer"&gt;inicialização aqui&lt;/a&gt;.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SDL_Init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SDL_INIT_EVERYTHING&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SDL_Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;SDL_Init Error: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SDL_GetError&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;A seguir criaremos nossa &lt;em&gt;Window&lt;/em&gt; onde o jogo será exibido. No código abaixo, a janela será criada no centro da tela com o tamanho definido anteriormente, e o título &lt;em&gt;Hello World SDL2&lt;/em&gt;. Você pode &lt;a href="https://wiki.libsdl.org/SDL_CreateWindow" target="_blank" rel="noreferrer"&gt;ver aqui&lt;/a&gt; todos os parâmetro em detalhes.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;SDL_Window&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SDL_CreateWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello World SDL2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SDL_WINDOWPOS_CENTERED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SDL_WINDOWPOS_CENTERED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;WINDOW_WIDTH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;WINDOW_HEIGHT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SDL_WINDOW_SHOWN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="k"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SDL_Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;SDL_CreateWindow Error: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SDL_GetError&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;O último item necessário para terminarmos a inicialização da SDL é o &lt;em&gt;Renderer&lt;/em&gt;, responsável por &amp;quot;desenhar&amp;quot; na tela criada anteriormente. Os detalhes da criação do renderer podem ser &lt;a href="https://wiki.libsdl.org/SDL_CreateRenderer" target="_blank" rel="noreferrer"&gt;vistos aqui&lt;/a&gt;.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;SDL_Renderer&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;renderer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SDL_CreateRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SDL_RENDERER_ACCELERATED&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;renderer&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="k"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SDL_Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;SDL_CreateRenderer Error: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SDL_GetError&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Com a SDL inicializada e a window e o renderer criados, podemos desenhar uma imagem na tela. O código abaixo carrega uma imagem no formato &lt;code&gt;BMP&lt;/code&gt; e a exibe no centro da tela. Primeiro criamos uma &lt;em&gt;surface&lt;/em&gt; para então criar a &lt;em&gt;texture&lt;/em&gt;. Com a textura criada, podemos remover a surface da memória (a texture será removida só no final da aplicação). O &lt;code&gt;SDL_Rect&lt;/code&gt; possui as coordenadas onde a imagem será desenhada e seu tamanho, considerando que o ponto de origem da imagem é no seu centro. Por fim, desenhamos a texture na tela utilizando o &lt;code&gt;SDL_Render&lt;/code&gt;.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;SDL_Surface&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SDL_LoadBMP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;image.bmp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="k"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SDL_Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;SDL_LoadBMP Error: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SDL_GetError&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;SDL_Texture&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;texture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SDL_CreateTextureFromSurface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;texture&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="k"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SDL_Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;SDL_CreateTextureFromSurface Error: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SDL_GetError&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;SDL_FreeSurface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;SDL_Rect&lt;/span&gt; &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;WINDOW_WIDTH&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.5f&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;IMAGE_WIDTH&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.5f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;WINDOW_HEIGHT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.5f&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;IMAGE_HEIGHT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.5f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IMAGE_WIDTH&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IMAGE_HEIGHT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;SDL_RenderClear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;SDL_RenderCopy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;texture&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;SDL_RenderPresent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Todo esse código acontece antes do &lt;em&gt;main loop&lt;/em&gt;, ou seja, será executado apenas uma vez. A imagem do exemplo será desenhada apenas uma vez na tela e, como no loop abaixo não tem outra chamada para o &lt;code&gt;SDL_Render&lt;/code&gt;, ela continuará desenhada até o fim. Este loop é usado apenas para ler o &lt;em&gt;input&lt;/em&gt; do jogador e sair do loop se a janela for fechada.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SDL_Event&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SDL_PollEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;SDL_QUIT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Quando o jogador fechar a tela e o jogo sair do loop vamos finalizar a SDL. Para isso tiramos tudo que foi alocado da memória, como texture, renderer e window. E por fim finalizamos a SDL.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;SDL_DestroyTexture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;texture&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;SDL_DestroyRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;SDL_DestroyWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;SDL_Quit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Assim temos nosso &lt;em&gt;Hello World&lt;/em&gt; com uma imagem desenhada na tela. &lt;a href="https://gist.github.com/cicanci/b54715298ab55dff2fbcd0ca3829d13b" target="_blank" rel="noreferrer"&gt;A class completa pode ser vista neste gist&lt;/a&gt;. Se tiver alguma dúvida sobre os métodos e objetos da SDL acesse a &lt;a href="https://wiki.libsdl.org/" target="_blank" rel="noreferrer"&gt;documentação da biblioteca&lt;/a&gt;, a qual contem bastante informação e exemplos práticos.&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2021/03/hello-world-sdl.webp"&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;h4 class="relative group"&gt;Cuidados&#10; &lt;div id="cuidados" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#cuidados" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h4&gt;&#10;&lt;p&gt;Pelo tamanho do post é possível ver que desenhar uma simples imagem na tela exige uma boa quantidade de código. Enquanto na Unity, isso pode ser feito praticamente arrastando uma imagem para dentro da engine, com a SDL tudo é mais &amp;quot;manual&amp;quot;. Isso pode dar mais trabalho, mas também da mais controle ao programador. Por isso, é preciso prestar atenção para não fazer algo errado sem perceber.&lt;/p&gt;&#10;&lt;p&gt;Quando estava criando este exemplo para o post, percebi que o simples fato de desenhar uma imagem na tela estava utilizando &lt;strong&gt;97%&lt;/strong&gt; da minha GPU (o que é um absurdo). Notei que meu erro foi executar os métodos &lt;code&gt;SDL_RenderClear()&lt;/code&gt;, &lt;code&gt;SDL_RenderCopy()&lt;/code&gt; e &lt;code&gt;SDL_RenderPresent()&lt;/code&gt; a cada loop (é um exagero para uma imagem estática).&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2021/03/bad-gpu.webp"&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;Movendo as chamadas destes métodos para fora do loop, a utilização da GPU caiu para &lt;strong&gt;1%&lt;/strong&gt;. Existem algumas técnicas para controlar melhor o &lt;em&gt;main loop&lt;/em&gt; e o &lt;em&gt;frame rate&lt;/em&gt;, assim como desenhar apenas quando a imagem mudar de posição, entre outras possibilidades. O que me pegou de surpresa foi a &lt;a href="https://wiki.libsdl.org/SDL_CreateRenderer" target="_blank" rel="noreferrer"&gt;própria documentação ter este exemplo&lt;/a&gt;, de uma imagem estática sendo desenhada todo frame.&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2021/03/good-gpu.webp"&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;h4 class="relative group"&gt;Conclusão&#10; &lt;div id="conclusão" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#conclus%c3%a3o" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h4&gt;&#10;&lt;p&gt;Trabalhar com a SDL é um pouco lento no início até ter a base do jogo pronta, depois disso é a programação do jogo em si. É mais complicado do que utilizar a Unity e C#, por exemplo, com uma curva de aprendizado bem maior. Porém, é bem recompensador e importante aprender a programar (e programar jogos) em um &amp;quot;nível mais baixo&amp;quot; do que em uma engine que já te dá tudo pronto e você não vê muito bem o que acontece por trás do seu script.&lt;/p&gt;&#10;&lt;p&gt;O código completo está disponível &lt;a href="https://gist.github.com/cicanci/b54715298ab55dff2fbcd0ca3829d13b" target="_blank" rel="noreferrer"&gt;neste link&lt;/a&gt;. Caso queira se aprofundar, recomendo olhar a &lt;a href="https://wiki.libsdl.org" target="_blank" rel="noreferrer"&gt;documentação oficial&lt;/a&gt;. &lt;a href="https://www.parallelrealities.co.uk/tutorials/" target="_blank" rel="noreferrer"&gt;Este site&lt;/a&gt; também possui bons exemplos de programação de jogos com SDL.&lt;/p&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/images/2021/03/hello-world-sdl.webp" medium="image"/></item><item><title>Como fazer um plugin para Android em Java na Unity</title><link>https://gamedeveloper.com.br/unity-plugin-android/</link><guid>https://gamedeveloper.com.br/unity-plugin-android/</guid><pubDate>Mon, 01 Mar 2021 00:00:00 +0000</pubDate><category>Unity</category><description>Existem algumas estruturas possíveis para implementar um plugin Android na Unity. Quando utilizamos um plugin desenvolvido por terceiros é comum que a sua distribuição seja através de um arquivo AAR, que é uma biblioteca java para Android, junto com alguns scripts em C# para sua utilização. Esta é a opção mais simples, pois a Unity já reconhece o arquivo AAR como uma biblioteca Android e cuida do resto na compilação. Também é possível utilizar um arquivo JAR, mas não é um formato muito utilizado hoje em dia para desenvolvimento com Android, e até exige um pouco mais de configuração para ser utilizado na Unity.&#10;</description><content:encoded>&lt;p&gt;Existem algumas estruturas possíveis para implementar um plugin Android na Unity. Quando utilizamos um plugin desenvolvido por terceiros é comum que a sua distribuição seja através de um &lt;a href="https://developer.android.com/studio/projects/android-library.html#aar-contents" target="_blank" rel="noreferrer"&gt;arquivo AAR&lt;/a&gt;, que é uma biblioteca java para Android, junto com alguns scripts em C# para sua utilização. Esta é a opção mais simples, pois a Unity já reconhece o arquivo AAR como uma biblioteca Android e cuida do resto na compilação. Também é possível utilizar um &lt;a href="https://docs.oracle.com/javase/tutorial/deployment/jar/basicsindex.html" target="_blank" rel="noreferrer"&gt;arquivo JAR&lt;/a&gt;, mas não é um formato muito utilizado hoje em dia para desenvolvimento com Android, e até exige um pouco mais de configuração para ser utilizado na Unity.&lt;/p&gt;&#10;&lt;p&gt;Outra maneira de desenvolver um plugin dentro da Unity é mantendo o código java dentro do próprio projeto e, com ajuda de alguns outros arquivos, a Unity consegue configurar e compilar seu código Java como uma biblioteca para Android. Neste post não vou explicar como criar um arquivo AAR, mas é tão simples quanto criar um &lt;a href="https://developer.android.com/studio/projects/android-library" target="_blank" rel="noreferrer"&gt;projeto de library no Android Studio&lt;/a&gt; e compilar para exportar o AAR, e a partir daí pode pular para a integração em C# na Unity.&lt;/p&gt;&#10;&#10;&lt;h4 class="relative group"&gt;Estrutura&#10; &lt;div id="estrutura" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#estrutura" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h4&gt;&#10;&lt;p&gt;Para usar o código java dentro da Unity precisamos montar a estrutura abaixo, assim a engine vai compilar o código corretamente como uma biblioteca Android. Qualquer plugin com código nativo deve sempre ser colocado dentro de uma pasta &lt;em&gt;Plugins&lt;/em&gt;, e em uma sub-pasta com o nome da plataforma, no caso &lt;em&gt;Android&lt;/em&gt;. Na pasta Android é onde fica a biblioteca Android, onde no exemplo abaixo é chamada &lt;strong&gt;native-test-lib&lt;/strong&gt;. Agora precisamos de pelo menos mais 3 arquivos, que eu irei descrever em seguida.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├───Plugins&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └───Android&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └───native-test-lib&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │ AndroidManifest.xml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │ build.gradle&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │ project.properties&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └───src&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └───com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └───cicanci&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └───unity&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ NativeTest.java&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&#10;&lt;h4 class="relative group"&gt;Arquivo de configuração&#10; &lt;div id="arquivo-de-configuração" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#arquivo-de-configura%c3%a7%c3%a3o" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h4&gt;&#10;&lt;p&gt;No arquivo &lt;code&gt;project.properties&lt;/code&gt; é necessário colocar apenas dois parâmetros para que o projeto seja reconhecido como uma biblioteca Android, a versão da &lt;a href="https://developer.android.com/studio/releases/platforms" target="_blank" rel="noreferrer"&gt;API do Android&lt;/a&gt; que será a target (não é a versão mínima e não necessariamente a versão que será utilizada na compilação), e o parâmetro que habilita o projeto como &lt;em&gt;library&lt;/em&gt;.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;target=android-21&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;android.library=true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&#10;&lt;h4 class="relative group"&gt;Android Manifest&#10; &lt;div id="android-manifest" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#android-manifest" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h4&gt;&#10;&lt;p&gt;O &lt;code&gt;AndroidManifest.xml&lt;/code&gt; utilizado na library tem a o mínimo necessário para a &lt;a href="https://developer.android.com/studio/releases/platforms" target="_blank" rel="noreferrer"&gt;definição deste arquivo&lt;/a&gt;: &lt;em&gt;package&lt;/em&gt; e versão. O package é o mesmo que será utilizado no arquivo Java, e neste exemplo é &lt;em&gt;com.cicanci.unity&lt;/em&gt;.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;utf-8&amp;#34;?&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;manifest xmlns:android=&amp;#34;http://schemas.android.com/apk/res/android&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; package=&amp;#34;com.cicanci.unity&amp;#34; android:versionCode=&amp;#34;1&amp;#34; android:versionName=&amp;#34;1.0&amp;#34; &amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;application&amp;gt;&amp;lt;/application&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/manifest&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&#10;&lt;h4 class="relative group"&gt;Compilação com gradle&#10; &lt;div id="compilação-com-gradle" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#compila%c3%a7%c3%a3o-com-gradle" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h4&gt;&#10;&lt;p&gt;Por fim, precisaremos apenas do arquivo &lt;code&gt;build.gradle&lt;/code&gt; que também define o projeto como library e mostra para o compilador onde está o &lt;code&gt;AndroidManifest.xml&lt;/code&gt; e o código Java (na pasta &lt;code&gt;src&lt;/code&gt;). Aqui também temos definidas algumas versões para o SDK do Android utilizado para compilação e o mesmo target definido no arquivo &lt;code&gt;project.properties&lt;/code&gt;. Este arquivo será compilado pela Unity junto com o &lt;a href="https://gradle.org/" target="_blank" rel="noreferrer"&gt;gradle&lt;/a&gt; do projeto.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apply plugin: &amp;#39;android-library&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;android {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sourceSets {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; main {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; manifest.srcFile &amp;#39;AndroidManifest.xml&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; java.srcDirs = [&amp;#39;src&amp;#39;]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; compileSdkVersion 30&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; buildToolsVersion &amp;#39;30.0.3&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; defaultConfig {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; targetSdkVersion 21&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Com todos os arquivos acima definidos e utilizando a estrutura mostrada no início do post, a Unity irá reconhecer o projeto como um plugin para Android, como podemos ver na imagem abaixo.&lt;/p&gt;&#10;&lt;figure&gt;&#10; &lt;img&#10; class="my-0 rounded-md"&#10; loading="lazy"&#10; decoding="async"&#10; fetchpriority="low"&#10; alt=""&#10; src="https://gamedeveloper.com.br/images/2021/03/unity-android-plugin.webp"&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;h4 class="relative group"&gt;Código java&#10; &lt;div id="código-java" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#c%c3%b3digo-java" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h4&gt;&#10;&lt;p&gt;Eu quis manter este exemplo bem simples por que meu objetivo é demonstrar como criar um plugin e utilizá-lo na Unity, por isso o código abaixo faz algo bem simples: recebe e retorna strings e inteiros. O package aqui deve ser o mesmo definido no &lt;code&gt;AndroidManifest.xml&lt;/code&gt;. Este é um exemplo simples, porém não existem limites para uma library Android aqui quando comparada com um aplicativo para Android feito fora da Unity.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;com.cicanci.unity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NativeTest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello from Android&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;getCounter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;getMessage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;setCounter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;counter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;setMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;A localização do arquivo Java dentro do plugin deve ter ser em uma estrutura de pastas que reflitam o package. Como neste exemplo o package é &lt;code&gt;com.cicanci.unity&lt;/code&gt;, o arquivo &lt;code&gt;NativeTest.java&lt;/code&gt; deve ficar dentro de &lt;code&gt;Plugins/Android/native-test-lib/src/com/cicanci/unity/&lt;/code&gt; - a localização do plugin Android na Unity + a pasta que o arquivo &lt;code&gt;build.gradle&lt;/code&gt; vai procurar o código Java que é &lt;code&gt;src&lt;/code&gt; + estrutura que reflete o package no &lt;code&gt;AndroidManifest.xml&lt;/code&gt;.&lt;/p&gt;&#10;&#10;&lt;h4 class="relative group"&gt;Implementação no C#&#10; &lt;div id="implementação-no-c" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#implementa%c3%a7%c3%a3o-no-c" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h4&gt;&#10;&lt;p&gt;A parte final do plugin é sua utilização na Unity através do C#, e nisso a engine ajuda bastante com a classe &lt;code&gt;AndroidJavaObject&lt;/code&gt;. Com esta class iremos criar nosso objeto com o nome completo da classe (package + nome da classe). Após criar o objeto podemos executar métodos da classe Java utilizando o método &lt;code&gt;Call()&lt;/code&gt;, que também possui parâmetro para retornar um tipo quando o método Java não é &lt;em&gt;void&lt;/em&gt;.&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cs" data-lang="cs"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#if&lt;/span&gt; &lt;span class="n"&gt;UNITY_ANDROID&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NativeTestAndroid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;AndroidJavaObject&lt;/span&gt; &lt;span class="n"&gt;_nativeTestClass&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;NativeTestAndroid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;_nativeTestClass&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;AndroidJavaObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;com.cicanci.unity.NativeTest&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;GetCounter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_nativeTestClass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;getCounter&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;GetMessage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_nativeTestClass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;getMessage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;SetCounter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;_nativeTestClass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;setCounter&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;SetMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;_nativeTestClass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;setMessage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Não existe muito segredo, é realmente bem simples executar um código de uma library Android em Java no C# da Unity. Basta prestar atenção no tipo do retorno do método e no seu nome na hora de definir os métodos no C#. Outra dica é colocar seu código C# dentro de um &lt;code&gt;#if UNITY_ANDROID&lt;/code&gt; para evitar erros de compilação em outras plataformas já que a classe &lt;code&gt;AndroidJavaObject&lt;/code&gt; existe apenas quando a plataforma é Android na Unity.&lt;/p&gt;&#10;&#10;&lt;h4 class="relative group"&gt;Conclusão&#10; &lt;div id="conclusão" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#conclus%c3%a3o" aria-label="Âncora"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h4&gt;&#10;&lt;p&gt;Neste post quis mostrar como é criar um plugin para Android na Unity e, a partir deste template é possível fazer muitas coisas. Na época da Unity 5 era mais comum criar plugins para Android, já que a engine tinha um suporte bem limitado para esta plataforma, isso mudou bastante nas versões posteriores. Hoje muito do que você precisa já tem suporte para Android na Unity, porém pode ser que seja limitado ou que você queira ter controle sobre o código - nestes casos é bom fazer seu próprio plugin.&lt;/p&gt;&#10;&lt;p&gt;Quando preciso desenvolver um plugin para Android na Unity eu geralmente crio um projeto novo no Android Studio e faço tudo por lá, inclusive com um aplicativo de testes. Desta forma é possível utilizar todas as ferramentas de desenvolvimento presentes na IDE antes de ir para a Unity, onde seria mais difícil e nada prático desenvolver uma library Android mais complexa. Eu prefiro exportar o projeto como um arquivo AAR, porém para algo simples e pequeno eu acabo deixando o código dentro da Unity e evito manter um projeto Android apenas para esta finalidade.&lt;/p&gt;&#10;&lt;p&gt;Todo o código deste post e um exemplo de uso está disponível neste &lt;a href="https://github.com/cicanci/unity-mobile-plugin-sample/tree/v1.0.0" target="_blank" rel="noreferrer"&gt;repositório no GitHub&lt;/a&gt;. Pretendo escrever outro post mostrando como fazer o mesmo plugin para iOS e sua utilização na Unity.&lt;/p&gt;</content:encoded><media:content url="https://gamedeveloper.com.br/images/2021/03/unity-android-sample-plugin.webp" medium="image"/></item></channel></rss>