Как в Unity правильно создавать и заставить работать события?
Перерыла весь интернет, пересмотрела кучу видео. Нигде нормально не объясняют, где событие нужно создавать, где подписка происходит, как она происходит и т.д. Где то через Action создают - у меня оно не работает. Подписка с помощью += также не работает, выдает ошибку. Объясните, пожалуйста, по человечески, как их создавать и что где должно быть. Замучалась уже. Очень запутанная тема
Ответы (1 шт):
Все довольно просто, достаточно было внимательно прочитать все в одном месте и попробовать сделать самостоятельно. Событие вызывается только в том классе, где оно было объявлено, извне его вызывать нельзя. Подписываться на события нужно извне. Как пример:
using System;
using UnityEngine;
public class PlayerInput : MonoBehaviour
{
public static event Action ActionButtonPressed;
public static event Action<float> MovementDirectionChanged;
private void Update()
{
if (Input.GetKeyDown(KeyCode.F))
{
ActionButtonPressed?.Invoke(); // Invoke можно вызвать только в классе, в котором ивент объявлен, извне его вызвать нельзя
}
var direction = Input.GetAxis("Horizontal");
MovementDirectionChanged?.Invoke(direction);
}
}
Здесь есть два ивента ActionButtonPressed и MovementDirectionChanged. Первый вызывается, когда нажата кнопка F, второй при каждом изменении горизонтальной оси. Вызывается событие, собственно, через метод Invoke.
Далее есть класс, который будет подписывать свои методы на это событие:
public class Dummy : MonoBehaviour
{
private void OnEnable()
{
PlayerInput.ActionButtonPressed += DoStuff; // += Move нельзя, т.к. сигнатура метода не совпадает
PlayerInput.MovementDirectionChanged += Move;
}
private void OnDisable()
{
PlayerInput.ActionButtonPressed -= DoStuff;
PlayerInput.MovementDirectionChanged -= Move;
}
private void DoStuff()
{
//DoStuff
}
private void Move(float direction) //Сигнатура метода должна совпадать с сигнатурой делегата, т.е, если делегатом будет Action<SomeType>, то у метода должен быть параметр с тем же типом, то бишь Move(SomeType something)
{
//двигаться в направлении direction
}
}
В OnEnable подписываем методы DoStuff и Move на события ActionButtonPressed и MovementDirectionChanged. Подписка осуществляется при помощи оператора +=, отписка, соответственно, при помощи -=. Если сигнатура делегата и сигнатура метода не совпадают, то подписать/отписать этот метод нельзя.
В OnDisable, соответственно, отписываем эти методы.
Теперь, если игрок нажмет на кнопку F, то вызовется ивент ActionButtonPressed и, соответственно, вызовутся все методы, которые на это событие подписаны, т.е. вызовется метод DoStuff. Также, если деактивировать объект, на котором висит скрипт Dummy, то вызовется метод OnDisable и методы отпишутся от ивента, т.е., при вызове ивентов, эти методы вызываться не будут. Нельзя забывать отписываться от событий, т.к., если этого не делать, то либо будут вызываться методы, когда это не надо, либо возникать различные ошибки.
Т.е. если делать +=, то метод добавится в список, а -= удаляет этот метод из списка, при вызове ивента (Invoke) все методы из списка вызываются. Не знаю, можно ли еще проще это объяснить