- Home /
Flawed code?
Hello!
First of all, "prefabConst" is a prefab for a construction building sprite, and "prefab" is the actual, finished building.
So my issue is that I have a quite simple code which after a button has been clicked, the event system runs a public function Build (). Everything works flawlessly until the Construction coroutine. Sometimes and for no apparent reason (and I repeat, ONLY sometimes) it doesn't run. I'm not sure if it doesn't run but the construction sprite persists which only tells me it didn't run in the first place.
I failed to find any patterns in why it decides not to work (like clicking too fast).
Does anybody have an idea on what could I do about this?
public void Build () {
x = Random.Range (-4.5f, 4.5f);
y = Random.Range (-2.5f, 2.5f);
z = 0;
pos = new Vector3 (x, y, z);
GameObject storeMe = Instantiate (prefabConst, pos, Quaternion.identity);
StartCoroutine (Construction(storeMe));
}
IEnumerator Construction (GameObject destroyMe) {
yield return new WaitForSeconds (5);
Instantiate (prefab, destroyMe.transform.position, Quaternion.identity);
Destroy (destroyMe);
}
Nothing I can see in the posted code. Have you tried isolating the issue? $$anonymous$$ake a backup of your scene and delete everything unrelated or try to reproduce the issue in a clean scene. One issue might of course be, that you might be starting multiple coroutines after one another. Call StopAllCoroutines() before starting a new one to check for that.
The problem with stopping the couroutines is that I won't be able to build multiple buildings. If I were to spam the Build() function the construction sprites would persist. right?
The only thing which could be a problem here is if you're passing store$$anonymous$$e before it's actually loaded. In other words, if you're passing an argument to your Coroutine somehow after it has been set to something other than null, but not fully loaded. I'd suggest you make Build an IEnumerator, run it as a coroutine, and yield return new WaitForSeconds(1f) after the store$$anonymous$$e initialization. If it's not that, I really don't see where the problem would be.
public void Build () {
StartCoroutine ("PreConstruction");
}
IEnumerator PreConstruction () {
x = Random.Range (-4.5f, 4.5f);
y = Random.Range (-2.5f, 2.5f);
z = 0;
pos = new Vector3 (x, y, z);
GameObject store$$anonymous$$e = Instantiate (prefabConst, pos, Quaternion.identity);
yield return new WaitForSeconds (1);
StartCoroutine (Construction (store$$anonymous$$e));
}
IEnumerator Construction (GameObject destroy$$anonymous$$e) {
yield return new WaitForSeconds (5);
Instantiate (prefab, destroy$$anonymous$$e.transform.position, Quaternion.identity);
Destroy (destroy$$anonymous$$e);
}
Here's what I did. Surprisingly this new script makes the bug quite a lot more frequent.
Is this monobehaviour that the coroutine is running in getting disabled at any point?
It isn't. It's stored inside the button that activates it but neither the GO or the Script itself are getting disabled at any point that I recall.
After some debugging, I found out that whenever a Debug.log is running in the IEnumerator I can not reproduce the error. It's incredible, does this have some kind of explanation? It looks way too random to me but I keep trying to reproduce the error and it just won't happen, but as soon as I remove the Debug.log the error appears again.
Actually, I was able to do it after alt + tabbing. $$anonymous$$ost likely it was probability. I refuse to believe alt tabbing unity does break the code.
A slight optimization idea: It looks as though you're only using the instance of prefabConst as a marker object to tell the Construction Coroutine where to place the new building. If you have already stored the position where the marker object is instantiated at to the variables x, y, and z, why not just change your Construction coroutine's arguments to accept those variables as arguments and instantiate the new building using those arguments as the position? I think it's a little inefficient to create a GameObject for the purpose of storing data.
The GameObject is created to show an "under construction" sprite, which after a while it is destroyed to show the finished building. Although I have been thinking about using the variable "pos" ins$$anonymous$$d of the GameObject, but I came to think it's just the same one way or another. Would it be better to use "pos"?
Oh, no, that's fine then - I didn't know that there was a sprite attached to the marker object to convey that a building is currently under construction at that location. If it has functionality then, you should leave it be. :)
Your answer
