- Home /
Reference multiple instances of script
I am trying to access a static variable (bool) from a script that is applied to multiple gameObjects of the same name and type (prefabs). Just using the static variable only returns true for ONE of the gameObjects.
Set up: It's a trigger that places the character "Behind Cover" when a button is pressed. This particular bit of code tells the character and it's attached animation controller to behave a certain way when the variable "safe" from the trigger script is true.
This works perfectly for the first cover object, but not for any others.
How can I find all instances of the CoverTrigger script and look for the "safe" value?
if (Input.GetButton ("Fire2")&& CoverTrigger.safe == true)
{
anim.SetBool("behindCover", true);
canShoot = false;
canMove = false;
canJump = false;
}
I can't see from this why CoverTrigger.safe would only be true for the first gameObject. Perhaps post your CoverTrigger code?
If it's static, doesn't that mean it's either on or off for everything.
I'm guessing you are initializing the static variable in the Start method maybe, so every time you create a new instance of prefab, it resets the static variable to false. You may set it to true and read it one frame right before it gets reset to false by the next prefab instance. If that's not it, seeing your CoverTrigger code will help find the problem.
Answer by supernat · Jan 30, 2014 at 06:12 PM
Your inCover variable is not static. You are setting that per wall, based on whether or not the player is in the trigger zone for that wall. Then you set a static variable in Update() for all of the walls, so the first wall that you are near will show safe while the rest do not. Think about it. The value of safe will be set to true for the wall where you have cover and false for walls where you don't have cover. I think you just need to rethink the logic. I wouldn't recommend doing the safe test in Update.
You probably only want to set safe to true if you have cover from any wall, correct? I think you want to reset "safe" at the top of your frame to false, then only set it to true when you enter a trigger area of a wall OR if you entered a trigger area but haven't left it yet. Don't set safe to false.
In your character controller class or some other single instance management class:
public static bool resetSafetyCheck = true;
void LateUpdate()
{
resetSafetyCheck = true;
}
Then in your wall class:
static bool safe = false;
bool stillInTrigger = false;
void Update()
{
if (CharacterClass.resetSafetyCheck)
{
CharacterClass.resetSafetyCheck = false;
safe = false;
}
if (stillInTrigger)
{
safe = true;
}
}
void OnTriggerEnter2D (Collider2D other)
{
// your other logic here...
safe = true;
stillInTrigger = true;
}
void OnTriggerExit2D (Collider2D other)
{
stillInTrigger = false;
}
Now this is not the most elegant way to approach this. It aligns with your current approach though. Myself, I would probably create a static Dictionary that maps walls to a boolean value for inCover, something like this in my character controller class:
public static Dictionary wallsInCover = new Dictionary...
void Update()
{
bool goodCover = false;
foreach (bool inCover in wallsInCover)
{
if (inCover)
{
goodCover = true;
break;
}
}
// At least one wall has good cover
safe = goodCover;
}
and in the WallClass:
void OnTriggerEnter2D(Collider2D other)
{
CharacterClass.wallsInCover[this] = true;
}
void OnTriggerExit2D(Collider2D other)
{
CharacterClass.wallsInCover[this] = false;
}
Thank you! I want to try the Dictionary method you outlined above, but I can't seem to declare the Dictionary correctly. Is there a different way to do it other than what you typed above? Unity doesn't seem to "get" it.
Add: using System.Collections.Generic; to the top of the script.
Thank you supernat. I fixed it without changing my code too much. I created a public variable in the controller script to change in the OnTriggerEnter/Exit functions of the wall script (ins$$anonymous$$d of Update). So, basically just reversed the logic and it works now.
Answer by blockofrock · Jan 30, 2014 at 04:45 PM
My apologies for not being more thorough. And thank you all for responding. Here are the specifics:
I have two "wall" objects. Each wall object has a trigger childed to it which contains the "CoverTrigger.cs" script. When the player steps in to the trigger, a bool flips to true. If the player presses Fire2 while in the trigger area, she will be "safe." Thus, turning on the collider of the wall. This action also (should) flip a public static bool "safe" to true, which my player controller script reads. This should flip the appropriate control bools and the animator bool to play the animation.
EVERYTHING works great for ONE of the walls. For the other wall, the collider turns on which means the the CoverTrigger.cs script works, but the "safe" bool doesn't seem to flip to true, meaning that the resulting animation and conditions from the controller script do not work. Here is the CoverTrigger script in its entirety:
using UnityEngine;
using System.Collections;
public class CoverTrigger : MonoBehaviour {
public float alphaAmount = 1.0f;
public bool inCover = false;
public static bool safe = false;
void OnTriggerEnter2D (Collider2D other)
{
if (other.gameObject.tag=="Player")
{
inCover = true;
}
//
}
void OnTriggerExit2D (Collider2D other)
{
if (other.gameObject.tag=="Player")
{
inCover = false;
}
}
void Update ()
{
if (inCover == true && Input.GetButton ("Fire2"))
{
transform.root.GetComponent<Collider2D>().enabled = true;
safe = true;
}
else if (inCover==false)
{
transform.root.GetComponent<Collider2D>().enabled = false;
safe = false;
}
else
{
transform.root.GetComponent<Collider2D>().enabled = false;
safe = false;
}
}
}
Here is the player controller script. The part that is not working for any wall but the first one is the if/else statement at the end of Update():
using UnityEngine;
using System.Collections;
public class CoverTrigger : MonoBehaviour {
public float alphaAmount = 1.0f;
public bool inCover = false;
public static bool safe = false;
void OnTriggerEnter2D (Collider2D other)
{
if (other.gameObject.tag=="Player")
{
inCover = true;
}
//
}
void OnTriggerExit2D (Collider2D other)
{
if (other.gameObject.tag=="Player")
{
inCover = false;
}
}
void Update ()
{
if (inCover == true && Input.GetButton ("Fire2"))
{
transform.root.GetComponent<Collider2D>().enabled = true;
safe = true;
}
else if (inCover==false)
{
transform.root.GetComponent<Collider2D>().enabled = false;
safe = false;
}
else
{
transform.root.GetComponent<Collider2D>().enabled = false;
safe = false;
}
}
}
I want to make the "safe" variable ring true across all wall objects so that the animation and movement restrictions will apply to everything you can take cover behind. Thank you again.