Как я могу заставить скрипт C # выполняться в определенном порядке? - PullRequest
0 голосов
/ 19 марта 2019

У меня конфликт скриптов, который проверяет, есть ли сетевое соединение и версия игры (если она актуальна);но он пропускает эти условия и загружает игру напрямую.

Как мне заставить скрипт следовать этому шаблону ?:

  1. Проверьте, есть ли подключение к интернету
  2. Проверьтеверсия игры
  3. Загружайте игру только при наличии подключения к Интернету и текущей версии игры

Вы заметите, что есть некоторые функции загрузки, которые повторяются;Я не уверен, какие из них применить.

CheckNetwork.cs

public Text AlertText;
public GameObject alert;
public string URL = "";
public string CurrentVersion;
string latestVersion;
public GameObject newVersionAvailable;

private void Start()
{
    StartCoroutine(LoadTxtData(URL));
}

void Awake()
{
    if (Application.internetReachability == NetworkReachability.NotReachable)
    {
        alert.SetActive(true);
        AlertText.text = "Sorry, you have to enable your conection to play this game";
        if (Input.GetKeyDown(KeyCode.Escape))
            Application.Quit();
    }
    else
    {
        alert.SetActive(false);
        CheckVersion();
    }
}

public void CheckVersion()
{
    if(CurrentVersion != latestVersion)
    {
        newVersionAvailable.SetActive(true);
    }
    else
    {
        newVersionAvailable.SetActive(false);
    }
}

private IEnumerator LoadTxtData(string url)
{
    UnityWebRequest www = UnityWebRequest.Get(url);
    yield return www.SendWebRequest();
    latestVersion = www.ToString();
    CheckVersion();
}

public void OpenURL(string url)
{
    Application.OpenURL(url);
}

Loading.cs

private Image progressBar;

private void Start()
{
    Invoke("LoadAsyncOperation", 3f);
    StartCoroutine(LoadAsyncOperation());
}

public IEnumerator LoadAsyncOperation()
{
    AsyncOperation gameLevel = SceneManager.LoadSceneAsync(1);
    while (gameLevel.progress < 1)
    {
        progressBar.fillAmount = gameLevel.progress;
        yield return new WaitForEndOfFrame();
    }
}

Loading2.cs

public GameObject loadingScreenObj;
public Slider slider;

AsyncOperation async;

public void StartGame()
{
    SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
}

public void LoadScreen(int LVL)
{
    //StartCoroutine(loadingScreen());
}

IEnumerator LoadingScreen(int lvl)
{
    loadingScreenObj.SetActive(true);
    async = SceneManager.LoadSceneAsync(lvl);
    async.allowSceneActivation = false;

    while (async.isDone == false)
    {
        slider.value = async.progress;
        if (async.progress == 0.9f)
        {
            slider.value = 1f;
            async.allowSceneActivation = true;
        }
        yield return null;
    }
}

SplashScrean.cs

void Start()
{
    Invoke("loadMenuLevel", 3f);
    Screen.sleepTimeout = SleepTimeout.NeverSleep;
}

void loadMenuLevel()
{
    SceneManager.LoadScene("gameplay");
}

void Update()
{
    if (Input.GetKey(KeyCode.Mouse0)) 
    {
        loadMenuLevel();
    }
    if (Input.GetKey(KeyCode.Escape))
    {
        Application.Quit();
    }
}

Ответы [ 2 ]

1 голос
/ 20 марта 2019

Я не могу дать вам полный код для вставки копии (в основном потому, что я еще не до конца понимаю, как все ваши скрипты связаны между собой), но я вижу, что вы уже используете Сопрограммы .

Как я уже упоминал ранее, использовал бы один центральный менеджер для обработки всех этих вещей.

Я приведу здесь только общий псевдокод и надеюсь, что вы найдете свойспособ здесь

public class LoadManager
{
    public CheckNetwork check;
    public Loading loading;
    public Loading2 loading2;
    public SplashScrean splashScreen;

    // suprise: a not well documented fact 
    // you can simply make the Start method an IEnumerator (Coroutine)
    // so you can directly wait for anything you want
    private void IEnumerator Start()
    {
        // Next suprise: You can simply yield other IEnumerators
        // that makes them execute and at the same time waits until they are finished
        // so all methods that you want to wait for from here
        // should be IEnumerators

        // as said this is only an example 
        // you could directly within that single
        // Coroutine do your complete download and check routine together
        yield return check.CheckPermissions();
        if(!check.isReachable)
        {
            yield break;
        }

        // same for chekcing the version
        yield return check.CheckVersion();

        if(!check.isUpToDate)
        {
            // do something for update
            yield break;
        }

        // is up to date so start and wait for loading
        yield return loading.LoadAsyncOperation();

        // and so on
    }
}

И есть также некоторые встроенные способы ожидания, например, WaitUntil , WaitForSeconds и т. д.

1 голос
/ 19 марта 2019

Это происходит потому, что вы вызываете метод Invoke("loadMenuLevel", 3f); в методе Start() в скрипте SplashScrean.cs.

Start() вызывается очень скоро после прикрепления MonoBehaviour к объекту.Якобы, вы прикрепили его к GameObject в сцене.Все они поражаются одновременно.

Вы также можете использовать его как вызываемый левой кнопкой мыши в методе Update() того же сценария:

if (Input.GetKey(KeyCode.Mouse0)) 
{
    loadMenuLevel();
}

Я бы добавил bools ккаждый из сценариев загрузки, которые установлены на true, когда каждая задача завершается.Затем в SplashScrean.cs измените вышеуказанное условие для автоматической загрузки уровня, если все три выполнены.Или сохраните условие нажатия клавиши и добавьте bools.

if (Application.internetReachability != NetworkReachability.NotReachable 
    && loadScriptComplete && isCurrentVersion && Input.GetKey(KeyCode.Mouse0)) 
{
    loadMenuLevel();
}

Теперь, если вам также нужна загрузка MonoBehaviours для ожидания выполнения их логики загрузки, подумайте о добавлении логики Update()для тех, кто проверяет установленный вами флаг в CheckNetwork.cs.

//For example. Instead of this
private void Start()
{
    Invoke("LoadAsyncOperation", 3f);
    StartCoroutine(LoadAsyncOperation());
}

//Do this
private void Update()
{
   //Note that we only need to check if it is a CurrentVersion, as if that is true, then we definitely have internet access.
   if(CheckNetwork.IsCurrentVersion) {
      Invoke("LoadAsyncOperation", 3f);
      StartCoroutine(LoadAsyncOperation());
   }
}

Редактирование / Дополнительные примечания Как я заметил:

CheckNetwork.cs ссылки CheckVersion(); вelse предложение.Это кажется бессмысленным.Для LoadTxtData() невозможно установить логику, на которую CheckVersion() полагается в этот период времени.Это своего рода состояние гонки, если хотите.Кроме того, вы все равно обрабатываете эту регистрацию в LoadTxtData(), поэтому я бы просто сделал это там.

...