I’m new to scripting and I’ve read many threads but I couldn’t figure out a solution for this.
I have two textures and I want to switch them every 1 second.
It should be like the code below, but for some reason “waiforseconds” doesn’t work for me at all!!
I want these textures switch continuously and not just 1 time. I know that I should have probably put the code in update function but placing it inside update doesn’t work neither.
public Texture2D tex01;
public Texture2D tex02;
void Start()
{
renderer.material.mainTexture = tex01;
yield return new WaitForSeconds(1);
renderer.material.mainTexture = tex02;
}
Then I thought maybe I should use IEnumerator, and I wrote this. But it doesn’t work again.
public Texture2D tex01;
public Texture2D tex02;
void Start()
{
renderer.material.mainTexture = tex01;
wait ();
renderer.material.mainTexture = tex02;
}
IEnumerator wait()
{
yield return new WaitForSeconds(1);
}
I’d appreciate if you could tell me what’s wrong with my code.
You’re calling the coroutine wrong. You can either make Start a coroutine by assigning it as an IEnumerator or you can call your wait coroutine by using StartCoroutine(IEnumerator);
try
IEnumerator Start()
{
//note you should not call renderer.material multiple times as this will create instances.
//Instead call once and store as a variable.
//Also it might be better to use renderer.sharedMaterial.
//This uses the material that is stored in your database instead of creating an instance.
//You'll save on draw calls and memory but this doesn't work if you have multiple objects
//using this material but only want to change one version of it.
//Also note that changing sharedMaterial actually changes the asset and changes will
//persist after you stop the game in the editor.
Material mat = renderer.material;
mat.mainTexture = tex01;
yield return new WaitForSeconds(1.0f);
mat.mainTexture = tex02;
}
I changed the code. But it seems that it doesn’t wait and when I start the game, it quickly jumps to the last texture and stays there,
And how can I store renderer.material as variable? Could you please give me some clues?
public class texturechange : MonoBehaviour {
public Texture2D tex01;
public Texture2D tex02;
public Texture2D tex03;
void Start()
{
for (int i = 0; i < 1000; i++)
{
renderer.sharedMaterial.mainTexture = tex01;
StartCoroutine(SwitchWait());
renderer.sharedMaterial.mainTexture = tex02;
StartCoroutine(SwitchWait());
renderer.sharedMaterial.mainTexture = tex03;
StartCoroutine(SwitchWait());
}
}
IEnumerator SwitchWait()
{
yield return new WaitForSeconds (1);
}
}
So starting a coroutine in Start that just waits isn’t going to do anything to delay the rest of Start.
A coroutine runs alongside the routine that started it so what you’re doing there is just starting a ton of coroutines that are all running in tandem but not actually doing anything. Look at the first bit of code I posted where I turned Start into an IEnumerator. If you really want to run a separate coroutine from Start then you need to place all the code dependent on that waiting within the coroutine try:
void Start()
{
StartCoroutine(SwitchWait());
}
IEnumerator SwitchWait()
{
Material mat = renderer.sharedMaterial;
mat.mainTexture = tex01;
yield return new WaitForSeconds(1.0f);
mat.mainTexture = tex02;
yield return new WaitForSeconds(1.0f);
mat.mainTexture = tex03;
yield return new WaitForSeconds(1.0f);
}
As I said, though, if Start isn’t doing anything else then you could simplify this by using:
IEnumerator Start()
{
Material mat = renderer.sharedMaterial;
mat.mainTexture = tex01;
yield return new WaitForSeconds(1.0f);
mat.mainTexture = tex02;
yield return new WaitForSeconds(1.0f);
mat.mainTexture = tex03;
yield return new WaitForSeconds(1.0f);
}
Unity will detect that Start is an IEnumerator rather than a void and run it as such. (Pretty sure Start is the only base function that can do this, just FYI).