Как узнать когда измениться enum-значение (без update)?

Форум для самых маленьких, а так же тех, кому недосуг читать справку самостоятельно.

Как узнать когда измениться enum-значение (без update)?

Сообщение greatPretender 18 апр 2019, 20:59

Вечер добрый.
У меня в скрипте на юните есть enum
public enum Status {GoToRoute, FindRoute, FindSiege, ...}
public Status curStatus; // текущее состояние юнита
enum меняется в результате всяких функций и прочего.
Подскажите, как мне сделать, чтобы я узнал, что curStatus сменил значение.
-Через update - я думаю это глупо, тем более я его почти не использую.
-Состояний много, и поэтому впихивать строку в switch в каждый case - тоже бред.
Есть же то ли делегаты, то ли события, то ли ещё что-то встроенное в юнити.
Заранее спасибо. )
greatPretender
Старожил
 
Сообщения: 526
Зарегистрирован: 23 сен 2015, 07:51

Re: Как узнать когда измениться enum-значение (без update)?

Сообщение 1max1 18 апр 2019, 21:35

Там где ты меняешь статус отлавливай это событие.
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: Как узнать когда измениться enum-значение (без update)?

Сообщение samana 18 апр 2019, 21:40

Смотря что именно вам нужно. Если нужно вызывать события уже в игре, то можно сделать через свойства:
Синтаксис:
Используется csharp
private Status _status;

public Status status
{
    get
    {
        return _status;
    }

    set
    {
        _status = value;
        // здесь можете вызывать событие
    }
}


Если же вы хотите что-то менять при смене enum в edit режиме, то можно сделать свой инспектор, который будет отлавливать изменения статуса.

Так же в MonoBehaviour есть метод OnValidate, который работает только в edit режиме и срабатывает при любом изменении значений в инспекторе текущего объекта. Например в этом методе вы можете проверять предыдущее и настоящее значение enum-а и если они разные, то значит - произошло изменение и вызывайте нужные вам методы.
Аватара пользователя
samana
Адепт
 
Сообщения: 4738
Зарегистрирован: 21 фев 2015, 13:00
Откуда: Днепропетровск

Re: Как узнать когда измениться enum-значение (без update)?

Сообщение greatPretender 18 апр 2019, 21:52

тааак... опять я что-то не догоняю, т.к. вообще не пользовался ни событиями, ни делегатами ))
В общем, как сделать-то событие или проверку на событие... в общем изменился enum на другое значение. Как это узнать кодом. Мне тяжело воспринимать абстракциями, не могу я в них конструктивно мыслить))
greatPretender
Старожил
 
Сообщения: 526
Зарегистрирован: 23 сен 2015, 07:51

Re: Как узнать когда измениться enum-значение (без update)?

Сообщение samana 18 апр 2019, 22:00

greatPretender писал(а):тааак... опять я что-то не догоняю, т.к. вообще не пользовался ни событиями, ни делегатами ))

Ух, что же делать... :-?

Дело в том, что события могут быть разные:
- например статическое. Оно будет принадлежать классу юнита и будет вызываться при смене статуса ЛЮБОГО юнита в игре. Такое событие сможет "словить" любой объект в игре, не имея ссылки на конкретный юнит.
- событие юнита. Оно будет принадлежать экземпляру юнита, и чтобы "отловить" это событие, то нужно будет подписаться на него у конкретного юнита.
Аватара пользователя
samana
Адепт
 
Сообщения: 4738
Зарегистрирован: 21 фев 2015, 13:00
Откуда: Днепропетровск

Re: Как узнать когда измениться enum-значение (без update)?

Сообщение greatPretender 18 апр 2019, 22:35

samana писал(а):- событие юнита. Оно будет принадлежать экземпляру юнита, и чтобы "отловить" это событие, то нужно будет подписаться на него у конкретного юнита.

Это то, что надо. А Как подписаться на это событие?
greatPretender
Старожил
 
Сообщения: 526
Зарегистрирован: 23 сен 2015, 07:51

Re: Как узнать когда измениться enum-значение (без update)?

Сообщение 1max1 18 апр 2019, 22:42

Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: Как узнать когда измениться enum-значение (без update)?

Сообщение samana 18 апр 2019, 23:05

greatPretender писал(а):Это то, что надо. А Как подписаться на это событие?

Конечно есть нюансы, но допустим вот это класс Юнита:

Синтаксис:
Используется csharp
using System;
using UnityEngine;

public class Unit : MonoBehaviour
{
    public enum Status { GoToRoute, FindRoute, FindSiege }

    // это событие, которое сработает при смене статуса.
    // В данный момент делегат Action, с одним параметром.
    public event Action<Unit> statusChanged;

    private Status _status;
    public Status status
    {
        get { return _status;}

        set
        {
            _status = value;
            // при смене статуса, юнит запустит событие, если на него кто-то подписался
            if (statusChanged != null) statusChanged(this);
        }
    }

}
 


А это класс какого-то другого объекта, который нашел Юнита и подписался на событие изменения его статуса:
Синтаксис:
Используется csharp
using UnityEngine;

public class SomeOtherClass : MonoBehaviour
{
    void Start()
    {
        Unit unitInScene = GameObject.Find("nameUnit").GetComponent<Unit>();
        unitInScene.statusChanged += Unit_statusChanged;
    }

    private void Unit_statusChanged(Unit obj)
    {
        // когда у unitInScene изменится статус (вне зависимости кто его изменил), то сработает вот этот метод.
        // этот метод имеет ссылку на юнита, который вызвал событие.
    }

}
 


Событие - это просто массив методов одинаковой сигнатуры по-сути. Сигнатура метода - это наличие и типы его параметров и тип возвращаемого значения. Изначально событие - пустое, в нём ничего нет. Но любой объект может "подписаться" на это событие, точнее просто добавить какой-то свой метод (который одинаковый по сигнатуре с событием) в список этого события. Подписка происходит с помощью +=, а отписка -= это важно. Любой объект, который подписывался на событие кого угодно, должен обязательно отписаться от всех событий перед своим уничтожением, иначе ссылки на методы (удалённого объекта) останутся висеть в списке события.

На событие может быть сколько угодно подписок.
Аватара пользователя
samana
Адепт
 
Сообщения: 4738
Зарегистрирован: 21 фев 2015, 13:00
Откуда: Днепропетровск

Re: Как узнать когда измениться enum-значение (без update)?

Сообщение Cr0c 19 апр 2019, 22:20

Простейший класс для оповещения изменения любых value type переменных
Синтаксис:
Используется csharp
public class Publisher<T> {
 public Action<T> OnChange = ()=>{};
 private T value;
 public Publisher(T value){
  this.value = value;
 }
 public T Value {
  get { return value; }
  set { if (value != this.value) {
   this.value = value;
   OnChange.Invoke(value);
   }
 }
}
}
 

Синтаксис:
Используется csharp
public Publisher<MyEnum> myEnum = new Publisher<MyEnum>(MyEnum.Value1);
/////
myEnum.OnChange += Class3.CatchChange;
myEnum.Value = MyEnum.Value2; // при этом вызовется подписчик(и)
/////
public class Class2 {
 public void CatchChange(MyEnum value) {}
}
 
Аватара пользователя
Cr0c
Адепт
 
Сообщения: 3035
Зарегистрирован: 19 июн 2015, 13:50
Skype: cr0c81

Re: Как узнать когда измениться enum-значение (без update)?

Сообщение greatPretender 20 апр 2019, 20:39

Ох, спасибо конечно всем, но эти абстракции ... я не могу понять применительно. Если кто-н привёл прям пример с переменной , то я бы уловил суть, иначе это всё для меня так и останется лежать "за стеклом" ))
greatPretender
Старожил
 
Сообщения: 526
Зарегистрирован: 23 сен 2015, 07:51

Re: Как узнать когда измениться enum-значение (без update)?

Сообщение 1max1 20 апр 2019, 21:21

Синтаксис:
Используется csharp
using UnityEngine;

class Entity : MonoBehaviour
{
    float health = 100.0f;

    void Start()
    {
        Messenger<float>.AddListener("Explosion", Damage);
    }

    void Damage(float value)
    {
        health -= value;
    }
}


Теперь если вызвать событие из любого другого класса, оно отразится на всех ентитях и нанесет урон всем, кто на него подписан, так называемое, глобальное событие.

Синтаксис:
Используется csharp
Messenger<float>.Broadcast("Explosion");
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: Как узнать когда измениться enum-значение (без update)?

Сообщение Cr0c 20 апр 2019, 21:53

greatPretender писал(а):Ох, спасибо конечно всем, но эти абстракции ... я не могу понять применительно. Если кто-н привёл прям пример с переменной , то я бы уловил суть, иначе это всё для меня так и останется лежать "за стеклом" ))

По два раза писать?
Синтаксис:
Используется csharp
public Publisher<MyEnum> myEnum = new Publisher<MyEnum>(MyEnum.Value1); // задание переменной
/////
myEnum.OnChange += Class2.CatchChange; // подписываемся на изменение
myEnum.Value = MyEnum.Value2; // при изменении вызовется подписчик(и)
/////
public class Class2 {
 public void CatchChange(MyEnum value) {} // здесь метод для вызова при событии
}
Аватара пользователя
Cr0c
Адепт
 
Сообщения: 3035
Зарегистрирован: 19 июн 2015, 13:50
Skype: cr0c81

Re: Как узнать когда измениться enum-значение (без update)?

Сообщение greatPretender 21 апр 2019, 21:11

Потыкался, вроде что-то уловил. Буду тестировать как это применять. Всем спасибо)
greatPretender
Старожил
 
Сообщения: 526
Зарегистрирован: 23 сен 2015, 07:51


Вернуться в Почемучка

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 24