Mai 26

Ogro – desenho passo a passo

Algumas pessoas me escrevem querendo saber detalhes sobre o processo 2D para meus trabalhos.

Bom, pare resumir toda a história não fujo da curva e sigo os mesmos passos de grandes desenhistas. Começo sempre pelo esboço usando bolas e linhas retas para esboçar a posição do personagem, sempre cuidando com a perspectiva empregada (que obviamente é a parte mais complexa do trabalho).

Feita a anotação geral de como será a pose do personagem, ai sim começa o trabalho de esboçar e sempre aplicando perspectivas de luz/sombra ao trabalho, para gerar o volume desejado.

Após estas etapas estarem completas, basta passar para a arte final e por fim trabalhar bastante na coloração. Costumo utilizar o Photoshop CS2 (tempos atrás fiz a atualização para a versão mais nova e não gostei, voltei para o bom e velho CS2). Em geral eu desenho em arquivos de 1500 x 1000 ou 1000 x 1500 pixels usando um tablet (por muitos anos fui adepto dos tablets da Genius mas finalmente comprei uma Wacom Bamboo – conselho : é bem melhor, vale a pena investir).

Me questionaram também sobre dinâmica nos meus trabalhos, pois  a maioria realmente passa um ar estático e os personagens não demonstram uma ação sendo executada, em gerais são poses de repouso. Sim, é próprio do meu estilo, em geral concept art costuma seguir este padrão para que não hajam tendências de como o personagem será após modelado/finalizado.

Mai 12

CriganBorgue

Passei alguns dias foras resolvendo vários problemas pessoais e também dedicando tempo para escultura em Biscuit para detalhes de roupa de cosplay dos meus filhos. Modelar  na vida real é bem mais difícil do que parece !

Bom, mas vamos falar da vida digital neste post. Retomei a modelagem de mais um crigan que estava faltando, um Crigan que não vai usar projéteis e sim ataques físicos (a idéia é ele socar o chão e gerar uma onda de choque).

O conceito do personagem passou por algumas adaptações, pois originalmente ele ficou muito parecido com os demais modelos que eu havia feito.

O modelo básico seguiu o básico da estrutura do personagem, para em segundo passo começar a detalhar a silhueta para obter o resultado desejado.

Na sequência melhorei a silhueta do personagem pensando principalmente na posterior retirada de um dos braços, então procurei chegar o máximo possível a simetria desejada de braço e região dos ombros e peito para preparar a área que seria retirada em seguida.

Com a separação em mente, fiz o mapeamento da textura e retirei o braço desejado para então modelar um objeto a parte para o braço.

Daqui para frente o foco foi na pintura da textura para obter os efeitos metálicos desejados e também os relevos para a armadura.

O passo-a-passo foi baseado em criar um modelo padrão, lado-a-lado (mirrored) e depois de mapeado eu arranquei um braço dele para em seguida modelar e mapear a textura separadamente.

O próximo passo é rigar o modelo e colocar ele dentro da Unity para iniciar a programação !

Ahhh,ia me esquecendo !

Aqui está o concept do personagem:

Mar 22

Criganato

Um dos personagens que eu havia imaginado para o jogo era um lançador de bombas.

A mecânica de bombas eu já havia criado no Billy Oposto, claro que não vou reaproveitar código e farei tudo novamente (não só para praticar mas também para ver se há coisas à melhorar).

Minha vontade é fazer uma bomba pula-pula, ou seja ao ter contato com o chão ela vai quicar e ganhar uma força extra. Isso envolve um pouco de física com rigid body, em algumas horas devo resolver o problema e colocar o processo para funcionar.

O cíclo inteiro do processo será:

  1. lançar bomba >
  2. aplicar física >
  3. iniciar laço de animação da textura da bomba + som + animação de lâmpadas >
  4. explodir (coletando info dos objetos atingidos)
  5. aplicar dano e iniciar animação de partículas finais

Parece tudo muito simples, mas pode acreditar, algumas horinhas de trabalho serão investidas para tornar isso realidade. Dado que o processo já foi todo definido, o próximo passo foi modelar a bomba do Criganato

Agora vou começar a trabalhar efetivamente no script para deixar tudo funcionando como deveria, eu já levei para dentro do jogo todas as animações padrão do personagem também, o que garante maior aproveitamento dos testes e do comportamento do personagem:

Fev 10

Tutorial : Não esconder objetos da câmera

Um dos grandes problemas para lidar em um jogo 3D é a câmera.

Tudo bem, ela é sua principal aliada, mas também é a que mais exige cuidados. Dependendo do estilo de jogo que você está proposto à criar, enfrentará sérios problemas relativos à camera e um dos mais básicos é ter seu personagem sendo ocultado por uma parede.

É muito trivial você precisar navegar entre cenários que exigem uma complexidade natural que por fim acaba por não mostrando onde (e como) está seu personagem. Um dos artifícios mais comuns neste tipo de situação é alterar o canal alpha do objeto que está entre seu personagem e a câmera.

Para fazer com que o efeito de transparência funcione corretamente você deve seguir alguns passos:

  • Suas texturas devem ser do tipo Transparent -> Diffuse, somente assim aceitarão alterações no valor de alpha do Color que pertence ao Renderer.
  • Um script para identificar o impacto entre um RayCast originado na câmera e os objetos à serem identificados
  • Preferencialmente use tags para saber o que deve e o que não deve ser trabalhado no script

Aqui está um exemplo prático do que foi feito:

Aqui está uma versão simplificada do script da câmera:

public class mainCamera : MonoBehaviour
{
    private GameObject ultimoEscondido;

    void Update()
    {
        Vector3 fwd = transform.TransformDirection(Vector3.forward);
        RaycastHit hit;

        if (ultimoEscondido != null)
        {
            if (ultimoEscondido.GetComponent<barreira>() != null)
            {
                ultimoEscondido.GetComponent<barreira>().exibir();
            }
            ultimoEscondido = null;
        }

        if (Physics.Raycast(transform.position, fwd, out hit, 3f))
        {
            Debug.Log("Camera bateu em " + hit.transform.gameObject.name + " com tag = " + hit.transform.tag);
            if (hit.transform.tag.ToLower().Equals("barreira"))
            {
                if (hit.transform.gameObject.GetComponent<barreira>() != null)
                {
                    ultimoEscondido = hit.transform.gameObject;
                    hit.transform.gameObject.GetComponent<barreira>().esconder();
                }
                else
                {
                    if (hit.transform.parent.gameObject.GetComponent<barreira>() != null)
                    {
                        ultimoEscondido = hit.transform.parent.gameObject;
                        hit.transform.parent.gameObject.GetComponent<barreira>().esconder();
                    }
                }
            }
        }
}

E aqui está o script do tipo Barreira (o script que interpreta que o gameObject deve ser exibido/ocultado). Vale lembrar que ele está pronto para trabalhar com o Renderer estando nele diretamente (por exemplo quando você adiciona o script à um modelo diretamente, o que não é recomendado, ou quando você cria um prefab).

public class barreira : MonoBehaviour
{
    public bool escondivel = true;

    public void esconder()
    {
        if (escondivel) atualizar(0.4f);
    }

    public void exibir()
    {
        if (escondivel) atualizar(1f);
    }

    private void atualizar(float f)
    {
        Color c;

        if (renderer != null)
        {
            c = renderer.material.color;
            c.a = f;
            renderer.material.color = c;
        }

        foreach (Renderer r in gameObject.GetComponentsInChildren<Renderer>())
        {
            Debug.Log("Achei em " + gameObject.name + " o renderer " + r.name + " que passa a ter alfa " + f);
            c = r.material.color;
            c.a = f;
            r.material.color = c;
        }
    }
}

Fev 03

A importância dos emptys dentro do Blender

Infelizmente não tem jeito, certas coisas você não vai achar em um livro de receitas.

Uma das boas práticas quando falamos de criação de jogos é sempre tentar tornar as coisas o mais flexível possíveis (seja para o artista, seja para o programador).

Ao desenvolver um jogo, você com certeza vai passar por dilemas básicos, como por exemplo “como posicionar melhor seu objeto“. Pode parecer algo simples mas não é, posso garantir !

O simples fato de que um tiro parte do cano de uma pistola parece algo simples mas quando falamos de 3D principalmente, as coisas tendem a ficar mais complicadas ainda.

As minhas primeiras expiriências na Unity me levaram a agir de forma errada, funcionava…mas o resultado é extremamente rígido, não há muita flexibilidade (claro, a menos que você programe tudo na unha).

A imagem acima reforça a importância de usar um empty dentro do Blender, que será interpretado corretamente pela Unity como um Transform (ou seja, fornecerá a posição relativa em 3D). Se seu modelo for animado, o empty pode ser parenteado a um bone e pronto, ele sempre estará atualizado e você não precisa programar nada, basta usar o empty como referência.

 IEnumerator Atirar()
    {
        float velocidade_tiro = 0f;
        float tempo_proximo = 0.3f;

        GameObject tmp = null;
        atirando = true;

        velocidade_tiro = 9f;
        yield return new WaitForSeconds(0.05f);

        gameObject.GetComponentInChildren<Animation>().Play("parado-atirando");
        yield return new WaitForSeconds(0.01f);

        Olhar();
        tmp = (GameObject)Instantiate(bala, empty.position, gameObject.transform.rotation);
        tmp.SetActive(true);
        tmp.GetComponent<bala>().criador = gameObject;
        tmp.GetComponent<bala>().dano = balaDano;
        tmp.AddComponent<Rigidbody>();
        tmp.rigidbody.mass = 0.01f;
        tmp.rigidbody.useGravity = false;
        tmp.rigidbody.velocity = transform.forward * velocidade_tiro;
        yield return new WaitForSeconds(tempo_proximo);

        atirando = false;
        yield return new WaitForSeconds(0.1f);
    }

A função atira acima foi postada em sua integridade, mas para referenciar o que estou querendo demonstrar veja o parãmetro empty.position que foi usado baseado no empty do próprio modelo (ou seja, se ele mudar de lugar, a posição sempre estará atualizada).

Isso pode te poupar um bocado de tempo, pense por exemplo em uma partícula que fica rodando ao redor do seu personagem, pode resolver de várias formas:

  • Animação dentro da Unity
  • Animação via código
  • Animação via empty dentro de sua ferramenta 3D

O que você deve ter em mente é que não há solução certa ou errada, existe sim aquelas que são mais práticas e dividem trabalho (neste caso, se houvesse somente um artista 3D) bastava o programador combinar que ele faz a animação e o programador só anexa o objeto desejado.

Artigos mais antigos «