- Home /
[Beginner question] 2D Time based spawning of objects like weeds or stones/ore
Hi there,
I'm currently working on a topdown 2D game and have a question about spawning stuff like Weeds or rocks after a certain amount of time.
What I'm trying to achieve:
Similar to games like Stardew Valley and Forager, I am trying to make a spawner that spawns weeds, rocks, or even trees that the player can interact with (chop them or gather them etc).
This would need a timer, and something that checks if the area is empty.
Where I am lost:
So right now I have my tilemap, which is the background. I then want to spawn trees, weeds, and other objects at random which I can cut or collect.
I am just unsure if I need to make a separate grid for this, that checks if the cell is empty, and if it is, it can spawn an item at random. Or, if somehow I should just do this without a grid?
I'm also a little confused as to how I achieve this the best and what the best practice is for this.
Below is a video, with a timestamp. At the timestamp, you see a bunch of ores that randomly spawned. I'm trying to create something similar. As far as I can tell, the spawner checks if the area is empty (on a grid?) and then it spawns say 1 object on a random cell that is empty every 1 minute or so.
Anyone got any idea on how to do this?
I did this but I don't think it's right...
public int numberToSpawn;
public List<GameObject> spawnPool;
public void SpawnObjects()
{
for (int i = 0; i < 10; i++)
{
float spawnY = Random.Range
(Camera.main.ScreenToWorldPoint(new Vector2(0, 0)).y, Camera.main.ScreenToWorldPoint(new Vector2(0, Screen.height)).y);
float spawnX = Random.Range
(Camera.main.ScreenToWorldPoint(new Vector2(0, 0)).x, Camera.main.ScreenToWorldPoint(new Vector2(Screen.width, 0)).x);
Vector2 spawnPosition = new Vector2(spawnX, spawnY);
Instantiate(spawnPool, spawnPosition, Quaternion.identity);
}
}
Answer by Caeser_21 · Jun 05 at 10:34 AM
I'm also creating a 2d open-world farming game that is somewhat similar to forager...
The way I did i handled spawning of objects : I made my world randomly generated tiles that are simple gameobjects. Then I actually instatintiated the objects as children of the tile... So when I need to check whether the tile is full or not I just check the childCount
of the object
BUT, I think you are using a tilemap to make your world.
A possible solution is to this is set up a timer and use raycasts to check whether an object is present in the given position... If you need code for reference on how to do it, I can provide some :)
Reference code :
[SerializeField] private int MaxX, MaxY, MinX, MinY; //Assign all these in the inspector according to the size of the tilemap
[SerializeField] private GameObject[] SpawnObjs; //These are the objects like weeds, stones, etc...
private float Timer;
[SerializeField] private float MaxTime; //This is the time between spawns, change accordingly
private void Update()
{
Timer += Time.deltaTime;
if (Timer >= MaxTime)
{
int XPos = Random.Range(MinX, MaxX + 1);
int YPos = Random.Range(MinY, MaxY + 1);
int InstNum = Random.Range(0, SpawnObjs.Length);
Instantiate(SpawnObjs[InstNum], new Vector3(XPos, YPos, 0f), Quaternion.identity);
Timer = 0;
}
}
This isn't tested but i think it should work :)
Reference code 2 : Change the code to this if you want to be sure that no objects spawn on top of each other
[SerializeField] private int MaxX, MaxY, MinX, MinY; //Assign all these in the inspector according to the size of the tilemap
[SerializeField] private GameObject[] SpawnObjs; //These are the objects like weeds, stones, etc...
private float Timer;
[SerializeField] private float MaxTime; //This is the time between spawns, change accordingly
private void Update()
{
Timer += Time.deltaTime;
if (Timer >= MaxTime)
{
int XPos = Random.Range(MinX, MaxX + 1);
int YPos = Random.Range(MinY, MaxY + 1);
int InstNum = Random.Range(0, SpawnObjs.Length);
RaycastHit2D = hit;
if (Physics2D.Raycast(new Vector3(XPos, YPos, 1f), Vector3.back, out hit))
{
if (hit.tranform.tag != "InstObj")
{
Instantiate(SpawnObjs[InstNum], new Vector3(XPos, YPos, 0f), Quaternion.identity);
}
}
Timer = 0;
}
}
Important : All the Objects like weeds, stones and whatever you are instantiating must have the tag InstObj
Sorry for not posting this code sooner, i got caught up in some other work... Good Luck :)
Hi there, thanks for your comment!
Yes I think I'll stick the method of using a tilemap. In theory my world is static so I can easily design the world, then I'm thinking of adding a grid on it, and spawning the things on the grid.
If you have some reference code that would be greatly appreciated as it would help me understand it a little more.
Thanks again!
I have updated my original answer with some reference code... try it out and see if it works :)