Ponto V!

Home Unity Mono Behaviors
Bruno Xavier
Mono BehaviorsImprimir
Escrito por Bruno Xavier

Neste artigo, o autor apresenta uma série de questões e explicações sobre os Mono Behaviors que são usados como componentes no motor Unity. Curioso? Então vamos lá…

O que exatamente são Mono Behaviours?

Scripts contendo funções usados como componente de um objeto.

É genérico ou descende de alguma classe e quais são elas?

Não é genérico, contém funções e parâmetros específicos que proporcionam automação, interação e execução de qualquer dado relacionado ao objeto parental ou referenciado.

Mono Behaviours descendem da classe Behaviour, que por sua vez são componentes ligados ao objeto que podem ser ativados ou desativados durante a execução do programa.

Todo Behaviour e suas subclasses é um Component, mas nem todo Component é um Behaviour, como por exemplo: Transforms.

Qual sua utilidade?

Mono Behaviours se utilizam principalmente das bibliotecas MONO, “parente” do sistema .NET.

A principal utilidade é claramente a capacidade de atribuir a cada objeto padrões comportamentais distintos para cada objeto na memória sem interferência direta na execução do programa em si. Com base em Behaviours, tudo na Unity é um objeto e é importante ser familiarizado com OOP para uma absorção mais rápida das ferramentas e maior velocidade na solução de erros críticos que possam surgir por erros na modulação do programa sendo escrito.

Como utilizar?

Uso de Mono Behaviours é simples. Tudo que é necessário é criar um script com a sintaxe de sua preferência e herdar de MonoBehaviour e o objeto está pronto .

Quais são suas limitações?

Não é permitido o uso de Namespaces em Mono Behaviours.

Não é possível serializar classes na Unity, por tanto, não é possível serializar nenhum Mono Behaviour também.

Derivar de um Mono Behaviour em DLLs ainda é muito limitado até o momento, poucas subclasses são expostas.

É obrigatório que seu Asset tenha o mesmo nome da Classe declarada no Script no caso de utilizar C# ou Boo.

Metodologia

Em grande maioria dos casos, devido a estrutura orientada a objetos predominante na Unity, seus scripts constantemente necessitarão conversar e trocar dados entre si antes de tomar qualquer decisão que não quebre a execução de alguma função envolvida em qualquer que seja o processo em questão. Com isso em mente, é importante ter uma estratégia de implementação bem definida apoiada no funcionamento dos Behaviours como um todo e identificar prematuramente qual será o volume da troca de informações entre seus scripts. Como mencionado no texto anterior, Behaviours tem sua própria estrutura de execução de dados (funções Awake, Start, Update, etc)…

No entanto, pouco foi discutido sobre como proceder quanto a troca de informação entre cada Behaviour; Vejamos a seguir com mais calma como trabalhar esta questão.

Enviando e recebendo mensagens

Seus scripts freqüentemente, literalmente, lhe apresentarão a necessidade de conversarem entre si antes de uma tomada de decisão; o que é feito de diversas formas, desde injeção direta de dados em um objeto até mesmo solicitar a mudança de um parâmetro se o mesmo puder ser alterado. Por vários motivos, logística e encapsulamento principalmente, a maneira mais saudável de trocar essas informações entre seus objetos é enviando e recebendo mensagens. Existem apenas alguns rápidos conceitos que deve estar ciente antes de começar a disparar mensagens indiscriminadamente…

Lembre-se, na Unity tudo é objeto, e cada objeto tem seu lugar na hierarquia, seu nome e endereço. Para conseguir acessar uma variável ou função em qualquer lugar do seu programa, você primeiro precisa encontrar a variável ou função através de sua identificação e endereço. A não ser que seja uma variável "estática" (onde todas as referências levam ao mesmo endereço), você precisará prover manualmente o endereço para ter certeza que é exatamente a variável ou função que pretende acessar pois podem haver inúmeras instâncias dessa variável armazenando valores diferentes em endereços diferentes.

Tomemos como exemplo:

Objeto A contém um script onde ao colidir com Objeto B comunica ao Objeto B que ele sofreu dano.

A função que controla o dano recebido está no Objeto B que por sua vez pode estar em qualquer parte na cena ou até mesmo atrás de uma conexão de rede. Para requisitar a execução da função e causar dano no Objeto B, o script em Objeto A precisa estar certo que a função pertence ao Objeto B em questão e não a algum Objeto C ou D.

Então o endereço da função seria basicamente: World > Objeto B > Component Behaviour > Função ou Variável.

Troca de mensagens entre objetos

A maneira lógica de acessar a função ou variável seria algo como:

localVar = ObjetoB.ScriptClassName.Function(); //ou

localVar = ObjetoB.ScriptClassName.variable;

Mas existe uma pequena questão que impede este livre acesso, todo componente é encapsulado em seu GameObject e um componente (script em Objeto A) não pode acessar diretamente outro componente que não pertença ao mesmo GameObject a menos que você crie um ponteiro permanente para esse objeto através de GetComponent(), o que não é uma boa prática, salvo casos muito específicos.

Sendo assim, tudo que é necessário é dizer ao Objeto A quem é e onde está o Objeto B, criando uma ponte entre os dois objetos e assim a mensagem enviada chegará sem problemas ao seu destino:

public GameObject localVar; // <-- inserir ObjetoB via Inspector;

localVar.SendMessage("MyFunction");

Note que o método SendMessage requer que você identifique somente o GameObject, no caso o Objeto B. Você envia a mensagem para o objeto e ele a reenvia automaticamente para qualquer um de seus componentes Mono Behaviour que contenha a função MyFunction().

Se for o caso de ser necessário enviar uma mensagem entre componentes do mesmo objeto, a solução é muito mais suave; Basta requisitar ao GameObject que envie a mensagem, no caso você não precisa perguntar o endereço da função pois o objeto irá assumir que a mensagem é local e o resultado será o mesmo:

gameObject.SendMessage("MyFunction");

"gameObject" é o ID local do objeto que recebe a mensagem e em seguida a repassa para seus behaviours, inclusive para o próprio Script A que requisitou o envio da mensagem, se houver uma função chamada MyFunction() ela será executada. Simples, não?!

É possível também acessar a função ou variável diretamente através do método GetComponent(); mas desta forma se cria uma ligação permanente entre ambos objetos A e B, podendo causar diversos bugs difíceis de rastrear conforme seu projeto aumenta, então procure utilizar mensagens sempre que possível já que você pode inclusive passar parâmetros em cada mensagem, praticamente eliminando a necessidade de acessar variáveis de outros objetos diretamente.

Para melhor esclarecimento e referências, cheque a documentação, divirta-se!


Comentários (7)
  • Marcos Vinícius Koga e Silva  - Muito útil!
    avatar

    Boa tarde!

    Muito bom o seu artigo! Estou fazendo o meu TCC com a Unity e cara... Isso vai me dar uma boa ajuda com a questão de boas práticas para a troca de mensagens, uma das coisas com que eu estava me batendo (inclusive estou fazendo uso do getComponent(), mas tentarei refatorar as coisas fazendo uso do sendMessage()). Esse esquema de troca de mensagens me lembrou muito o Actionscript, hehehe.

    Muito obrigado! =D

  • Marcos Vinícius Koga e Silva  - Sobre o SendMessage
    avatar

    Opa, tudo bom?

    Então... Procurei refatorar o meu código para aplicar o que tu mostrou em seu artigo, mas me deparei com um problema: O sendMessage acusava erro na minha função que tinha retorno. Pesquisei por exemplos de uso desta função e todos sempre apontavam para alguma função do tipo void. Isso me forçou a voltar a deixar o código como estava... Você sabe me dizer se existe alguma solução para funções que não sejam do tipo void?

  • Bruno Crivelari Sanches
    avatar

    Apenas chutando: talvez passar como parâmetro um objeto e colocar o valor de retorno nele?

    T+

  • Bruno Xavier
    avatar

    Marcos, como o Sanches mencionou, você pode passar parametros em SendMessage.
    Mas você nunca irá retornar um valor através de SendMessage, por que você não pode assinar uma viaravel atraves dela, então sempre o alvo de uma mensagem será uma void, onde pode executar as demais ações necessarias. Abraço.

  • Lucas
    avatar

    ola, poderiam me ajudar?
    criei uma funcao OnCollisionEnter(Collision col) e queria executar ela pela void Update.

    void Update () {
    //se apertar o botao C executa a funcao de colisao
    if(Input.GetKey(KeyCode.C))
    {
    OnCollisionEnter();
    }

    }

    void OnCollisionEnter(Collision col)
    {// se colidir muda a textura
    if(col.gameObject.tag == "Player";)
    {
    planoChest.renderer.material.mainTexture = sequenciaAnimacaoChest[1];
    }
    }
    }
    //error
    error CS1501: No overload for method `OnCollisionEnter' takes `0' arguments

    só que eu nao sei que argumentos ele quer ja tentei de tudo e axo que a soluçao é simples.

    espero que me ajudem, obrigado

  • Luis Eduardo Nery Santos
    avatar

    Se não me engano não é possível chamar a Função OnCollisionEnter() dentro do Update(), porque você quer fazer isso? Essa função serve para detectar uma colisão em um objeto, não é preciso chama-la no Update(), ela será chamada sempre que seu gameObject colidir com outro gameObject.

  • Rafael
    avatar

    Você quer usar uma tecla para realizar uma tarefa. Não precias utilizar Collision. BASTA VOCÊ UTILIZAR
    planoChest.renderer.material.mainTexture = sequenciaAnimacaoChest[1];

    DENTRO DE

    if(Input.GetKey(KeyCode.C))
    {

    }

    '-' Você ta querendo "jogar" uma pedra para colidir com um balde de tinta e assim derrama-lo sobre um chão? Precisa programar melhor seus códigos.

Escrever um comentário
Your Contact Details:
Gravatar enabled
Comentário:
[b] [i] [u] [url] [quote] [code] [img]   
:angry::0:confused::cheer:B):evil::silly::dry::lol::kiss::D:pinch::(:shock:
:X:side::):P:unsure::woohoo::huh::whistle:;):S:!::?::idea::arrow:
Security
Por favor coloque o código anti-spam que você lê na imagem.
LAST_UPDATED2  

Busca

Linguagens

Twitter