Jump to content

Bem vindo à Unidev
Registre para ter acesso a todos os recursos do site. Uma vez registrado e logado, você poderá criar tópicos, postar em tópicos já existentes, gerenciar seu perfil e muito mais. Se você já tem uma conta, faça login aqui - ou então crie aqui uma conta agora mesmo!
- - - - -
Photo

Unity: como invocar eventos entre componentes de forma simples


Um dos grandes conceitos implementados na orientação à objetos é a delegação. Com ela você pode informar que objetos podem ou não possuir caracteristicas que o objeto em seu estado original oferece.

Em vários trechos do meu código eu possuia um processo relativamente comum que consistia em verificar uma variável, fazer um cálculo e disparar um evento (no meu caso sempre no update).

Ou seja, no final eu tinha um timer interno. Então pensei "estou fazendo algo errado, isso não deve ser feito dessa forma e sim com um componente".

Investi 5 minutos de tempo pensando e bolei uma solução simples mas que usa um conceito bem enraizado de delegação. Construi um objeto que possui um evento, este evento no objeto por sí só consiste em um mera declaração, nada mais que isso.

O efeito está sim, em quem hospeda um componente do tipo que criei, pois lá na classe cliente eu posso disparar outras ações a partir do momento que sei que o evento ocorreu.

Deixando agora a teoria de lado, vamos a pratica:
using UnityEngine;
using System.Collections;

public class Timer : MonoBehaviour 
{
    private float timerInterno;
    private int segundosInterno;
    public int segundos = 0;
    
    public delegate void OnTimerEventHandler();
    public event OnTimerEventHandler OnTimer;

    void Update () 
    {
        if (segundos > 0)
        {
            timerInterno += Time.deltaTime;
            segundosInterno = Mathf.RoundToInt(timerInterno % 60);
            if (segundosInterno > segundos)
            {
                timerInterno = 0f;
                segundosInterno = 0;
                OnTimer();
            }
        }
	}
}

Como você pode ver o código é simples, mas o ponto vital está em declarar a variavel delegada que cria o evento do tipo que preciso (no meu caso não há parâmetros mas você pode atribuir por exemplo um GameObject como parâmetro do evento).
public class Teste : MonoBehaviour 
{
    // Use this for initialization
    void Start () 
    {
       gameObject.GetComponent<Timer>().OnTimer += new Timer.OnTimerEventHandler(OnTimer);
    }

    void OnTimer()
    {
        Debug.Log("ocorreu o evento timer !");
    }
}
Para chegar no resultado acima bastou Adicionar o Componente do tipo que você criar ao seu GameObject, e no código ligar o componente ao seu script.
É simples de implementar um eventHandler na classe filha que só receberá uma notificação de que o evento ocorreu. Com isso você pode experimentar novas maneiras de gerenciamento de eventos entre objetos.
  • Zaraki likes this



1 Comments

mcunha, creio essa abordagem tem alguns probleminhas:

 

Primeiro voce deve verificar se OnTimer tem algum valor, se já foi atribuido a algum delegate.

 

if (OnTimer)

    OnTimer();

 

Segundo, se vc der um Destroy no componente que fez o OnTimer += (...), o framework vai dar erro..

 

Eu fiz um tutorial (ficou um longo e creio que as pessoas não assistem até o final, infelizmente) onde eu implemento uma solução bem completinha para isso. Está aqui. Dá uma olhada, é bem bacana :)