Como criar e utilizar um Unity Package

1 de Março de 2020 · 9 min de leitura

Uma forma comum de compartilhar código, modulos e até plugins nativos sempre foi criar um package - exportar um arquivo .unitypackage para ser importado em outro projeto. É uma forma prática de distribuir conteúdo para Unity, porém tem problemas como falta de versionamento, não ter um canal de distribuição centralizado, não avisar de atualizações, permitir que seu conteúdo seja modificado ou removido, entre outros. Isso tudo, quando existia, dependia do desenvolvedor criar uma ferramenta para controlar a integridade e o versionamento do pacote.

Felizmente, a Unity criou uma ferramenta que ajuda em todos os pontos acima e mais alguns, chamada Unity Package Manager. Para utilizá-lo, é necessário criar um projeto seguindo o padrão de package, que pode depois ser importado como um projeto local, um tarball, um repositório git, e até distribuído por npm.

Neste post vou falar mostrar como eu fiz para criar o meu package chamado Cicanci Utils e como configurei para ele ser distribuído em um repositório público no GitHub. O conteúdo do package em si é bem básico no momento - apenas um script para enviar e receber mensagens que criei neste post. Minha ideia é adicionar mais scripts úteis neste package, sempre com algum post explicando seu funcionamento.

Criando um package

Criar um package é bem simples, e começa com um projeto novo na Unity. Depois de criar um projeto novo, você precisa criar os seguintes arquivos, sendo que alguns são obrigatórios como o package.json e a estrutura abaixo para código e teste.

O package.json é um arquivo com toda informação necessária sobre o pacote, e é o que vai ser exibido na janela do Package Manager. Este arquivo contém campos importantes como nome, versão do pacote, versão mínima suportada, e dependencias de outros packages. Abaixo está o exemplo do meu, que contém também dados de autor, palavras-chave e o tipo do pacote.

{
  "name": "com.cicanci.unity-utils",
  "version": "1.0.0",
  "displayName": "Cicanci Utils",
  "description": "Useful pieces of code for Unity projects.",
  "unity": "2017.4",
  "keyworks": [
    "library",
    "utility",
    "utils"
  ],
  "author": {
    "name": "Bruno Cicanci",
    "email": "bruno@cicanci.com",
    "url": "https://cicanci.com"
  },
  "type": "library"
}

Adicionando conteúdo

No meu caso, eu criei um package do tipo library e adicionei o código do pacote em uma pasta chamada Runtime e os testes unitários em uma outra pasta chamada Test\Runtime. Além dos scripts, é necessário criar um arquivo asmdef para cada um desses dois diretórios. Dentro destas pastas pode ter a estrutura de namespace que você quiser.

Para funcionar os testes eu tive que adicionar no asmdef dele uma referência para o pacote da Unity chamado Test Runner (engine e editor). Caso contrário, um erro de compilação acontece por que uma pasta com asmdef não consegue importar e usar namespaces de pacotes que não estão adicionados como referência, além da API padrão da Unity.

Publicando no GitHub

Eu tive alguns problemas para publicar o package no GitHub e fazer ele ser reconhecido pela Unity. O primeiro problema é a estrutura, pois a Unity não reconhece como um package um projeto na raiz do repositório. Para funcionar é necessário adicionar o conteúdo do package direto na raiz do repositório, como mostrado na image abaixo.

O segundo problema que tive, depois que resolvi a estrutura do repositório, foi com os arquivos .meta. Eu acho que não eram necessários, já que no repositório não é mais um projeto Unity. Porém, eu estava enganado e é necessário sim adicionar estes arquivos.

Esta estrutura é bem simples, porém dificulta um pouco na hora de atualizar o pacote e publicar. A melhor maneira que encontrei foi criar um projeto na Unity e clonar o repositório dentro dele. Provavelmente existe alguma maneira melhor de manter um package publicado no GitHub, se você souber por favor comenta a baixo.

Eu publiquei como um repositório público por ser mais simples e poder realmente divulgar o package, porém também é possível configurar um repositório privado para ser usado na sua empresa ou em seus projetos, por exemplo. Não li sobre como fazer, mas li que é possível sim com alguma configuração a mais.

Importando em seu projeto

Por fim, vamos a parte da utilização do package. É bem simples, basta abrir o Package Manager e adicionar um novo package como git URL. Você pode adicionar o link SSH ou HTTPS, ambos funcionam. No meu pacote o link é https://github.com/cicanci/cicanci-utils.git.

Depois de importado, basta usar como normalmente é feito. Importe o namespace na sua classe e está pronto para utilizar todo conteúdo do package. Abaixo está um exemplo de uso, que também está disponível no README do repositório.

using Cicanci.Utils;
using UnityEngine;

public class MessageBehaviour : MonoBehaviour
{
    private void Start()
    {
        MessageManager.Instance.AddListener<MyMessage>(OnMessageReceived);
    }

    private void OnDestroy()
    {
        MessageManager.Instance.RemoveListener<MyMessage>(OnMessageReceived);
    }

    private void OnMessageReceived(MyMessage message)
    {
        Debug.Log(message.Greetings);
    }

    public void SendMessage()
    {
        MyMessage message = new MyMessage { Greetings = "Hello, World!" };
        MessageManager.Instance.SendMessage(message);
    }
}

public class MyMessage
{
    public string Greetings;
}

Conclusão

Apesar de dar um pouco mais de trabalho para configurar do que apenas exportar seu projeto como um .unitypackage, as vantagens de utilizar o novo sistema de package é bem grande. É bem simples para outros desenvolvedores usarem seu código e conteúdo, e mais fácil para manter atualizado e organizado seguindo um padrão pré-definido pela engine.

Meu package Cicanci Utils é bem simples e pequeno, eu criei apenas para estudar como criar e distribuir um pacote, e poder postar o resultado aqui no blog. Minha idea é adicionar mais scripts úteis neste package, junto com posts explicando o que tem de novo nele. É bom ter um lugar organizado e centralizado onde posso jogar meus scripts que uso com frequência ao invés de copiar e colar de outros projetos.

Vou deixar uma referência muito boa que é este vídeo do canal Infallible Code explicando praticamente tudo que escrevi neste post, com exceção da parte de publicá-lo no GitHub. Recomendo assistir os demais vídeos deste canal, o conteúdo é muito bom.

O que você achou do Package Manager? Usaria em seu projeto? Se já usou e tem dicas para compartilhar, deixe um comentário abaixo.