Использование корутины как bool или другие идеи для скрипта

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

Использование корутины как bool или другие идеи для скрипта

Сообщение prayde.niste 14 авг 2018, 23:41

Есть 2 скрипта:
1. Отвечает за установку "OS" (Банально переносит Text.text на другой Text)
2. Отвечает за всплывающее окно (Как MessageBox) на котором прогресс бар симулирует установку OS

Всё бы ничего, но мне нужно передать в 1 скрипт return true/false. Типа (Установилась/Не установилась) чтобы потом решать,
переносить Text.text на другой Text или нет! В этом то и является загвоздка. Перепробовал очень много способов.
Сначала из 1 скрипта вызывался метод а метод корутину и вроде как работает но реализовать return как с метода так и
с корутины один хрен не получилось. Потом начал натыкивать кучу bool переменных и циклов для получения хоть какого то
результата. Тоже ничего путнего не вышло( потом узнал что корутина это и есть метод. Я давай заменять старый метод одной
корутиной на ввесь скрипт. Вариант хороший. Но ***** вызвать корутину вызвал... но теперь 1 скрипт жалуется что это ну не как
не bool'евая((( Пока что всё пришло к такому виду:

Скрипт номер 1
Синтаксис:
Используется csharp
Class InventoryTweek2

public void Use()
    {
                MessageBox message = MainCamera.GetComponent<MessageBox>();  //Объявил 2 скрипт

                if (message.StartCoroutine(message.Tick()))
                {
                    //Это перенос Text.text на другой Text. Не обращайте на него внимания. В моей проблеме роли не играет.
                    Config cfg = MainCamera.GetComponent<Config>();
                    cfg.SYSTEM.text = choosen.text;
                    choosen.text = "None";
                    thisButton.GetComponent<Text>().text = "None";
                }
        }
 



Скрипт номер 2

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

public class MessageBox : MonoBehaviour
{

    public Image parent;
    public Slider slider;
    public Text status;
    //public bool isNotCancelled;      Те переменные которые я понатыкал. Тоже уже никакой роли не играют
    //public bool isFinished;
    //public bool inProgress;
    public string status_name;

    public void Start()
    {
        parent.gameObject.SetActive(false);  //Это команда скрывает или показывает MessageBox
    }

    public IEnumerator Tick()
    {
        parent.gameObject.SetActive(true);   //Параметры MessageBox`а при старте. В проблеме роли не играет
        status.text = status_name;
        //isNotCancelled = true;
        //isFinished = false;
        //inProgress = true;
        slider.value = 0;


        while (isNotCancelled)  //цикл который заполняет прогресс бар и возвращает true/false
        {
            yield return new WaitForSeconds(0.05f);
            if (slider.value >= 100)
            {
                yield return true;
                break;
            }
            else slider.value++;
        }
        yield return false;
    }

    public void Button()   //Просто кнопка для отмены процесса (не реализовано)
    {
        inProgress = false;
        isNotCancelled = false;
    }


     //СТАРЫЕ НАРАБОТКИ (ПО СУТИ МУСОР МОЖНО НЕ СМОТРЕТЬ!!)
        /*public bool StartProgress(string status_name)
        {
            Debug.Log("StartProgress is started");

            parent.gameObject.SetActive(true);
            status.text = status_name;
            isNotCancelled = true;
            isFinished = false;
            inProgress = true;
            slider.value = 0;

            StartCoroutine(Tick());
            while (isNotCancelled) {
                if (!inProgress)
                {
                    if (isFinished)
                    {
                        Debug.Log("StartProgress is Finished true");

                        parent.gameObject.SetActive(false);
                        return true;
                    }
                    else
                    {
                        Debug.Log("StartProgress is Finished false");

                        parent.gameObject.SetActive(false);
                        return false;
                    }
                }
            }
            return true;
        }

        IEnumerator Tick()
        {
            while (isNotCancelled)
            {
                yield return new WaitForSeconds(0.05f);
                if (slider.value >= 100)
                {
                    inProgress = false;
                    isFinished = true;
                    break;
                }
                else slider.value++;

                Debug.Log(slider.value);
            }
            inProgress = false;
            isFinished = false;
        }

        public void Button()
        {
            inProgress = false;
            isNotCancelled = false;
        }*/

    }

 


Заранее спасибо тем людам которые откликнутся на помощь!
Аватара пользователя
prayde.niste
UNец
 
Сообщения: 18
Зарегистрирован: 14 авг 2018, 23:04

Re: Использование корутины как bool или другие идеи для скрипта

Сообщение waruiyume 14 авг 2018, 23:57

Передайте в корутину ссылку на функцию в которой находится тот код который у вас внутри ифа.
Аватара пользователя
waruiyume
Адепт
 
Сообщения: 6143
Зарегистрирован: 30 окт 2010, 05:03
Откуда: Ростов на Дону

Re: Использование корутины как bool или другие идеи для скрипта

Сообщение Anonymyx 15 авг 2018, 00:11

Или так:
Синтаксис:
Используется csharp
 public IEnumerator Tick(System.Action<bool> result)
    {
        parent.gameObject.SetActive(true);   //Параметры MessageBox`а при старте. В проблеме роли не играет
        status.text = status_name;
        //isNotCancelled = true;
        //isFinished = false;
        //inProgress = true;
        slider.value = 0;


        while (isNotCancelled)  //цикл который заполняет прогресс бар и возвращает true/false
        {
            yield return new WaitForSeconds(0.05f);
            if (slider.value >= 100)
            {
                result(true);
                yield  break;
            }
            else slider.value++;
        }
        result(false)
    }

...
Синтаксис:
Используется csharp
IEnumerator void Use()
    {
bool res;
                MessageBox message = MainCamera.GetComponent<MessageBox>();  //Объявил 2 скрипт
yield return message.StartCoroutine(message.Tick(x=>res = x));
                if (res)
                {
                    //Это перенос Text.text на другой Text. Не обращайте на него внимания. В моей проблеме роли не играет.
                    Config cfg = MainCamera.GetComponent<Config>();
                    cfg.SYSTEM.text = choosen.text;
                    choosen.text = "None";
                    thisButton.GetComponent<Text>().text = "None";
                }
        }


Но передать метод как колбек вариант получше, да.
ЗЫ, писал "от руки".
Аватара пользователя
Anonymyx
Адепт
 
Сообщения: 1973
Зарегистрирован: 05 апр 2015, 15:55

Re: Использование корутины как bool или другие идеи для скрипта

Сообщение Bill Gates 15 авг 2018, 09:37

Все неправильно. Во-первых, UI должен скрывается/показывается с помощью навешанного на него скрипта CanvasGroup, а не через SetActive. Во-вторых, вам нужно перейти на событийно-ориентированный подход. В-третьих, не выставляйте наружу все, что не нужно. Учитесь грамотно использовать модификаторы доступа.

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

/// <summary>
/// Класс, отвечающий за показ окна с прогрессом
/// </summary>
/// <remarks>
/// 1. Вообще, многие компоненты UI могут иметь возможность скрываться и показываться, поэтому
/// логично создать интерфейс с методами Show и Hide и реализовывать его в необходимых классах.
/// Другой вариант — создать вместо интерфейса базовый класс скрываемого UI-компонента и наследовать
/// остальные классы от него.
///
/// 2. Этот компонент должен висеть на верхнем уровне иерархии, поэтому предполагается, что
/// <see cref="parent"/> находится на том же объекте, что и этот скрипт.
///
/// 3. Все константы можно вынести в отдельный класс Constants.
///
/// 4. Используем модификаторы доступа и аттрибут SerializeField, чтобы поля были видны в инспекторе,
/// но не торчали наружу для других классов (вспоминаем ООП: данные объекта должны быть скрыты от остальных объектов).
/// Когда данные торчат наружу, то любой пользователь вашего кода может захотеть изменить эти данные из других классов,
/// что может привести (и приведет) к поломке внутренней логики, завязанной на этих полях.
/// </remarks>
[RequireComponent (typeof (CanvasGroup))]
public class MessageBox : MonoBehaviour
{
    /// <summary>
    /// Период обновления прогресса
    /// </summary>
    private const float TICK_PERIOD = 0.5f;

    /// <summary>
    /// Значение, прибавляемое к прогрессу в каждом обновлении
    /// </summary>
    private const float CHUNK_VALUE = 0.1f;

    /// <summary>
    /// Событие, возникающее при достижении прогресса конечного значения
    /// </summary>
    public event System.Action OnProgressComplete;

    private void DoProgressComplete ()
    {
        if (OnProgressComplete != null)
            OnProgressComplete ();
    }

    /// <summary>
    /// Событие, возникающее при изменении прогресса
    /// </summary>
    public event System.Action<float> OnProgressChanged;

    private void DoProgressChanged (float value)
    {
        if (OnProgressChanged != null)
            OnProgressChanged (value);
    }


    /// <summary>
    /// Событие, возникающее при прерывании прогресса
    /// </summary>
    public event System.Action OnCancel;

    private void DoCancel ()
    {
        if (OnCancel != null)
            OnCancel ();
    }

    [SerializeField]
    private Image parent;

    [SerializeField]
    private Slider slider;

    [SerializeField]
    private Text status;

    [SerializeField]
    private Button cancelButton;

    private CanvasGroup canvasGroup;

    /// <summary>
    /// Установить видимость окна
    /// </summary>
    /// <param name="enabled">Видимость окна</param>
    private void SetVisibility (bool enabled)
    {
        canvasGroup.alpha = enabled ? 1f : 0f;
        canvasGroup.interactable = enabled;
        canvasGroup.blocksRaycasts = enabled;
    }

    private IEnumerator StartProgressCor ()
    {
        slider.value = 0;

        while (true)
        {
            yield return new WaitForSeconds (TICK_PERIOD);

            if (slider.value >= 1f)
            {
                DoProgressComplete ();

                yield break;
            }
            else
            {
                slider.value += CHUNK_VALUE;

                DoProgressChanged (slider.value);
            }
               
        }
    }

    private void CancelButton_Click ()
    {
        StopAllCoroutines ();

        DoCancel ();
    }

    /// <summary>
    /// Запустить прогресс
    /// </summary>
    public void StartProgress ()
    {
        StartCoroutine (StartProgressCor ());
    }

    /// <summary>
    /// Показать окно
    /// </summary>
    public void Show ()
    {
        SetVisibility (true);
    }

    /// <summary>
    /// Спрятать окно
    /// </summary>
    public void Hide ()
    {
        SetVisibility (false);
    }

    void Start ()
    {
        canvasGroup = GetComponent<CanvasGroup> ();

        //подписываемся на кнопку отмены
        cancelButton.onClick.AddListener (CancelButton_Click);

        //скрываем окно
        Hide ();
    }
}

 


Синтаксис:
Используется csharp
public class InventoryTweek2 : MonoBehaviour
{
    [SerializeField]
    private MessageBox messageBox;

    private void MessageBox_OnProgressComplete ()
    {
        //Ура, прогесс завершен и далее что-то делаем

        messageBox.Hide ();
    }

    private void MessageBox_OnCancel ()
    {
        //Ура, мы прервали прогресс и далее что-то делаем

        messageBox.Hide ();
    }

    public void Use ()
    {
        messageBox.Show ();
        messageBox.StartProgress ();
    }

    void Start ()
    {
        /* Подписываеся на события нашего окошка */
        messageBox.OnProgressComplete += MessageBox_OnProgressComplete;
        messageBox.OnCancel += MessageBox_OnCancel;
    }

    void Update ()
    {

    }
}
 
Bill Gates
UNIт
 
Сообщения: 127
Зарегистрирован: 16 июл 2015, 11:27

Re: Использование корутины как bool или другие идеи для скрипта

Сообщение lawsonilka 15 авг 2018, 11:44

Во-первых, UI должен скрывается/показывается с помощью навешанного на него скрипта CanvasGroup, а не через SetActive

это почему, что плохого в отключении объекта?
lawsonilka
UNIверсал
 
Сообщения: 390
Зарегистрирован: 21 окт 2014, 14:48

Re: Использование корутины как bool или другие идеи для скрипта

Сообщение seaman 15 авг 2018, 12:26

"Activating and deactivating UI elements using SetActive(...) forces the UI system to rebuild the UI layout of the GameObject and all its children. This can lead to FPS drops..."
https://davidkoloski.me/blog/
seaman
Адепт
 
Сообщения: 8352
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара

Re: Использование корутины как bool или другие идеи для скрипта

Сообщение lawsonilka 15 авг 2018, 13:37

seaman писал(а):"Activating and deactivating UI elements using SetActive(...) forces the UI system to rebuild the UI layout of the GameObject and all its children. This can lead to FPS drops..."
https://davidkoloski.me/blog/

ясно, статические UI объекты лучше выключать через альфу.
lawsonilka
UNIверсал
 
Сообщения: 390
Зарегистрирован: 21 окт 2014, 14:48

Re: Использование корутины как bool или другие идеи для скрипта

Сообщение prayde.niste 15 авг 2018, 14:05

Спасибо! Буду проверять! Отпишусь когда смогу...
Безработному на пропитание: 5168 7559 0207 5270
Аватара пользователя
prayde.niste
UNец
 
Сообщения: 18
Зарегистрирован: 14 авг 2018, 23:04

Re: Использование корутины как bool или другие идеи для скрипта

Сообщение prayde.niste 19 авг 2018, 15:46

Bill Gates писал(а):Все неправильно. Во-первых, UI должен скрывается/показывается с помощью навешанного на него скрипта CanvasGroup, а не через SetActive. Во-вторых, вам нужно перейти на событийно-ориентированный подход. В-третьих, не выставляйте наружу все, что не нужно. Учитесь грамотно использовать модификаторы доступа.

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

/// <summary>
/// Класс, отвечающий за показ окна с прогрессом
/// </summary>
/// <remarks>
/// 1. Вообще, многие компоненты UI могут иметь возможность скрываться и показываться, поэтому
/// логично создать интерфейс с методами Show и Hide и реализовывать его в необходимых классах.
/// Другой вариант — создать вместо интерфейса базовый класс скрываемого UI-компонента и наследовать
/// остальные классы от него.
///
/// 2. Этот компонент должен висеть на верхнем уровне иерархии, поэтому предполагается, что
/// <see cref="parent"/> находится на том же объекте, что и этот скрипт.
///
/// 3. Все константы можно вынести в отдельный класс Constants.
///
/// 4. Используем модификаторы доступа и аттрибут SerializeField, чтобы поля были видны в инспекторе,
/// но не торчали наружу для других классов (вспоминаем ООП: данные объекта должны быть скрыты от остальных объектов).
/// Когда данные торчат наружу, то любой пользователь вашего кода может захотеть изменить эти данные из других классов,
/// что может привести (и приведет) к поломке внутренней логики, завязанной на этих полях.
/// </remarks>
[RequireComponent (typeof (CanvasGroup))]
public class MessageBox : MonoBehaviour
{
    /// <summary>
    /// Период обновления прогресса
    /// </summary>
    private const float TICK_PERIOD = 0.5f;

    /// <summary>
    /// Значение, прибавляемое к прогрессу в каждом обновлении
    /// </summary>
    private const float CHUNK_VALUE = 0.1f;

    /// <summary>
    /// Событие, возникающее при достижении прогресса конечного значения
    /// </summary>
    public event System.Action OnProgressComplete;

    private void DoProgressComplete ()
    {
        if (OnProgressComplete != null)
            OnProgressComplete ();
    }

    /// <summary>
    /// Событие, возникающее при изменении прогресса
    /// </summary>
    public event System.Action<float> OnProgressChanged;

    private void DoProgressChanged (float value)
    {
        if (OnProgressChanged != null)
            OnProgressChanged (value);
    }


    /// <summary>
    /// Событие, возникающее при прерывании прогресса
    /// </summary>
    public event System.Action OnCancel;

    private void DoCancel ()
    {
        if (OnCancel != null)
            OnCancel ();
    }

    [SerializeField]
    private Image parent;

    [SerializeField]
    private Slider slider;

    [SerializeField]
    private Text status;

    [SerializeField]
    private Button cancelButton;

    private CanvasGroup canvasGroup;

    /// <summary>
    /// Установить видимость окна
    /// </summary>
    /// <param name="enabled">Видимость окна</param>
    private void SetVisibility (bool enabled)
    {
        canvasGroup.alpha = enabled ? 1f : 0f;
        canvasGroup.interactable = enabled;
        canvasGroup.blocksRaycasts = enabled;
    }

    private IEnumerator StartProgressCor ()
    {
        slider.value = 0;

        while (true)
        {
            yield return new WaitForSeconds (TICK_PERIOD);

            if (slider.value >= 1f)
            {
                DoProgressComplete ();

                yield break;
            }
            else
            {
                slider.value += CHUNK_VALUE;

                DoProgressChanged (slider.value);
            }
               
        }
    }

    private void CancelButton_Click ()
    {
        StopAllCoroutines ();

        DoCancel ();
    }

    /// <summary>
    /// Запустить прогресс
    /// </summary>
    public void StartProgress ()
    {
        StartCoroutine (StartProgressCor ());
    }

    /// <summary>
    /// Показать окно
    /// </summary>
    public void Show ()
    {
        SetVisibility (true);
    }

    /// <summary>
    /// Спрятать окно
    /// </summary>
    public void Hide ()
    {
        SetVisibility (false);
    }

    void Start ()
    {
        canvasGroup = GetComponent<CanvasGroup> ();

        //подписываемся на кнопку отмены
        cancelButton.onClick.AddListener (CancelButton_Click);

        //скрываем окно
        Hide ();
    }
}

 


Синтаксис:
Используется csharp
public class InventoryTweek2 : MonoBehaviour
{
    [SerializeField]
    private MessageBox messageBox;

    private void MessageBox_OnProgressComplete ()
    {
        //Ура, прогесс завершен и далее что-то делаем

        messageBox.Hide ();
    }

    private void MessageBox_OnCancel ()
    {
        //Ура, мы прервали прогресс и далее что-то делаем

        messageBox.Hide ();
    }

    public void Use ()
    {
        messageBox.Show ();
        messageBox.StartProgress ();
    }

    void Start ()
    {
        /* Подписываеся на события нашего окошка */
        messageBox.OnProgressComplete += MessageBox_OnProgressComplete;
        messageBox.OnCancel += MessageBox_OnCancel;
    }

    void Update ()
    {

    }
}
 


Спасибо! Очень помогли и очень много узнал. Ещё кое-что. Я узнал про оператор ?. и ?[] (https://docs.microsoft.com/ru-ru/dotnet ... -operators)

Заменяет
var handler = this.PropertyChanged;
if (handler != null)
handler(…);

на это: PropertyChanged?.Invoke(…)
Можно ли использовать в моём случае? И как насчёт вызова MessageBox из другого класса? Не из InventoryTweek2.

Заранее спасибо!
Безработному на пропитание: 5168 7559 0207 5270
Аватара пользователя
prayde.niste
UNец
 
Сообщения: 18
Зарегистрирован: 14 авг 2018, 23:04


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

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

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