Reputation:
I have a script conflict that checks if there is network connection and the version of the game (if it's up to date); but it's skipping those conditions and loading the game directly.
How do I make the script follow this pattern?:
You'll notice there are some loading function who repeat themselves; I'm not sure which ones to apply.
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);
}
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();
}
}
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;
}
}
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();
}
}
Upvotes: 0
Views: 256
Reputation: 90779
I can't give you a complete copy-pastable code here (mainy because I don't fully understand yet how all your scripts are connected between each other) but I see you are already using Coroutines.
I would as mentioned before use one central manager to handle all those things.
I will only give you a general pseudo-code here and hope you find your way frome here
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
}
}
And there are also some builtin ways for waiting like e.g. WaitUntil, WaitForSeconds etc.
Upvotes: 1
Reputation: 985
This is happening because you call the Invoke("loadMenuLevel", 3f);
method in the Start()
method in the SplashScrean.cs
script.
Start()
is invoked very soon after a MonoBehaviour
is attached to an object. Ostensibly, you have it attached to a GameObject
in the scene. All of these are being hit at once.
You also have it as invokable via left mouse click in the same script's Update()
method:
if (Input.GetKey(KeyCode.Mouse0))
{
loadMenuLevel();
}
I would add bools
to each of the loading scripts that are set to true
when each task completes. Then, in SplashScrean.cs
, change the above condition to load the level automatically if all three are complete. Or, keep the key press condition and add the bools
.
if (Application.internetReachability != NetworkReachability.NotReachable
&& loadScriptComplete && isCurrentVersion && Input.GetKey(KeyCode.Mouse0))
{
loadMenuLevel();
}
Now, if you also need the Loading MonoBehaviours
to wait to execute their loading logic too, then consider adding Update()
logic to them that checks the flag you set in 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());
}
}
Edits/Additional Notes As I notice:
CheckNetwork.cs
references CheckVersion();
in the else
clause. That seems pointless. It is impossible for LoadTxtData()
to have set the logic that CheckVersion()
relies on in that time frame. A sort of race condition, if you will. Plus, you handle that check in LoadTxtData()
anyways, so I would just do that there.
Upvotes: 1