I’m attempting to develop my first game and seem to have stumbled upon a noob moment…
In my game, on Start some game objects called DarkTile are being instantiated to represent darkness. I’ve also manually placed some other game objects called Totem with as properties a bool activeState and a float influenceRange.
In my GameManager script (which is assigned to an empty element in the scene) I’ve put under Update some code to keep check of the active state for all totems, and destroy all dark tiles within the influence range when the totem becomes active (part of the game objective).
However, when I click Play (there are no errors displayed in the console) the dark tiles directly around the totem are not being destroyed when I check Active State = true.
Here’s the code, can anyone tell me what I’m doing wrong? Thanks in advance.
void Update(){
//get references to Totem and Dark Tile gameobjects
Totem[]totems=GetComponents<Totem>();
DarkTile[]darkTiles=GetComponents<DarkTile>();
//check totem state
foreach(Totem totem in totems){
if(totem.activeState==true){
//check distance to active totem
foreach(DarkTile tile in darkTiles){
float dist=Vector3.Distance(totem.transform.position,tile.transform.position);
//destroy tiles directly around totem
if(dist<totem.influenceRange){
Destroy(tile);
}
}
}
}
}
Few things:
First is that when you call Destroy() you pass in a tile, not a gameObject. The “Tile” script will be destroyed, not the GameObject. Fix this by calling “Destroy(tile.gameObject)” instead.
Second, you can’t call “Destroy()” in a foreach loop to destroy an object that is part of the collection you’re grouping through. That means you can’t “foreach” through tiles and destroy a tile inside the loop. See if you can replace it with a “for” loop and that will solve the problem.
Lastly, update is called every frame. you have a “foreach” inside of a “foreach”, which could potentially be a lot of work for an update if either of those loops is big. To illustrate, if you have 10 totems and 100 dark tiles, thats 1000 times you’re checking if a tile is close to a totem per frame! You might want to try to find another way to check if a totem is near tiles, like maybe only check for closeness when a totem is made or moved instead of each frame.
EDIT: A few more problems actually.
GetComponents() only returns components attached to the GameObject this script is attached to, so that won’t work for you unless all of the dark tiles and totems are attached to the same GameObject.
In addition to that, GetComponents() is a very slow operation and will slow your game a TON if you put it inside an update. Consider adding objects to a list when they’re made so you don’t have to remake that list every frame.
Makes sense, with 800 tiles. Here I was hoping that unaltered objects were ignored during update. I’ll write a method that’s triggered right after the activeState is set true.
If I wanted to destroy/disable specific gameobjects within a variable range of a known position, what would be the easiest way to do this? Do I have to evaluate them all, or is it possible to select by position and type?
If you’re only going to loop through once or not very often, looping through the entire long list is fine. You could also try using colliders to represent a totem range and disable any dark tiles that touch that collider.
There are even fancier methods like saving some sort of tile/map system so you can loop through nearby spaces instead of looping through every dark tile. I wouldn’t worry about taking this on yet, it sounds like you’re already doing some pretty advanced things for a first project.
Thank you. Unity is my doorway to actual programming, but I already have some experience in something similar to Grasshopper.
Giving it some thought I will store the tiles in a twodimensional list with the x- and z coordinates as indexes, and knowing the totem position and influence range I can loop only a part of the list and then evaluate the distances. This, I think, would be the most efficient approach.
That would be great, much better than looping through 800 tiles every frame