- Home /
Issue calling a variable from another script - C#
Hey guys,
I have a situation in my game in which a button needs to be pressed to open a door.
For the button, the actual button object and the base are parented under an empty gameobject called ButtonParent, to which the following script is attached:
using UnityEngine;
using System.Collections;
public class ButtonScript : MonoBehaviour
{
Animator animator;
public bool buttonDown;
public bool buttonInRange;
void Start()
{
buttonDown = false;
animator = GetComponent<Animator>();
}
void Update()
{
if (Input.GetButtonDown("Jump") && buttonInRange)
{
if (!buttonDown)
{
ButtonControl("Open");
buttonDown = true;
}
else
{
ButtonControl("Close");
buttonDown = false;
}
}
}
void OnTriggerEnter(Collider col)
{
if (col.gameObject.tag == "Player")
{
buttonInRange = true;
}
}
void OnTriggerExit(Collider col)
{
if (col.gameObject.tag == "Player")
{
buttonInRange = false;
}
}
void ButtonControl(string direction)
{
animator.SetTrigger(direction);
}
}
For the door, the two door objects are parented under an empty gameobject called DoorParent, to which the following script is attached:
using UnityEngine;
using System.Collections;
public class Doors : MonoBehaviour
{
public ButtonScript refButtonScript;
Animator animator;
bool doorOpen;
void Start()
{
doorOpen = false;
animator = GetComponent<Animator>();
refButtonScript = FindObjectOfType<ButtonScript>();
}
void Update()
{
if (refButtonScript.buttonDown == true)
{
DoorControl("Open");
doorOpen = true;
Debug.Log("Door should be open");
}
if (refButtonScript.buttonDown == false)
{
DoorControl("Close");
doorOpen = false;
Debug.Log("Door should be closed");
}
}
void DoorControl(string direction)
{
animator.SetTrigger(direction);
}
}
What's supposed to happen is, when the player is within reach of the button, pressing space pushes the button, causing the bool buttonDown to be true, which is then called from the door script to open the doors.
I got it to work, almost.
When the button is pressed, the doors open, but then they close and open again. Likewise, when the button is pressed again, the doors close, and then open and close again.
I can't figure out for the life of me why the doors are opening and closing twice. Can anyone tell what is going wrong?
Thanks.
Answer by allenallenallen · Dec 23, 2015 at 09:42 AM
I think the mistake you made here is in the Door script. In the Door script, you're constantly checking whether the door button has been pushed or not, which is a redundant action. Because if a button is pressed, the door MUST react.
Instead of Door script containing a reference to the Button script, have the Button script contain a reference to the Door script. Doors open or close depending on the Buttons, not the other way around.
For the Button script:
// Add the reference variable for the Doors script.
public Doors refDoors;
void Awake(){
refDoors = FindObjectOfType<Doors>(); // To be honest, I wouldn't use this method to get the Doors script. What if you have more than one Doors scripts in the scene?
}
void Update()
{
if (Input.GetButtonDown("Jump") && buttonInRange)
{
if (!buttonDown)
{
ButtonControl("Open");
buttonDown = true;
refDoors.OpenDoors(); // Calls a void in the Doors script that opens the doors.
}
else
{
ButtonControl("Close");
buttonDown = false;
refDoors.CloseDoors(); // Calls a void in the Doors script that closes the doors.
}
}
}
For the Doors script:
// Delete everything in void Update() but add the following voids.
// Open doors
void OpenDoors(){
DoorControl("Open");
doorOpen = true;
Debug.Log("Door should be open");
}
// Close doors
void CloseDoors(){
DoorControl("Close");
doorOpen = false;
Debug.Log("Door should be closed");
}
And now the Doors script doesn't need to waste time and resources checking every frame to see if the buttons are pushed or not. I believe this is a much more effective way than what you have right now.
Thanks. That solution worked.
I do have a question about that one comment you had:
refDoors = FindObjectOfType(); // To be honest, I wouldn't use this method to get the Doors script. What if you have more than one Doors scripts in the scene?
I understand your concern there. Unfortunately, all of the tutorials I was able to find explaining the other methods on how to call a variable from another script predate the launch of Unity 5, so the code in those tutorials no longer work.
For instance, I was trying to do it this way, with ScriptB calling info from ScriptA:
using UnityEngine;
using System.Collections;
public class scriptA : $$anonymous$$onoBehaviour
{
public scriptB _scriptB;
void Start ()
{
_scriptB.helloScriptB();
}
}
and
using UnityEngine;
using System.Collections;
public class scriptB : $$anonymous$$onoBehaviour
{
public void helloScriptB ()
{
print("hello, I am script b");
}
}
I can't figure out what coding change I need to make to make this work. If you could explain to me how to do it this way in Unity 5, you'd really be doing me a solid.
I guess you dragged the scriptB into the scriptA variable in the editor, right?
That's one way to do it. You'll always have the correct script if you manually drag and choose the script.
Actually, it doesn't allow me to drag the script in. But if it's done properly, it should just grab the script on its own, yes?
Your answer
Follow this Question
Related Questions
How do you return variables from other scripts? 2 Answers
Calling variables from other scripts 2 Answers
Getter function not returning correct value from another script (C# scripting) 1 Answer
Calling a variable from another script overwrites it? 1 Answer
How can I take a variable from another script and then apply it to a newly insantiated prefab? 2 Answers