Страница 1 из 1

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

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

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

СообщениеДобавлено: 18 апр 2019, 21:35
1max1
Там где ты меняешь статус отлавливай это событие.

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

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

public Status status
{
    get
    {
        return _status;
    }

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


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

Так же в MonoBehaviour есть метод OnValidate, который работает только в edit режиме и срабатывает при любом изменении значений в инспекторе текущего объекта. Например в этом методе вы можете проверять предыдущее и настоящее значение enum-а и если они разные, то значит - произошло изменение и вызывайте нужные вам методы.

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

СообщениеДобавлено: 18 апр 2019, 21:52
greatPretender
тааак... опять я что-то не догоняю, т.к. вообще не пользовался ни событиями, ни делегатами ))
В общем, как сделать-то событие или проверку на событие... в общем изменился enum на другое значение. Как это узнать кодом. Мне тяжело воспринимать абстракциями, не могу я в них конструктивно мыслить))

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

СообщениеДобавлено: 18 апр 2019, 22:00
samana
greatPretender писал(а):тааак... опять я что-то не догоняю, т.к. вообще не пользовался ни событиями, ни делегатами ))

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

Дело в том, что события могут быть разные:
- например статическое. Оно будет принадлежать классу юнита и будет вызываться при смене статуса ЛЮБОГО юнита в игре. Такое событие сможет "словить" любой объект в игре, не имея ссылки на конкретный юнит.
- событие юнита. Оно будет принадлежать экземпляру юнита, и чтобы "отловить" это событие, то нужно будет подписаться на него у конкретного юнита.

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

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

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

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

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

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

СообщениеДобавлено: 18 апр 2019, 23:05
samana
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 изменится статус (вне зависимости кто его изменил), то сработает вот этот метод.
        // этот метод имеет ссылку на юнита, который вызвал событие.
    }

}
 


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

На событие может быть сколько угодно подписок.

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

СообщениеДобавлено: 19 апр 2019, 22:20
Cr0c
Простейший класс для оповещения изменения любых 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) {}
}
 

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

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

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

СообщениеДобавлено: 20 апр 2019, 21:21
1max1
Синтаксис:
Используется 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");

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

СообщениеДобавлено: 20 апр 2019, 21:53
Cr0c
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) {} // здесь метод для вызова при событии
}

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

СообщениеДобавлено: 21 апр 2019, 21:11
greatPretender
Потыкался, вроде что-то уловил. Буду тестировать как это применять. Всем спасибо)