When I run the code below, I get the “starting courotine” Debug.Log but I don’t get the other Debug.Logs
using System.Collections;
using UnityEngine;
public class TileSpawn : MonoBehaviour
{
private Vector3 pos;
public int tilesToSpawn;
private bool isFirstTileSpawned;
private bool isStartingLoop;
private int curSquareDimensions;
private IEnumerator courotine;
[SerializeField] private GameObject tile;
private void Start()
{
pos = new Vector2(0, 0);
isFirstTileSpawned = false;
courotine = SpawnTiles(3);
}
void Update()
{
if (curSquareDimensions*curSquareDimensions >= tilesToSpawn)
{
Debug.Log("starting courotine");
StopCoroutine("SpawnTiles");
}
else
{
Debug.Log("starting courotine");
StartCoroutine(courotine);
}
}
private IEnumerator SpawnTiles(int squareDimensions)
{
Debug.Log("courotine is currently running");
tilesToSpawn = squareDimensions * squareDimensions;
if (!isFirstTileSpawned)
{
Instantiate(tile, pos, Quaternion.identity);
Debug.Log("first tile spawned");
isFirstTileSpawned = true;
curSquareDimensions = 1;
}
isStartingLoop = true;
if (curSquareDimensions < squareDimensions)
{
if (isStartingLoop)
{
pos.y += 1;
Instantiate(tile, pos, Quaternion.identity);
curSquareDimensions += 2;
isStartingLoop = false;
}
//this is for making the starting top part, going right
for (int i = 0; i < (curSquareDimensions-1)/2; i++)
{
pos.x += 1;
Instantiate(tile, pos, Quaternion.identity);
yield return null;
}
//this is for making the right side
for (int i = 0; i < (curSquareDimensions-1); i++)
{
pos.y -= 1;
Instantiate(tile, pos, Quaternion.identity);
yield return null;
}
//this is for making the bottom side
for (int i = 0; i < (curSquareDimensions-1); i++)
{
pos.x -= 1;
Instantiate(tile, pos, Quaternion.identity);
yield return null;
}
//this is for making the left side
for (int i = 0; i < (curSquareDimensions-1); i++)
{
pos.y += 1;
Instantiate(tile, pos, Quaternion.identity);
yield return null;
}
//this is for making the top left side
for (int i = 0; i < (curSquareDimensions-1)/2; i++)
{
pos.x += 1;
Instantiate(tile, pos, Quaternion.identity);
yield return null;
}
pos.x += 1;
isStartingLoop = true;
}
}
}
You need to use courotine = StartCoroutine(SpawnTiles(3)); - it’s not a coroutine unless you tell Unity that it’s a coroutine. (And spelling “coroutine” correctly will help you find and understand code better later, too.)
When I replaced courotine = SpawnTiles(3); with the code you provided, it gave me an error saying "Cannot implicitly convert type ‘UnityEngine.Coroutine’ to ‘System.Collections.IEnumerator’ "
IEnumerator is the return value type for a coroutine. But it is not a coroutine.
In a nutshell, these are the bits that make up code using coroutines. It’s not meant for you to cut and paste into your code, just for learning from it. Kurt above already gave you plenty of documentation.
private Coroutine coruotine;
// ...
coroutine = StartCoroutine(MyCoroutine());
// ...
StopCoroutine(coroutine);
// ...
IEnumerator MyCoroutine()
{
// do stuff
yield return null;
// do more stuff
}
The coroutine only runs once despite “starting coroutine” being run multiple times, why is this? (Visual Studio 2019 told me to use a discard _ to stop the error when I just do coroutine; on line 21, same result occurs when I do StartCoroutine(SpawnTiles(3));)
A couroutine only runs through its body once. The returned value is no longer useful once the coroutine gets to the bottom of its code, it basically stops itself when it’s done. If you want to start the couroutine again, you can: just call StartCoroutine again. PLEASE read the documentation that’s been given to you above.
For my case, I want a square made of evenly sized tiles and is odd in lengths so that it has a proper center, what should I use instead of a coroutine?
I refactored your code (with the assistance of GPT-4) to remove the coroutine. I did a rough count of the number of lines that were just boilerplate supporting the coroutine while adding nothing of value to the script and came out to at least 25 lines of code.
Refactored Script
using System.Collections;
using UnityEngine;
public class TileSpawn : MonoBehaviour
{
private Vector3 pos;
public int tilesToSpawn;
private bool isFirstTileSpawned;
private int curSquareDimensions;
[SerializeField] private GameObject tile;
private void Start()
{
pos = new Vector2(0, 0);
isFirstTileSpawned = false;
SpawnTiles(3);
}
private void SpawnTiles(int squareDimensions)
{
tilesToSpawn = squareDimensions * squareDimensions;
if (!isFirstTileSpawned)
{
Instantiate(tile, pos, Quaternion.identity);
isFirstTileSpawned = true;
curSquareDimensions = 1;
}
while (curSquareDimensions < squareDimensions)
{
pos.y += 1;
Instantiate(tile, pos, Quaternion.identity);
curSquareDimensions += 2;
SpawnTileLayer();
}
}
private void SpawnTileLayer()
{
// Starting top part, going right
for (int i = 0; i < (curSquareDimensions - 1) / 2; i++)
{
pos.x += 1;
Instantiate(tile, pos, Quaternion.identity);
}
// Right side
for (int i = 0; i < (curSquareDimensions - 1); i++)
{
pos.y -= 1;
Instantiate(tile, pos, Quaternion.identity);
}
// Bottom side
for (int i = 0; i < (curSquareDimensions - 1); i++)
{
pos.x -= 1;
Instantiate(tile, pos, Quaternion.identity);
}
// Left side
for (int i = 0; i < (curSquareDimensions - 1); i++)
{
pos.y += 1;
Instantiate(tile, pos, Quaternion.identity);
}
// Top left side
for (int i = 0; i < (curSquareDimensions - 1) / 2; i++)
{
pos.x += 1;
Instantiate(tile, pos, Quaternion.identity);
}
pos.x += 1;
}
}