Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

how to have action occur after user presses two buttons in succession -- out of 216 buttons

Discussion in 'Scripting' started by Zaffer, Aug 31, 2014.

  1. Zaffer

    Zaffer

    Joined:
    Oct 21, 2010
    Posts:
    266
    Hi,

    I am setting up an interactive palette of 216 buttons. I would like to have an action occur after the user chooses 2 buttons in succession out of the 216. I am making the palette with GUI code like this:

    Code (JavaScript):
    1. if (GUI.Button(Rect(0, 0, 12, 12), GUIContent(Resources.Load("0/0 xxx 0/B0_0_0"), "0 0 0"))) {Debug.Log("0 0 0 ");}
    2.     if (GUI.Button(Rect(12, 0, 12, 12), GUIContent(Resources.Load("0/0 xxx 0/B0_51_0"), "0 51 0"))) {Debug.Log("0 51 0");}
    3.     if (GUI.Button(Rect(24, 0, 12, 12), GUIContent(Resources.Load("0/0 xxx 0/B0_102_0"), "0 102 0"))) {Debug.Log("0 102 0");}
    4.     if (GUI.Button(Rect(36, 0, 12, 12), GUIContent(Resources.Load("0/0 xxx 0/B0_153_0"), "0 153 0"))) {Debug.Log("0 153 0");}  
    5.     if (GUI.Button(Rect(48, 0, 12, 12), GUIContent(Resources.Load("0/0 xxx 0/B0_204_0"), "0 204 0"))) {Debug.Log("0 204 0");}
    6.     if (GUI.Button(Rect(60, 0, 12, 12), GUIContent(Resources.Load("0/0 xxx 0/B0_255_0"), "0 255 0"))) {Debug.Log("0 255 0");}
    etc, etc X 216 buttons

    My original plan when I got this idea was to have some logic like this (pseudocode)
    Code (JavaScript):
    1. if(any button is pressed){
    2.        set buttonA flag;
    3.    }
    4. if(buttonA flag && any button is pressed){
    5.        do something;
    I guess I was thinking of objects and tags, but obviously, that won't work with buttons because there's no way to tag buttons (is there?) Also each button comes with its own built in "if clause" so I would have to make 216 sets of "if/else" clauses, one for each button which seems too laborious -- both for me and for the processor. I have a feeling I'm going about this the wrong way. Any suggestions will be greatly appreciated. (image attached of my palette so far). Thanks.

    Zaffer button_palette.JPG
     
  2. Polymorphik

    Polymorphik

    Joined:
    Jul 25, 2014
    Posts:
    599
    Whoa....no no no...rethink your strategy bro. I came across a similar problem when I created a Mine-Sweeper game in Java a while back. Each tile was a 'Button', I wanted to have the amount of buttons be relative to the size of the screen when the player started the game. In order for me to do this to avoid hard coding X amount of buttons. I used an array. With a single method I could create them and add a listener to each button and figure out which button was pressed.

    Here you need the same strategy. Don't go and make 216 buttons that is torture and poor software design. What you want, is to flag each button. When the buttons is clicked, have it trigger an event that will then execute code for THAT specific button. This is the best approach if you have that many buttons. Also, organize and categorize what each button does. This way instead of having 1 group of 216 buttons, you can break them down into smaller groups and maintain them that way.

    Hope this helps.
     
  3. Themp

    Themp

    Joined:
    Nov 8, 2011
    Posts:
    96
    You might want to load your buttons via a forloop:
    Code (csharp):
    1.  
    2. int Rows = Mathf.Ceil(sqrt(216));
    3. int Columns  = Rows;
    4.  
    5. for(int i=0; i < Rows; i++)
    6. {
    7.     for(int j=0; j< Columns; j++)
    8.     {
    9.         if(Rows*Columns < texturesArray.Count)
    10.         {
    11.              if (GUI.Button(Rect(i*50, j*50, 12, 12), texturesArray[i][j], "0 0 0"))) {Debug.Log("0 0 0 ");}
    12.         }
    13.     }
    14. }
    15.  
    Also calling Resources.Load each GUI update is too intensive, I'd preload everything in the Start() function and put em in an array.
    A 2-Dimensional array is handy for this case.


    After all that you can just check the number you've clicked.
    So in the if(GUI.BUTTON) statement you can set:
    Debug.Log("Pressed: " + i*j);
    That way you can see which button you pressed (refering again to the texturesArray).

    And to help you a little more, each button gives you an integer (giving you the button you pressed).
    Now I don't know what you want to do with these buttons? (maybe for a gradient IDK)

    There are alot of ways to handle it but I'd suggest making a List<int> and storing the number there after you pressed it (This way you can store more then 2 numbers for other uses then 2 presses (Even for 5 presses should you want it), (Code should be dynamic and adaptive)

    And after each press you should check for the 2 buttons.
    So make a function called CheckPresses() for example which you execute each time you press a GUI.Button.

    Which is basically:
    Code (csharp):
    1.  
    2. if(integerList.Count >= 2)
    3. {
    4.   //do something with the numbers you have
    5. //Maybe with a forloop like this (I don't know what you need them for)
    6. /*
    7.      for(int i=0; i < integerList.Count; i++)
    8.      {
    9.           //do something here
    10.     }
    11. */
    12. }
    13.  
    Alot of people might initially think to put this in a Update() loop but you only need to check when you press so this reduces strain and thus makes your program more efficient

    Also to give you a little more insight, 1 Resources.Load(Whatever) call is easily worth 1000 if statements, not only due to the amount of checks, but also because of the latency which happens when you load a file
     
    Last edited: Aug 31, 2014
    Polymorphik likes this.
  4. Serge_Billault

    Serge_Billault

    Joined:
    Aug 26, 2014
    Posts:
    190
    In reality you dont need any button : https://www.sugarsync.com/pf/D2307301_98582733_618566

    The palette is just a texture of nb cols * nb rows pixels. When it receives a click event, the selection is immediate : it's deduced from where the click occured in the palette window. To resume : zero buttons.

    If one would want to modify the palette color at a specific slot, it would be as epic as m_palette.SetPixel( col, row, color ).
     
    Last edited: Aug 31, 2014
  5. Zaffer

    Zaffer

    Joined:
    Oct 21, 2010
    Posts:
    266
    Hi Themp,

    Thanks for your help. Here's what I'm trying to do: http://www.bitsong.com/forPosting/Unity/Color%20Cube_Build.html/Color%20Cube_Build.html.
    It's a 3D interactive RGB color cube -- made so you can travel inside it (using the mouse) and look around to see how the colors relate to each other. You can also use the Z, X, C, V, F, and G keys to rotate the cube and move it up and down. I'm trying to make an interactive palette where the user can click on two color buttons and then be lined up to glide from the first color to the second, seeing all the colors in between. I have the "gliding" code done.

    Here's what I have so far, based on your suggestion. I made an array for one 6x6 square and put 36 Resources.Load commands in it -- didn't quite understand how to make this a two dementional array. If this does work, eventually I'll have to make 6 of these and line them up with two across and three down.

    Code (JavaScript):
    1. textureArray_1[0] = GUIContent(Resources.Load("0/0 xxx 0/B0_0_0"));
    2. textureArray_1[1] = GUIContent(Resources.Load("0/0 xxx 0/B0_51_0"));
    3. textureArray_1[2] = GUIContent(Resources.Load("0/0 xxx 0/B0_102_0"));
    4. textureArray_1[3] = GUIContent(Resources.Load("0/0 xxx 0/B0_153_0"));
    5. textureArray_1[4] = GUIContent(Resources.Load("0/0 xxx 0/B0_204_0"));
    6. textureArray_1[5] = GUIContent(Resources.Load("0/0 xxx 0/B0_255_0"));
    etc, etc up to [35]

    Here's my forloop:

    Code (JavaScript):
    1. var rows : int = 6.0;
    2.     var columns : int = 6.0;
    3.  
    4.       for(var i=0; i <= rows; i++)
    5.     {
    6.         for(var j=0; j<= columns; j++)
    7.         {
    8.             if(rows * columns <= textureArray_1.Count)
    9.             {      
    10.                 if (GUI.Button(Rect(i*12, j*12, 12, 12), textureArray_1[i*j], "0 0 0")){
    11.                     Debug.Log("0 0 0 ");
    12.                 }
    13.             }
    14.         }
    15.     }
    16.  
    Obviously it's got some problems. (I don't know what to put in the textureArray[ ], 35, 0, i, j, i*j?). But the main problem is that I get the error message: "Ambiguous reference "Button". Don't know what to do with that one. The only Button is the one in the forloop. Any suggestions will be greatly appreciated. Thanks.
     
    Last edited: Aug 31, 2014