- Home /
If statement seeming to give false positive
Hello, I have a series of tiles in my game (First person), and I want to spawn a GameObject (Called "Indicator") on the tile the player is looking at to show which tile they are looking at. And if there is already a Indicator GameObject in the scene that is not the child of the tile the player is looking at to destroy it.
The problem comes when the player looks at a tile. It will spawn the Indicator GameObject but then destroy it and spawn it again and so on and so forth extremely quickly. Here is the offending code.
if (Physics.Raycast (rayOrigin, fpsCam.transform.forward, out hit, 5))
{
if (hit.collider.GetComponent<Tile>())
{
//Spawns an indicator gameobject only if there are no other others in the scene.
if (!GameObject.FindGameObjectWithTag("Indicator"))
{
Instantiate(indicator, hit.transform);
Debug.Log("Spawned Indicator");
}
// Just a debugging check. But in all testing is not called for some reason. Though it should be.
else if (GameObject.FindGameObjectWithTag("Indicator").transform.parent == hit.transform.gameObject)
{
Debug.Log("Gameobject has indicator child");
}
// This should destroy indicator if one is in the scene that is not a child of the tile the player is currently looking at.
else if (GameObject.FindGameObjectWithTag("Indicator").transform.parent != hit.transform.gameObject)
{
Destroy(GameObject.FindGameObjectWithTag("Indicator"));
}
}
}
I have checked and double checked, with lots of different Debug.Logs and the debugger in visual studio. And the last else if statement shows that the indicator is the child of the same gameobject that the player is looking at. I am at my wits end, and have no idea why it is not calling the second to last else if statement or why it keeps calling the last one. Any help with be greatly appreciated.
Answer by yummy81 · Feb 03, 2018 at 12:27 PM
I've recreated your logic with my own version. At first I got rid of all those "FindGameObjectWithTag" methods. They are very expensive especially when they are invoked inside Update. I also removed "Instantiate". Next, I created gameobject with the name "Indicator" in the Inspector, set its active state to false, and assigned it to the "[SerializeField] private Transform indicator; ". This way I can activate or disactivate it whenever I want it to, without any overhead related to constant instantiating and destroying. I also created the new layer, to which I assigned all the Tiles. I assigned this layer to the "[SerializeField] private LayerMask layerMask" and used it as the fifth parameter in the Raycast method. And that's essentially it.
[SerializeField] private Transform indicator;
[SerializeField] private LayerMask layerMask;
private RaycastHit hit;
private void Update()
{
if (Physics.Raycast(rayOrigin, fpsCam.transform.forward, out hit, 5f, this.layerMask))
{
if (hit.collider.GetComponent<Tile>())
{
this.indicator.position = hit.transform.position;
this.indicator.gameObject.SetActive(true);
}
}
else
{
this.indicator.gameObject.SetActive(false);
}
}
Right now I have the tiles as box colliders. And I still seem to be having some problems. I was wondering, what does using the layermask as the fifth parameter do? I mean how does it benefit it?
When I was analysing your code I assigned
this.indicator.position = hit.point;
ins$$anonymous$$d of
this.indicator.position = hit.transform.position;
This triggered some ugly jittering. So layers helped to solve this problem. But yes, layers are not necessary when it comes to your version with hit.transform.position. You can omit them.
Raycast works with box colliders so everything should be as expected...
Okay, I got a set of box colliders. With the required script on them. And all on the new layer. I got a copy of the code you posted, with the addition of the needed code for the raycast. And put the script on my player gameobject. And set the layermask to be the same as the one the box colliders are on. And set the indicator transform to be the indicator gameobject that is in the scene. But when I look around at the box collider tiles it does not do anything with the indicator.... :/
Answer by natepool · Feb 03, 2018 at 05:34 PM
@MechaWolf99 @piotrek_81 is correct, that is an expensive approach so a more efficient method should be explored. In the meantime, if you want to get this code functional I believe you can with this change
Line 7....
GameObject go = Instantiate(indicator, hit.transform);
go.transform.parent = hit.transform;
This will explicitly set the parent of Indicator to the Tile that is “hit”. This change will ensure your if else logic fires as expected.
Your answer
Follow this Question
Related Questions
How to check if the difference between any pair of numbers in an array is less than some value? 0 Answers
Endless runner background looping delayed. 0 Answers
Disabling function of a key 1 Answer
How to use multiple If statements? Or can I use relational operators in switch statements? 1 Answer
I can't figure out why this if statement isn't responding 1 Answer