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. Dismiss Notice

How to know when a gui.button is clicked, so a variable in another script can change?

Discussion in 'Scripting' started by Exnihilon, May 14, 2014.

  1. Exnihilon

    Exnihilon

    Joined:
    Mar 2, 2014
    Posts:
    157
    Hello to all. I need a little help to make a variable change in runtime, between two js scripts.
    Let me explain what I want to achieve in my application.

    There is a gui.button named "IsoRotate" attached to a js script named "Isometric" that does a 45degrees rotation on a cube gameobject on the X axis
    .
    There is also another gui.button named "Rotate", that has a js script attached named "Rotation", that rotates the same cube gameobject on the X axis.

    Because the actions implemented on the cube have cumulative results, is there a way to have the X axis on the "Rotation" script, changed to the Z axe, only if the "IsometricRotation" gui.button is clicked?

    I know I should be using the get.component function, to access those variables between the scripts, but I'm new to Unity scripting and in programming in general, so any help or even better a working an example, would be very much welcomed.

    Thank you all in advance for your answers.
     
  2. laurelhach

    laurelhach

    Joined:
    Dec 1, 2013
    Posts:
    229
    Basically you need to have references between your script to be able to call them.
    Example:

    Script B:
    Code (csharp):
    1.  
    2. public var isoRotate;
    3.  

    Script A:
    Code (csharp):
    1.  
    2. ScriptB refB1;
    3. public Rect rectValue = new Rect(0,0,0,0);
    4.  
    5. void Awake(){
    6.      // You need to have your script (ScriptB) in a GameObject / Prefab in your scene to access it
    7.      refB1 = GameObject.FindGameObjectWithTag("tag of your script B").GetComponent<ScriptB>();
    8. }
    9.  
    10. void OnGUI(){
    11.      if(GUI.Button(rectValue, "IsometricRotation")){
    12.           refB1.isoRotate = "changeValue";
    13.      }
    14. }
    15.  
    16.  
    Your variable in your script you want to access needs to be public.
    This is obviously a way to access values and communicate between scripts, in the end, it might not satisfy your needs for what you try to achieve. You will need to build on this. Btw, this is c#.
     
  3. Exnihilon

    Exnihilon

    Joined:
    Mar 2, 2014
    Posts:
    157
    Hi @laurelhach. Thank you for your answer and the snippet code, though I need to make it in js, as both my scripts are written in this language.

    I have to ask you another question about the example code you posted. I see there is a OnGUI function, that does the change in variable value as I can understand, is that so?

    As you can see in my posting, I have already two buttons, the "IsoRotate" button (button A with script A = Isometric.js) and the "Rotate" button (button B with script B=Rotation.js). I don't need a new button to be clicked in order to change the variable value.

    All I want to achieve is the following functionality to the user:

    Case 1
    a. If the button A (IsoRotate), is clicked before button B (Rotate) is clicked - A boolean that monitors the button A clicking, is changed to "true" only when the button is clicked in script A (Isometric.js).
    b. The button B (Rotate) is clicked after the button A has been clicked. - The variable of the X axis is set to "0" and the Z axis is set to "1".

    Case 2
    a. The button A is not clicked before button B is clicked - The boolean remains as "false"
    b. The button B is clicked. - The variable of the axis X remains as set to "1".

    Hope it is more clear to you now.

    Can you re-post a modified version of your example, even in C#? I need to see the logic in coding, and I will build on it as a js code for my app. Thank you in advance for your answer.
     
    Last edited: May 15, 2014
  4. laurelhach

    laurelhach

    Joined:
    Dec 1, 2013
    Posts:
    229
    Hi Exnihilon,

    The OnGUI method is used when you want to display something on screen using GUI. or GUILayout.
    It was simply to show you how to trigger your variable using a button.

    So I am not a coder by experience, so the way I will show you might not be optimal.
    From what I understand you probably should have your buttons in the same script. It would be easier to manage the conditions that way.

    I will still try to do it your way (I don't know if you have other dependencies).

    You should note that if you want to repeat your scenario, it won't work anymore as I am not resetting the values.
    So from what you said, the script will work once for now.
    You probably need a way to reset your sequence if you have too (maybe after clicking B ?).

    Anyway, let me know if this is enough.
    PS: I didn't spell check the code, so I might have errors (Caps, etc.)

    ScriptA:
    Code (csharp):
    1.  
    2.  
    3. // Variable
    4. Rotation rotationB; // you should also try to use a different name for your script as rotation is something used in your transform options.
    5. public Rect rectValue = new Rect(0,0,0,0);
    6.  
    7. void Awake(){
    8.      rotationB =  GameObject.FindGameObjectWithTag("GameObject that contains Rotation script - Tag Name").GetComponent<Rotation>();
    9. }
    10.  
    11. // Where your GUI.Button Is
    12. if(GUI.Button(rectValue, "IsoRotate"){ // your gui button will show the name "IsoRotate".
    13.      // We set the bool to true if button A has been pressed first.
    14.      rotationB.SpaceController(true, false);
    15. }
    16.  
    Script B
    Code (csharp):
    1.  
    2.  
    3. Isometric isometricA;
    4. bool yourBool = false; //A boolean that monitors the button A
    5. int variableAxisX = 0;
    6. int variableAxisZ = 0;
    7.  
    8. void Awake(){
    9.      isometricA =  GameObject.FindGameObjectWithTag("GameObject that contains Isometric script - Tag Name").GetComponent<Isometric>();
    10. }
    11.  
    12. void Something(){
    13.      // Where your GUI.Button Is
    14.      if(GUI.Button(rectValue, "Rotate"){ // your gui button will show the name "Rotate".
    15.           SpaceController(false, true);
    16.      }
    17. }
    18.  
    19. // To be accessible from the other script, the method / function needs to be public
    20. public void SpaceController(bool isIso, bool isRot ){
    21.  
    22.      // The first time, the bool is false, so it won't execute.
    23.      // If you click on A, the statement below will set the bool to true and the next time you click it will trigger.
    24.      // Somehow, you need to be able to reset your variables to be able to run your check again.
    25.      if(yourBool  isRot ){
    26.           // The variable of the X axis is set to "0" and the Z axis is set to "1".
    27.           variableAxisX = 0;
    28.           variableAxisZ = 1;
    29.      }
    30.  
    31.      if(isIso  !yourBool)
    32.           // A boolean that monitors the button A
    33.           yourBool = true;
    34.  
    35.      if(isRot  !yourBool){
    36.           variableAxisX = 1;
    37.           // what about Z axis?
    38.      }
    39.  
    40. }
    41.  
    42.  
     
  5. Exnihilon

    Exnihilon

    Joined:
    Mar 2, 2014
    Posts:
    157
    Hi @laurelhach. Thank you for your updated answer and the snippet code example. Please take a look at my updated coding that is following your logic, written in unityscript (js). I believe you could read it and maybe you could help solve out a little problem that I'm facing.


    Here is the code for script A (Isometric.js):

    Code (csharp):
    1.  
    2.     var btnATexture : Texture;
    3.     private var isRotated : boolean = false;
    4.     private var mustRotate : boolean = false;
    5.     var checkBtnClick : boolean = false; //A boolean that monitors the button (A) "IsoRotate"
    6.     private var modelOnTarget : GameObject;
    7.     var rotationB : doRotation;
    8.      
    9.     function Awake(){
    10.          rotationB =  GameObject.FindGameObjectWithTag("markerObject").GetComponent(doRotate);
    11.     }
    12.      
    13.     // Use this for initialization
    14.     function Start()
    15.     {
    16.         modelOnTarget = GameObject.FindGameObjectWithTag("markerObject");
    17.     }
    18.      
    19.     // Update is called once per frame
    20.     function Update()
    21.     {
    22.         if (mustRotate  !isRotated)
    23.         {
    24.             //Rotate all models 45 degrees around Y axis
    25.             if (modelOnTarget != null)
    26.             {
    27.                 var modelTrackable;
    28.                
    29.                   modelTrackable = modelOnTarget.transform.GetChild(0);
    30.                     modelOnTarget.transform.RotateAround(Vector3(1,0,0), Mathf.PI/3);  
    31.             }
    32.            
    33.            isRotated = true;
    34.            mustRotate = false;
    35.             }
    36.         }
    37.            
    38.      function OnGUI()
    39.            {
    40.             if (GUI.Button(Rect(20, 100, 40, 25), btnATexture))
    41.                 {
    42.                     if (!isRotated)
    43.                         {
    44.                         mustRotate = !mustRotate;
    45.                           checkBtnClick = true; //A boolean that monitors the button (A) "IsoRotate"
    46.                     }
    47.                 }
    48.  
    Here is the code for script B (doRotation.js):

    Code (csharp):
    1.  
    2. #pragma strict
    3.    
    4.     static var rotateIt = false;    
    5.     var isometricA;
    6.     //A boolean that monitors the button (A) "IsoRotate"
    7.     var checkBtnClick : boolean = false;
    8.        
    9.        
    10.     function Awake()
    11.     {
    12.          isometricA =  GameObject.FindGameObjectWithTag("markerObject").GetComponent(Isometric);
    13.     }        
    14.      
    15.     function Update()
    16.     // The first time, the boolean is false, so it won't execute.
    17.     {
    18.         if (rotate)
    19.          {
    20.          transform.Rotate(new Vector3(0, 80, 0) * Time.deltaTime);  //This is the initial setting for rotation on Y axis, when the button  (A) Isometric                                                                                                                          //has not  been clicked.
    21.         }
    22.             else
    23.             {
    24.     // If button (A) "IsoRotate" is clicked, then the statement below  will set the boolean to true, and the Y axis has to be changed to Z.
    25.  
    26.             if(checkBtnClick)
    27.                     {
    28.                     checkBtnClick = true; //A boolean that monitors the button (A) "IsoRotate"
    29.                       transform.Rotate(new Vector3(0, 0, 80) * Time.deltaTime);
    30.                     }
    31.             }
    32.     }
    33.             static function doRotation()
    34.                 {
    35.                     rotate = !rotate;
    36.                 }
    37.  

    The problem is, when the button (A) "IsoRotate" is clicked, I get the variable "checkBtnClick" (same as "yourBool" at your example), also checked in the Inspector, but I cannot get the same variable to trigger the the Y and Z axis swap, as it should when the button B (Rotate) is clicked. I get the axis swap, only if manually check the variable in the Inspector, in "Rotate.js" script.

    Any clues, on how to make the variable " checkBtnClick", trigger the axis change from Y to Z, automaticaly when button (B) "Rotate" is clicked, afterwards the button (A) "IsoRotate" has been clicked?

    Thank you for your time reading this updated post.
     
  6. laurelhach

    laurelhach

    Joined:
    Dec 1, 2013
    Posts:
    229
    You didn't quite do what I had in the example above.
    You missed the update I was doing in both scripts to make it work.
    So basically in your code example, you are not updating the variables from A to B.
    The reason why I've added the Awake() method is to have a reference to your other script.
    But if you want you could just move my line from my Awake methods to your Start() methods.

    I was using this below to try to keep things organized.
    I was refering to the method in order to update the bools always at the same place (script B).

    Code (csharp):
    1.  
    2. rotationB.SpaceController(true, false);
    3.  
    When you click on the button from your script A, you need to also update the variable in the other script.

    Code (csharp):
    1.  
    2.             if (GUI.Button(Rect(20, 100, 40, 25), btnATexture)) {
    3.                if (!isRotated){
    4.                    mustRotate = !mustRotate;
    5.                    checkBtnClick = true; //A boolean that monitors the button (A) "IsoRotate"
    6.                    // Here ***
    7.                    // you need to update the bool on the other script to make it work otherwise only the bool in your current script will be updated.
    8.                    rotationB.checkBtnClick = true;
    9.                }
    10.            }
    11.  
    Hope that helps.
     
  7. Exnihilon

    Exnihilon

    Joined:
    Mar 2, 2014
    Posts:
    157
    Hello again, @laurelhach. Thank you for the updated post following my code logic. The reason I didn't follow up your example, is that I couldn't understood the logic of the "SpaceController(true,false). Meaning where, and how to add it in my posted code? As a variable or as a function?

    If I put it in the "Start" function I'm getting the error " SpaceController is not a member of 'doRotate'. I know, I'm missing somthing here, but what is it?

    ***EDIT***
    Need to mention that button (A) "IsoRotate" is generated inside the same script, but button (B) "Rotate", is referenced to script "doRotate.js". Both scripts (A) and (B), are attached to the same gameobject (Cube).
    Hope that clears all out.
     
    Last edited: May 16, 2014
  8. laurelhach

    laurelhach

    Joined:
    Dec 1, 2013
    Posts:
    229
    SpaceController is a function and needs to be added like Awake() or Start() inside your class.

    I was passing two arguments (true and false) in the function.
    Depending of the bool values, I was setting your values (X, Z, Etc.) to what you were asking.
    (A first, B second, or B first).

    Basically you need to update your bools and such when you click on the buttons.

    So the function SpaceController was in your second script and I was calling it from the buttons when clicked.

    Can you paste you complete code? In your example above, you also have missing brackets, so there is probably more stuff...
    If you don't want to post it, you can send me a private message if you prefer.

    PS: If your both script are in the same GameObject, you don't need to do a FindGameObject... just do :
    Code (csharp):
    1.  variable = GetComponent<...>();
     
  9. Exnihilon

    Exnihilon

    Joined:
    Mar 2, 2014
    Posts:
    157
    Well, @laurelhach, don't mind the missing brackets. This is pretty much the stuff in the posted code (Posted: 12:32 PM 2 Hours Ago)

    I have added the function for 'SpaceController' as bellow:

    var SpaceController;
    function SpaceController( ){
    }

    Also added the line 'SpaceController(false, true); ' in the 'function Start()'.

    Still, can compile through o.k. I'm getting the error "Error BCE0089: Type 'Isometric' already has a definition for 'SpaceController'. (BCE0089) (Assembly-UnityScript-firstpass)" in the "Isometric.js"

    Can you help, sort it out? Thank you in advance.
     
  10. laurelhach

    laurelhach

    Joined:
    Dec 1, 2013
    Posts:
    229
    Did you add SpaceController() in your both script?
    I need to see your scripts ...
    And SpaceController(false, true); shouldn't be added in Start(), it has to be added in the statement that you execute when you click on the button.
     
    Last edited: May 16, 2014
  11. Exnihilon

    Exnihilon

    Joined:
    Mar 2, 2014
    Posts:
    157
    Here is the code updated, with our last quotes. The value that is checking for the button click, is updated between both scripts A-B, but there is a misfunction.

    The button (A) 'IsoRotate", does also the rotation on axis Y when clicked. This function should be done by clicking button (B) "Rotate", after its axis is set to Z insdead of initial Y.

    Here is the updated Script (A), "IsoRotate.js":

    Code (csharp):
    1.  
    2.     var btnATexture : Texture;
    3.     private var isRotated : boolean = false;
    4.     private var mustRotate : boolean = false;
    5.     var checkBtnClick : boolean = false; //A boolean that monitors the button Isometric
    6.     private var chipsTarget : GameObject;
    7.     var rotationB : doRotate;
    8.      
    9.     function Awake(){
    10.          rotationB =  GameObject.FindGameObjectWithTag("markerObject").GetComponent(doRotate);
    11.     }
    12.      
    13.     function SpaceController(){
    14.     }
    15.  
    16.     // Use this for initialization
    17.     function Start()
    18.     {
    19.         modelOnTarget = GameObject.FindGameObjectWithTag("markerObject");
    20.     }
    21.      
    22.     // Update is called once per frame
    23.     function Update()
    24.     {
    25.         if (mustRotate  !isRotated)
    26.         {
    27.             //Rotate all models 45 degrees around Y
    28.             if (modelOnTarget != null)
    29.             {
    30.                 var modelTrackable;
    31.                
    32.                   modelTrackable = modelOnTarget.transform.GetChild(0);
    33.                     modelOnTarget.transform.RotateAround(Vector3(1,0,0), Mathf.PI/3);  
    34.             }
    35.            
    36.            isRotated = true;
    37.            mustRotate = false;
    38.             }
    39.         }
    40.            
    41.      function OnGUI()
    42.            {
    43.             if (GUI.Button(Rect(20, 100, 40, 25), btnATexture))
    44.                 {
    45.                     if (!isRotated)
    46.                         {
    47.                           mustRotate = !mustRotate;
    48.                           checkBtnClick = true; //A boolean that monitors the button Isometric
    49.                           rotationB.isIsoBtnPressed = true; //Updates the values in both scripts
    50.                     }
    51.                 }    
    52.         }        
    53.  
    54.  
    Here is the updated Script (B), "Rotate.js":

    Code (csharp):
    1.  
    2. #pragma strict
    3.    
    4.     static var rotate = false;    
    5.     var isometricA;
    6.     //A boolean that monitors the button (A) "Isometric"
    7.        var checkBtnClick : boolean = false;
    8.        
    9.        
    10.     function Awake()
    11.     {
    12.          isometricA =  GameObject.FindGameObjectWithTag("markerObject").GetComponent(Isometric);
    13.     }        
    14.  
    15.     function SpaceController(){
    16.     }
    17.  
    18.      
    19.     function Update()
    20.     // The first time, the boolean is false, so it won't execute.
    21.     {
    22.         if (rotate)
    23.          {
    24.          transform.Rotate(new Vector3(0, 80, 0) * Time.deltaTime); //This is the initial setting, for rotation on Y axis, when button (A) "Isometric", has not been clicked.
    25.         }
    26.             else
    27.             {
    28.     // If button (A) "Isometric" is clicked,then the statement below will set the boolean to true, and the Y axis has to be changed to Z.
    29.  
    30.             if(checkBtnClick)
    31.                     {
    32.                     checkBtnClick = true; //A boolean that monitors the button (A) "Isometric"
    33.                       transform.Rotate(new Vector3(0, 0, 80) * Time.deltaTime); //This is the setting, for rotation on Z axis, when button (A) "Isometric", has been clicked.
    34.                     }
    35.             }
    36.     }
    37.             static function doRotation()
    38.                 {
    39.                     rotate = !rotate;
    40.                 }
    41.                    
    42.  
    Take a look, if you please, so we can close this thread with a working code. I have tried out to find what is causing this misfunction, could not make it funtion o.k, though. Thank you in advance.
     
  12. laurelhach

    laurelhach

    Joined:
    Dec 1, 2013
    Posts:
    229
    So first, the reason why your rotation happens right away, is because in your OnGUI function in script A, when you click on the button you set this to true, so the rotation executes automatically.

    Script A:
    Code (csharp):
    1.  
    2. // You need to have a bool that is only set to true from Script B when you click on your button.
    3. // See Below for code update
    4. if (mustRotate  !isRotated)
    5.  
    You don't need to have an empty function. It's useless to have something empty. Like an envelop that you would post without a letter :)
    So you can remove both of them, if you don't use it the way I did it at the beginning.
    Code (csharp):
    1.  
    2. function SpaceController(){
    3.      //is empty
    4. }
    5.  
    Script B:
    Where is your button ? I don't see anything about GUI.
    You need something like that with different values for your Rect if you want to be able to trigger it.
    Obviously you need a new var btnBTexture also.
    Code (csharp):
    1.  
    2. function OnGUI() {
    3.     if (GUI.Button(Rect(20, 100, 40, 25), btnBTexture)) {
    4.               isometricA.isIsoBtnPressed = true; //Updates the values in both scripts
    5.     }
    6. }
    7.  
    Updated Script A:
    Code (csharp):
    1.  
    2. // Update is called once per frame
    3. // you need to add in your declaration var isIsoBtnPressed : boolean = false;
    4. function Update(){
    5.       if (isIsoBtnPressed){
    6.         //Rotate all models 45 degrees around Y
    7.         if (modelOnTarget != null) {
    8.             var modelTrackable;
    9.             modelTrackable = modelOnTarget.transform.GetChild(0);
    10.             modelOnTarget.transform.RotateAround(Vector3(1,0,0), Mathf.PI/3);  
    11.         }
    12.        
    13.         // we set the bool to false again
    14.         // I never use Update function most of the time, but instead coroutine.
    15.         // you need to check when your object is done rotating, otherwise it will never rotate if you set the bool right away
    16.         // I commented the line, otherwise you will never see your object spinning. but you need to find a way to check when the rotation is done, if you want your object to rotate only on a specific angle.
    17.         // isIsoBtnPressed = !isIsoBtnPressed;
    18.  
    19.     }
    20. }
    21.  
    your function in script B doesn't seem to be called at any moment: doRotation().
    Are you calling it somewhere else?

    PS: is the Update working in your script B?
     
  13. Exnihilon

    Exnihilon

    Joined:
    Mar 2, 2014
    Posts:
    157
    Well @laurelhach, you must have missed reading my updated post that only in Script (A), "IsoRotate", there is a GUI.button inside the script.
    The Script (B) "Rotate", it is called through a GUI.button in another script. Therefore I don't/should not have a GUI.button inside that script.

    So, as it is cleared now, where should I put the line for updating values in both scripts?

    Code (csharp):
    1.  
    2.  
    3.  isometricA.isIsoBtnPressed//Updates the values in both scripts
    4.