Engenharia Insper / Laboratório de Realidade Virtual e Jogos Digitais

Componentes

Todo component (criado como um script no Unity) que você consegue inserir em um GameObject herda de MonoBehaviour. Neste documento iremos estudar um pouco mais a fundo no uso de scripts;

Atributos e o Inspector

Como qualquer classe, nossos Scripts, podem conter atributos sejam eles públicos ou não, mas como estamos trabalhando com jogos, muitas vezes estamos cooperando com outros profissionais que não necessariamente sabem programar, pensando nisso a Unity implementou uma funcionalidade de podermos alterar os valores do nosso script via a janela do Inspector, não sendo necessário alterar o código para pequenos ajustes.

Atributos Públicos provavelmente a forma mais simples de deixar um atributo visível pela interface do Inspector;

public class MyComponent : MonoBehaviour

{

    public GameObject legameObject;

    public Camera lecamera;

    public Canvas canvas;

    public int life;

    public float time;

    public int[] powers;

}

Os tipos básicos para os atributos como inteiros, ponto flutuante, textos, são muito usados, mas às vezes descemos que um atributo seja um tipo específico de uma classe que criamos ou que seja do próprio Unity. Perceba que quando criamos os atributos com tipos de outros componentes, ao vermos o campo do atributo no inspector, fica um espaço em branco e o tipo esperado escrito entre parênteses. O Unity consegue agora receber um objeto desse tipo trazendo grande flexibilidade para a ferramenta.

Existem duas formas de inserirmos os valores nesses campos, que vamos assumir aqui que precisam ser um game object. Para isso, você pode selecionar o objeto e levar ele para o campo arrastando da hierarquia ou diretamente da janela de projeto. Outra forma é clicar no pequeno círculo que fica do lado direito nos espaços em branco dos campos e então o Unity irá abrir uma janela para a seleção do que queremos, em função obviamente do que está disponível no seu projeto.

Atributos Privados se queremos que alguns atributos sejam privados, definimos o modificador private no código C# e quando fazemos isso o Unity retira a visibilidade desses atributos do inspector.

public class MyComponent : MonoBehaviour

{

    private GameObject legameObject;

    private Camera lecamera;

    private Canvas canvas;

    private int life;

    public float time;

    public int[] powers;

}

Se ainda quisermos acessar esses atributos pelo inspector temos duas opções, deixar o Inspector no modo Debug, nesse caso ele fica apenas visível e não editável, e podemos também usar a demarcação [SerializeField] logo antes de nosso atributo privado.

public class MyComponent : MonoBehaviour

{

    [SerializeField]

    private GameObject legameObject;

    [SerializeField]

    private Camera lecamera;

    [SerializeField]

    private Canvas canvas;

    [SerializeField]

    private int life;

    public float time;

    public int[] powers;

}

Além dessa demarcação existem outras que podem ajudar muito a criar uma utilização mais fluida do Inspector.

[Header("Um texto")] // Cria um texto separador no inspector

[Tooltip("Uma explicação")]// Cria um texto que aparece quando o mouse fica em cima da propriedade no inspector

[Space(10)]//Cria um espaço de respiro no inspector

[Range(1, 100)]//Cria um slider entre os valores

[RequireComponent(typeof(Dependeciaa))] //Quando adicionar este componente a um gameobject ele irá adicionar o componente dependência

[HideInInspector] //Quando queremos uma propriedade pública não seja mostrada inspector

public class MyComponent : MonoBehaviour

{

    [Header("Public Properties")]

    public float time;

    [Header("Personagem")]

    [Space(50)]

    public string nome;

    [Multiline]

    [Tooltip("Descrição do personagem")]

    public string desc;

    [SerializeField]

    [Range(0, 100)]

    private int life;

}

Acessando componentes via código.

Dentro de um script, as vezes precisam acessar um componente via código e mudar seus parâmetros. O Unity permite que façamos alterações no código da maioria das propriedades dos componentes.

Digamos que precise acessar um rigidbody em nosso script, algo comum de se fazer. Podemos então fazer algo como no código abaixo:

public class MyComponent : MonoBehaviour

{

    private Rigidbody _rb;

    private void Awake()

    {

        _rb = GetComponent<Rigidbody>();

    }

}

Perceba que a forma como usamos o método GetComponent é:

GetComponent<NomeDoComponente>();

Este método irá procurar o componente NomeDoComponente nos componentes do GameObject em que o script foi adicionado e retornar ele, se existir;

Podemos ainda buscar um componente nos "filhos" ou no "pai" do GameObject em que esse script está;

public class MyComponent : MonoBehaviour

{

    private Rigidbody _rb;

    private Rigidbody child_rb;

    private Rigidbody parent_rb;

    private void Awake()

    {

        _rb = GetComponent<Rigidbody>();

        child_rb = GetComponentInChildren<Rigidbody>();

        parent_rb = GetComponentInParent<Rigidbody>();

    }

}

Observe que todos esses métodos estão no singular, nesse caso ele irá retornar o primeiro resultado encontrado que satisfaça o componente requerido, quanto temos mais de um componente, temos a opção de capturar uma lista com todos os componentes em questão;

public class MyComponent : MonoBehaviour

{

    private Rigidbody[] _rbs;

    private Rigidbody[] child_rbs;

    private Rigidbody[] parent_rbs;

    private void Awake()

    {

        _rbs = GetComponents<Rigidbody>();

        child_rbs = GetComponentsInChildren<Rigidbody>();

        parent_rbs = GetComponentsInParent<Rigidbody>();

    }

}

Atenção: As opções GetComponentsInChildren e GetComponentsInParent incluem os componentes presentes no próprio GameObject.

Buscando outros GameObjects na cena

Da mesma forma como os componentes, pode ser que não consigamos referenciar os GameObjects que queremos alterar diretamente pelo inspector, quando estamos instanciando-os por exemplo.

O Unity permite que possamos buscar esses GameObjects de diversas formas, algumas mais performáticas que outras.

Nossas opções são:

GameObject findOneOfType = (GameObject)FindObjectOfType(typeof(Camera)); //Lento!! Retorna o primeiro objeto do tipo requerido

GameObject[] findManyOfType = (GameObject[])FindObjectsOfType(typeof(Camera)); ; //Lento!! Retorna todos os objetos do tipo requerido

GameObject childByName = transform.Find("Nome").gameObject; //Retorna o transform do primeiro filho com o nome procurado;

GameObject goByName = GameObject.Find("Nome"); //Lento!! Retorna o primeiro objeto com o nome procurado;

GameObject oneGoByTagName = GameObject.FindGameObjectWithTag("TagName"); //Retorna o primeiro objeto com a Tag procurada;

GameObject[] manyGoByTagName = GameObject.FindGameObjectsWithTag("TagName"); //Retorna todos objetos com a Tag procurada;

As opções mais recomendadas pela Unity são as por tag e a transform.child()

Para usar as duas últimas, precisamos configurar as Tag no inspector e atribuir as tags em nossos game objects, seja pelo inspector, seja por código.

Para criar uma tag, ache a seleção de tag no inspector, e selecione Add Tag..., será aberta uma janela no próprio inspector, Tags & Layers. Podemos acessar essa aba também em Edit > Project Settings e acessar a aba de mesmo nome.

Clique no +, a unity pedirá para você inserir um nome para a sua tag, clique em save e ela estará criada. Mas ainda não atribuída, selecione o GameObject que você quer aplicar a tag, e selecione-a

Acessando esses game objects podemos então acessar os componentes relativos a ele diretamente

umGameObject.GetComponent<AudioSource>().Play();