- Home /
Activating only one of many prefabs with the same tag
My game will be using signs to use tell the player different objectives they will have to accomplish it. These signs will hold hidden messages which only appear when the player is facing directly at them. In order to accomplish this, the player character will project a ray onto the sign's collider. When it does hit the sign, the message appears. I have that part of the sign's functionality set up; my trouble comes with making sure the sign the player is looking at is the only sign that shows its hidden message.
If my ray hits one of the colliders on the sign, all of the signs activate, not just the one the ray hits. I'm not quite sure what to do at this point. I've looked all over for help with this issue, but none of them help with keeping one out of a number of prefabs active. Here is the class that activates the signs when the player looks at a sign:
public class SignContentFinder : MonoBehaviour {
GameObject[] interactSigns;
void Awake() {
interactSigns = GameObject.FindGameObjectsWithTag("SignContent");
}
// Update is called once per frame
void Update()
{
Ray ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2, 0));
RaycastHit hit;
foreach (GameObject sign in interactSigns)
{
if (Physics.Raycast(ray, out hit, 5f))
{
sign.renderer.material.mainTexture = sign.GetComponent<SignContentController>().secretTex;
}
else
sign.renderer.material.mainTexture = sign.GetComponent<SignContentController>().mainTex;
}
}
}
Any help would be appreciated. I would like to actually get some feedback this time, as opposed to the 5-6 recent questions I've posted with no feedback.
Answer by PAEvenson · Jun 02, 2013 at 03:05 AM
It is because of your forloop. You should be checking the hit variable to see if that is actually the sign youre hitting. I would do something like this(not tested >_<):
void Update()
{
foreach (GameObject sign in interactSigns)
{
//set all our signs to not show our secret text
sign.renderer.material.mainTexture = sign.GetComponent<SignContentController>().mainTex;
}
Ray ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2, 0));
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 5f))
{
SignContentController controller = hit.collider.gameObject.GetComponent<SignContentController>();
if(controller != null)//if we are null it isnt a sign >_<
{
controller.gameObject.renderer.material.mainTexture = controller.secretTex;
}
}
}
The main idea is that ray casts don't need a loop since they have a secret loop in them -- "shooting" the ray just once checks every sign (but stops when it hits one.)
Then the other is the raycast tells you what if hit, using the output HIT variable. You don't have to shoot it "at" anything specific, and it will still say what it hits.
I was able to incorporate the code into my script, and it worked. I still needed to add my check to turn all of the signs back into the main texture, as I want the message to disappear when the player isn't looking at it.
Either way, thanks PAEvenson for the help.
As for Owen: I'm still not sure I follow. Are you saying if I removed my foreach loop, would the code work the same?
Your original "what's in front of me" raycast was in a loop. No need for that (notice how PAvanson's code just raycasts once.)
I just noticed that. Thanks for pointing that out.
So the foreach loop now just sets all of the signs not hit by the ray to its initial message.
$$anonymous$$eanwhile, the Physics.Raycast check has a reference solely for the collider that was hit by the ray. This reference will then change that sign's collider to the secret message only when the collider is hit by the ray.
Have I got that right?
I think, yes. The raycast "I hit this" is the var hit
. Then you can see, next line, where the code uses hit
to look up the sign (or next line, where it says "hey, HIT wasn't a sign!")
The loop just happens to be how you do sign record-keeping. Nothing to do with the raycast.
Your answer
![](https://koobas.hobune.stream/wayback/20220613103348im_/https://answers.unity.com/themes/thub/images/avi.jpg)