@Enivoxx

Как отслеживать состояние компонента через систему событий в Unity?

Не могу до конца понять возможности системы событий в Unity и когда именно ее следует применять. Большинство туториалов по системе событий, с которыми удалось ознакомиться, показывают как устроены эвенты с точки зрения синтаксиса, но не дают представления о том, какие конкретно дают возможности события с точки зрения контроля происходящего в коде, особенно интересуют ситуации, когда можно использовать события, как альтернативу Upadate.

К примеру, такая ситуация. Есть Canvas, на нем есть компонент Canvas Group и в нем есть свойство Interactable. Это свойство динамически меняется через другие скрипты, соответственно, нет точного понимания, когда именно произойдет изменение свойства Interactable. Можно ли в данном случае использовать только систему событий и отследить момент, когда именно произойдет изменение свойства Interactable? То есть, можно ли заменить этот код:

_canvasGroup = Canvas.GetComponent<CanvasGroup>();

void Update()
{
   if (_canvasGroup.interactable == true)
       //action
}


на примерно что-то такое:

Event OnCanvasChanged;

void Start()
{
    OnCanvasChanged.AddListener(Cnanging);
}

void Changing()
{
   if(_canvas.interactable == true)
        {
            //action
        }
        if (_canvas.interactable == false)
        {
            //action
        }
}

Или без Update все равно не обойтись?
  • Вопрос задан
  • 94 просмотра
Решения вопроса 1
K0TlK
@K0TlK
Буллю людей.
соответственно, нет точного понимания, когда именно произойдет изменение свойства Interactable

Это твоя проблема. Изменять внутреннее состояние объекта напрямую извне нельзя. Делай обертку, которая будет вызывать ивент, когда канвасгруп становится интеракивным/не интерактивным.

Напишу тот же пример, что и на SO тебе написал.
public class SomeCanvas : MonoBehaviour
{
    public event Action<bool> ActiveStateChanged;
        
    [SerializeField] private CanvasGroup _canvasGroup;

    public void Activate()
    {
        SetActiveState(true);
    }

    public void Deactivate()
    {
        SetActiveState(false);
    }

    private void SetActiveState(bool state)
    {
        if (_canvasGroup.interactable == state) return;
        
        _canvasGroup.interactable = state;
        ActiveStateChanged?.Invoke(state);
    }
}

public class NotSomeCanvas : MonoBehaviour
{
    [SerializeField] private SomeCanvas _someCanvas;

    private void OnEnable()
    {
        _someCanvas.ActiveStateChanged += LogActiveState;
    }

    private void OnDisable()
    {
        _someCanvas.ActiveStateChanged -= LogActiveState;
    }

    private void LogActiveState(bool state)
    {
        print($"Current state - {state}");
    }
}


SomeCanvas - обертка, через него делаешь интерактивным/не интерактивным свой канвасгруп, он вызывает ивент, на ивент подписываешь нужные методы. Можешь разделить на 2 ивента Activated/Deactivated чтобы не делать проверки на false или true, как тебе удобно
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@Enivoxx Автор вопроса
Спасибо! Мысль понял) Просто конкретно в данном примере с canvas.interactable элементы ui выводит сторонний плагин, модифицировать логику, которая делает канвасгруп интерактивным, возможности нет. Есть только возможность обращаться к _canvas.interactable и поверять текущее значение. Получается, в таких случаях, решение - только проверять в Update() ?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы