- Home /
Issues with button pushing logic
Unity,
Having an issue where only one button pushes in when I click it (this is expected) but all of my buttons push out when I click it again. Any thoughts as to why this may happen? I tried to comment it out as best I could to explain what's going on.
Thanks!
Addyarb
using UnityEngine;
using System.Collections;
public class ButtonGameButton : MonoBehaviour {
public ButtonGame bGame;
public string name;
private float speed = 0.5f;
public bool pressButtonIn = false;
public bool pressButtonOut = false;
public Transform myTransform;
// Use this for initialization
void Start () {
bGame = GetComponentInParent<ButtonGame> ();
name = transform.gameObject.name;
}
// Update is called once per frame
void Update () {
if (pressButtonIn) { //if the button is clicked, push it in a little.
transform.Translate (Vector3.right * speed * Time.deltaTime);
}
if (pressButtonOut) { //if the button is clicked and is pushed in, push it back out.
transform.Translate (-Vector3.right * speed * Time.deltaTime);
}
if (bGame.button1Pressed == true && name == "Button1") { //if the script tells us that our particular transform is to be pushed...
StartCoroutine (ButtonPressed ()); //start push coroutine (see above vector translates)
}
if (bGame.button1Down && bGame.button1Pressed) { //likewise if the script tells us our particular transform is to be unpushed..
StartCoroutine (ButtonUnpressed()); //start coroutine
}
if (bGame.button2Pressed == true && name == "Button2") {
StartCoroutine (ButtonPressed ());
}
if (bGame.button2Down && bGame.button2Pressed) {
StartCoroutine (ButtonUnpressed());
}
if (bGame.button3Pressed == true && name == "Button3") {
StartCoroutine (ButtonPressed ());
}
if (bGame.button3Down && bGame.button3Pressed) {
StartCoroutine (ButtonUnpressed());
}
if (bGame.button4Pressed == true && name == "Button4") {
StartCoroutine (ButtonPressed ());
}
if (bGame.button4Down && bGame.button4Pressed) {
StartCoroutine (ButtonUnpressed());
}
if (bGame.button5Pressed == true && name == "Button5") {
StartCoroutine (ButtonPressed ());
}
if (bGame.button5Down && bGame.button5Pressed) {
StartCoroutine (ButtonUnpressed());
}
if (bGame.button6Pressed == true && name == "Button6") {
StartCoroutine (ButtonPressed ());
}
if (bGame.button6Down && bGame.button6Pressed) {
StartCoroutine (ButtonUnpressed());
}
}
IEnumerator ButtonPressed(){ //access our update script transform translates to push button in.
pressButtonIn = true;
yield return new WaitForSeconds(.5f);
pressButtonIn = false;
}
IEnumerator ButtonUnpressed(){ //access our update script transform translates to push button back out.
pressButtonOut = true;
yield return new WaitForSeconds(.5f);
pressButtonOut = false;
}
void OnMouseDown() { //here we detect which transform is being pressed.
if (name == "Button1") {
bGame.button1Down = true;
}
if (name == "Button2") {
bGame.button2Down = true;
}
if (name == "Button3") {
bGame.button3Down = true;
}
if (name == "Button4") {
bGame.button4Down = true;
}
if (name == "Button5") {
bGame.button5Down = true;
}
if (name == "Button6") {
bGame.button6Down = true;
}
}
}
It's pretty hard to say what could go wrong when you have public variables like ButtonGame.button1Down
and ButtonGame.button1Pressed
. We don't know how you are changing their values outside of your ButtonGameButton
class.
To me those variables go against many principles of object oriented program$$anonymous$$g. If you have a ButtonGameButton
class, why do you store the button's state in some other class ? Each button should only know their own state and react graphically when it changes.
The game class should then have an array of these buttons and decide what to do when one of them indicates being pressed. For this purpose the Button class should have appropriate "getters" for it's status variables.
The "scalability" of the code becomes very bad, since you have to change your ButtonGameButton
class every time you add a new button.
I agree with you as far as the scalability and simplicity of this model. However, I'm very bad at comprehending arrays right now, so working with bools ins$$anonymous$$d makes understanding them much easier for me.
The reason the buttons access another script is because their parent object must know their state to keep track of the points. If you look at my comment on the answer below, I've posted the script. Again, there's probably a much simpler and more elegant way to do this, but this is all I can do for now, unless someone shows me a better way (which I'm all open to!).
Answer by hatake3 · Sep 21, 2014 at 11:09 AM
I think you're setting bGame.buttonXDown to true when pressing button X, but you're not setting it to false again when button is "pressed out". Therefore, the condition in all the
if (bGame.buttonXDown && bGame.buttonXPressed)
if-statemements in the Update method will be true after you've pressed all the buttons.
You should do
bGame.buttonXDown = false;
e.g. in the ButtonUnPressed coroutine or in the if (pressButtonOut) block
Here's the "bGame" code. I seem to be doing what you describe in your answer. I know it seems sort of messy, but I couldn't figure out a better way to do it!
using UnityEngine;
using System.Collections;
public class ButtonGame : $$anonymous$$onoBehaviour {
public bool button1Down = false;
public bool button1Pressed = false;
public bool button2Down = false;
public bool button2Pressed = false;
public bool button3Down = false;
public bool button3Pressed = false;
public bool button4Down = false;
public bool button4Pressed = false;
public bool button5Down = false;
public bool button5Pressed = false;
public bool button6Down = false;
public bool button6Pressed = false;
public int total = 0;
public int targetTotal;
// Use this for initialization
void Start () {
targetTotal = Random.Range (1, 21);
}
// Update is called once per frame
void Update () {
if (button1Down && !button1Pressed) {
total += 1;
button1Down = false;
button1Pressed = true;
}
if (button1Down && button1Pressed) {
button1Down = false;
button1Pressed = false;
total -= 1;
}
if (button2Down && !button2Pressed) {
total += 2;
button2Down = false;
button2Pressed = true;
}
if (button2Down && button2Pressed) {
button2Down = false;
button2Pressed = false;
total -= 2;
}
if (button3Down && !button3Pressed) {
total += 3;
button3Down = false;
button3Pressed = true;
}
if (button4Down && button4Pressed) {
button4Down = false;
button4Pressed = false;
total -= 4;
}
if (button4Down && !button4Pressed) {
total += 4;
button4Down = false;
button4Pressed = true;
}
if (button4Down && button4Pressed) {
button4Down = false;
button4Pressed = false;
total -= 4;
}
if (button5Down && !button5Pressed) {
total += 5;
button5Down = false;
button5Pressed = true;
}
if (button5Down && button5Pressed) {
button5Down = false;
button5Pressed = false;
total -= 5;
}
if (button6Down && !button6Pressed) {
total += 6;
button6Down = false;
button6Pressed = true;
}
if (button6Down && button6Pressed) {
button6Down = false;
button6Pressed = false;
total -= 6;
}
if (total == targetTotal) {
Debug.Log ("you win!");
}
}
}
Answer by Addyarb · Sep 21, 2014 at 11:34 PM
Got it fixed by rewriting the entire script from scratch. Still not scalable by most means, but it works perfectly. Also added a cooldown. Anyone who stumbles upon this is free to use the code!
Script to place on buttons themselves: (Must have 1-6 buttons, or edit code accordingly) using UnityEngine; using System.Collections;
public class ButtonGameButton : MonoBehaviour {
public ButtonGame bGame; //Our parent object's score keeping script.
public string myName; //The name of the object, used to differentiate between cubes in the heirarchy.
private Transform myTransform; //Our transform. Varies on which cube is clicked. (i.e. if Button1 is clicked, myTransform = button1.transform)...
public bool pushButtonIn = false; //The bool to tell the update function to translate the button backwards, into the wall.
public bool pushButtonOut = false; //The bool to tell the update function to translate the button forwards, away from the wall.
public int total = 0; //The total of points we currently have. Once we reach the target points, we win the game.
public bool pushedIn = false; //The bool to tell us if the button is pushed in or not. If false, it is not pushed in.
public bool canPressButton = true;
void Start () {
myName = gameObject.name;
bGame = GetComponentInParent<ButtonGame> ();
}
void Update () {
if (pushButtonIn) { //if the IEnumerator function wishes for us to push the button in...
myTransform.Translate (Vector3.right * Time.deltaTime); //push the button's transform towards the wall.
}
if (pushButtonOut) { //if the IEnumerator function wishes for us to push the button back out...
myTransform.Translate(-Vector3.right * Time.deltaTime); //push the button's transform away from the wall.
}
}
void OnMouseDown() {
if (canPressButton) {
if (myName == "Button1" && pushedIn) { // If we press a button and it's name is button1 and it is depressed...
StartCoroutine (ButtonCooldown ()); //Start our button cooldown, to make sure players don't press too rapidly.
myTransform = transform.parent.FindChild ("Button1"); //The Transform which we should alter is button1's transform.
StartCoroutine (PushOut ()); //Start the PushOut coroutine, which will activate the if block in the update function.
bGame.total -= 1; //subtract 1 from the total in our parent object's script, because we unpushed button 1.
} else {
if (myName == "Button1") { // If we press a button and it's name is button1 and it is not yet depressed...
StartCoroutine (ButtonCooldown ()); //Start our button cooldown, to make sure players don't press too rapidly.
myTransform = transform.parent.FindChild ("Button1"); //The transform which we should alter is button1's transform.
StartCoroutine (PushIn ()); //Start the PushIn coroutine, which will activate the if block in the update function
//to push the button backwards.
pushedIn = true; //Set pushed in to true, which will tell us that the button is currently depressed.
bGame.total += 1; //add 1 to the total in our parent object's script, because we pushed button 1.
//The value of the button will always equal it's name, and we access the parent object because
//simply storing the int in this script would not be consistent with the rest of the buttons' scripts.
}
}
if (myName == "Button2" && pushedIn) {
StartCoroutine (ButtonCooldown ());
myTransform = transform.parent.FindChild ("Button2");
StartCoroutine (PushOut ());
bGame.total -= 2;
} else {
if (myName == "Button2") {
StartCoroutine (ButtonCooldown ());
myTransform = transform.parent.FindChild ("Button2");
StartCoroutine (PushIn ());
pushedIn = true;
bGame.total += 2;
}
}
if (myName == "Button3" && pushedIn) {
StartCoroutine (ButtonCooldown ());
myTransform = transform.parent.FindChild ("Button3");
StartCoroutine (PushOut ());
bGame.total -= 3;
} else {
if (myName == "Button3") {
StartCoroutine (ButtonCooldown ());
myTransform = transform.parent.FindChild ("Button3");
StartCoroutine (PushIn ());
pushedIn = true;
bGame.total += 3;
}
}
if (myName == "Button4" && pushedIn) {
StartCoroutine (ButtonCooldown ());
myTransform = transform.parent.FindChild ("Button4");
StartCoroutine (PushOut ());
bGame.total -= 4;
} else {
if (myName == "Button4") {
StartCoroutine (ButtonCooldown ());
myTransform = transform.parent.FindChild ("Button4");
StartCoroutine (PushIn ());
pushedIn = true;
bGame.total += 4;
}
}
if (myName == "Button5" && pushedIn) {
StartCoroutine (ButtonCooldown ());
myTransform = transform.parent.FindChild ("Button5");
StartCoroutine (PushOut ());
bGame.total -= 5;
} else {
if (myName == "Button5") {
StartCoroutine (ButtonCooldown ());
myTransform = transform.parent.FindChild ("Button5");
StartCoroutine (PushIn ());
pushedIn = true;
bGame.total += 5;
}
}
if (myName == "Button6" && pushedIn) {
StartCoroutine (ButtonCooldown ());
myTransform = transform.parent.FindChild ("Button6");
StartCoroutine (PushOut ());
bGame.total -= 6;
} else {
if (myName == "Button6") {
StartCoroutine (ButtonCooldown ());
myTransform = transform.parent.FindChild ("Button6");
StartCoroutine (PushIn ());
pushedIn = true;
bGame.total += 6;
}
}
}
}
IEnumerator PushIn(){
pushButtonIn = true; //Set the push button bool to true, so that our update function's translate code will activate.
yield return new WaitForSeconds (.5f); //wait 3 seconds for our button to reach the desired position in the wall.
pushButtonIn = false; //Shut our translate code off, which will stop the button's movement until it is unpushed.
}
IEnumerator PushOut(){
pushButtonOut = true; //Set the push button bool to true, so that our update function's translate code will activate.
yield return new WaitForSeconds (.5f); //wait 3 seconds for our button to reach the desired position in the wall.
pushButtonOut = false; //Shut our translate code off, which will stop the button's movement until it is unpushed.
pushedIn = false; //Finally, set our PushedIn bool to false, which tells us that the button is not depressed.
}
IEnumerator ButtonCooldown(){
canPressButton = false;
yield return new WaitForSeconds (1);
canPressButton = true;
}
}
Script to keep on parent object (scorekeeping code)
using UnityEngine;
using System.Collections;
public class ButtonGame : MonoBehaviour {
public int total = 0;
public int targetTotal;
private Vector3 LocationToDropKey;
public Transform key;
// Use this for initialization
void Start () {
targetTotal = Random.Range (1, 21);
LocationToDropKey = transform.TransformPoint(0, 0, 1);
}
void Update () {
if (targetTotal == total) {
//we win
Instantiate (key, LocationToDropKey, transform.rotation);
}
}
}
Damn, I was working on alternative scripts you could use :p Glad you got it working!
Your answer
![](https://koobas.hobune.stream/wayback/20220613163445im_/https://answers.unity.com/themes/thub/images/avi.jpg)