Ok, guys, Im making a simple board game with a tile system.
I want to make some of these tiles give the user some bonus points to the score, when passed over (only the first time the user passes over it).
I have no problem, making a single tile of this type, and it works perfectly for ONLY ONE tile. But I am really confused and need to know how to make this work for more than one tile of the same type, in the same script.
{
//tile is a 'quad' which is place ontop of the actual tile (basically just a texture)
tile = tilechecker.collider.gameObject;
if(tile.tag=="bonus tile" && !collectedbonus)
{
//tile2 is the actual tile on which the quad named 'tile' lies
tile2 = tile.transform.parent;
print ("got bonus");
points++;
collectedbonus = true;
}
}
I have a general idea that I have to use some sort of arrays, but really don’t know how to implement it.
The way my script works is, the player has a ray coming out of the bottom of it, checking for the tile every update frame. On hitting the desired tile, the bonus gets added.
The problem is that you’re using a boolean flag, collectedbonus for all tiles. The issue occurs because after you collect one bonus, that flag is set, and so when you come to the next one, the code finds you have already collected the bonus, and so it doesn’t give you any more. You can solve this in several ways.
The simplest way is to add a script to the bonus tile, which contains the boolean flag. Then, in your collision script, you can use GetComponent to access this script and read and set the flag. That way, each tile has their own boolean, and it will work correctly.
Another solution, though messier and less efficient, but will work if you are for some reason unable to add scripts to individual tiles, is to forgo booleans entirely, and create a Set of bonus tile objects. Initially, this will be empty. Whenever you cross over a bonus tile, you can check if it is already in the set, and if it is, then it has already been touched. If it isn’t in the set, you can add it in, and give the player the bonus points.
There are other solutions, but those are the two most obvious ones.
If you want to do everything with one script you can simply change the tag of the object the first time it’s hit. Once you change the tag on the tile, that specific tile will never trigger the bonus again.
if(tile.tag=="bonus tile")
{
tile.tag = "UsedBonusTile";
//tile2 is the actual tile on which the quad named 'tile' lies
tile2 = tile.transform.parent;
print ("got bonus");
points++;
collectedbonus = true;
}
In the example above the tile once triggered will change the tag from whatever it currently is to “UsedBonusTile”. Then if another collider interacts with that tile, your script will just ignore it since it doesn’t have the tag it’s looking for. I also modified the If statement, because the boolean is no longer necessary.
OK I’ll try to give an example of how I would handle this:
//PlayerScript
//create variable to hold the current tile object
public gameObject rayHitObject;
//do all stuff to determine if you hit bonus tile
//Added range to your raycast make sure it goes far enough
//just to be safe, did not see that in your code yet
if(Physics.Raycast(transform.position,Vector3.down,out tilechecker, 200))
{
//you should only do this once per move
//do this once per tile
//it looked like you might do this every FixedUpdate()
//in another thread of yours I think you should fix that
//obtain your current tile Object from your raycast
rayHitObject = tilechecker.collider.gameObject;
//I don't know why you have a Script for just the bonus tiles.
//You could and probably should have one script that can handle ALL the tiles
//if your tile script is named bonus after you get the rayHitObject from the single Raycast
//you can go:
//prepare to handle this one object one time (not every Fixed Update)
//Grab the tile Script Component to change Bool:
bonus otherObjectsScriptBonus = rayHitObject.GetComponent<bonus>;
//set bool
if (otherObjectsScriptBonus.check == false)
{
otherObjectsScriptBonus.check = true;
//call a function to update your points only once
}
else if (otherObjectsScriptBonus.check == true)
{
//wait for the next time they move to cast another ray...
return;
}
}
Hopefully that helps it seems like you are very close but the problem of correctly setting a bool on an object only one time is extremely simple if you do it like this example. You just need to make sure you only do it once per move and control all your logic. In another one of your threads it looks like you were trying to call all kinds of stuff every FixedUpdate.
I would recommend only doing the minimum work required for both performance and so you can solve this easier. So do one rayCast per move, handle the logic, and then once the logic is complete allow the player to move.