Search Unity

Help with converting old GUI code and applying it to the new GUI

Discussion in 'Scripting' started by DigitalAdam, Jul 30, 2015.

  1. DigitalAdam

    DigitalAdam

    Joined:
    Jul 18, 2007
    Posts:
    1,209
    Hey,

    I'm new to scripting so please bear with me. What I'm trying to do is remove the GUI creation within the script below, and create new UI using Unity 5's GUI system. So I have two 'InputFields' in my scene; one for the bots responses, and another for my input. I also created a button to submit my input.

    I created a C# script called "Chat.cs". I think I need to attach that script to all 3 UI elements; 'On Value change (String)' and 'On Click'. Is that correct?

    Here is the original script, could someone help me refine it to work?

    Thanks!

    _________________________________

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class ChatWindowExample2 : MonoBehaviour
    6. {
    7.         private Chatbot bot;
    8.         public GUISkin myskin;
    9.         private string messBox = "", messBoxAnswer = "", ask = "", user = "Me";
    10.         private Rect windowRect;
    11.    
    12.         // Use this for initialization
    13.         void Start ()
    14.         {
    15.                 bot = new Chatbot ();
    16.         }
    17.  
    18.         void OnGUI ()
    19.         {
    20.                 GUI.skin = myskin;
    21.                 // Width of the text box; This formula sets the width according to the screen size
    22.                 float W = (700 * Screen.height) / 800;
    23.                 // Height of the text box; This formula adjust the height according to the screen size
    24.                 float H = (210 * Screen.height) / 600;
    25.                 if (Screen.width < Screen.height) {
    26.                         windowRect = new Rect (0, Screen.height - H, Screen.width, H);
    27.                 } else {
    28.                         windowRect = new Rect (Screen.width / 2 - W / 2, Screen.height - H, W, H);
    29.                 }
    30.                 windowRect = GUI.Window (2, windowRect, windowFunc, "Chat");
    31.         }
    32.  
    33.         private void windowFunc (int id)
    34.         {
    35.                 // Question User
    36.                 GUILayout.Label (user + ": " + messBox);
    37.                 // Response bot
    38.                 GUILayout.Label ("BOT: " + messBoxAnswer);
    39.                 //Skip a few lines to the box question becomes more below.
    40.                 //GUILayout.Label ("\n");
    41.                 //
    42.                 GUILayout.BeginHorizontal ();
    43.                 // Where the player put the text
    44.                 ask = GUILayout.TextField (ask);
    45.                 //=================================================
    46.                 if (GUILayout.Button ("Send", GUILayout.Width (75))) {  
    47.                         messBox = ask;              
    48.                         // Response Bot AIML
    49.                         var answer = bot.getOutput (ask);
    50.                         // Response BotAIml in the Chat window
    51.                         messBoxAnswer = answer;  
    52.                         ask = "";
    53.                 }
    54.                 //==================================================
    55.                 GUILayout.EndHorizontal ();
    56.         }//close windowFunc
    57.    
    58. }
    59.  
     
    Last edited: Aug 1, 2015
  2. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    [code ][/code ] tags. I'll wait ^_^
     
    LeftyRighty likes this.
  3. DigitalAdam

    DigitalAdam

    Joined:
    Jul 18, 2007
    Posts:
    1,209
    I don't know what you mean...

    Ah, I figured it out... I never posted any code before.
     
    LeftyRighty and Kiwasi like this.
  4. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    I can barely read it- a perfect example of why the old system is now the "old" system. That whole script needs to be trash-binned, so let's move on.

    Your GUI elements definitely won't have the same scripts attached to them- each GUI element serves a specific function right? Scripts are functional.

    From what you've said, it looks like the button is the only one that actually needs a custom script anyways- the user input knows how to handle user input just from the settings in the inspector, and the output just needs a Text component, not one that allows user input, because you don't type into it.

    The button needs logic- OnClick() can be used to run a function anywhere, on any object in the scene, but in this case I think you just need to run an internal function that reaches out and processes the text in the input, while outputting some other text to the output. In order to be able to reference both of them, just make the new script you're attaching to it have public fields for an Input Field type and a Text type (UnityEngine.UI namespace btw). Once you've done that, attach the script to the button, then once you've seen the new fields pop up in the inspector in it, just drag the InputField object and the Text object into their respective slots there so you can reference them from inside of the script. After that, you just need to make a new OnClick function in the script and process the input/output when the button is pressed.
     
  5. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    You young folk missed some brilliant fun times coding GUI in legacy. :)

    Here is what you need.
    • BeginScroll view is replaced with a scroll rect
    • Any objects inside the scroll should be children of the scroll rect
    • GUI.button is replaced with a button. You write a MonoBehavior that has a public method for the stuff inside of the if, and connect that up via the inspector
    • Begin horizontal is replaced with a horizontal layout group. Any objects in the horizontal layout group should be children of the horizontal layout group
    • A text field gets replaced with an input field. You create a MonoBehavior that has a public method with a string parameter to get the value from it. You can set it up so the value changes with every key press, or so it only changes when the user submits a value.
    • Labels are replaced by text
    • There is no native replacement for a drag window, but you can easily replace it with a custom component of your own. Check out my tutorial on drag and drop below.


    Hope that helps. Let me know if you have any problems. The key to working with the new UI is remembering everything is a GameObject. Its not learning anything new, its a case of unlearning all of the legacy UI stuff.
     
  6. DigitalAdam

    DigitalAdam

    Joined:
    Jul 18, 2007
    Posts:
    1,209
    I replaced the code with something a bit more scaled down and less to work with...

    Thanks for the suggestions. I actually never coded anything in my life, so I'm trying to get the above script to work with the new UI. I dont need anything fancy as far as scroll bars and such. I have 3 UI elements; two input text fields and one button. I just cant figure out how to write the new script, attach it to the elements, and get the button to work.
     
  7. DigitalAdam

    DigitalAdam

    Joined:
    Jul 18, 2007
    Posts:
    1,209
    From what I'm seeing; it looks like 1 input box is called "messBox", another is called "messBoxAnswer", and the button is called "ask". Im assuming each UI element needs a script attached. Can I use one script and attached that to all 3?
     
  8. DigitalAdam

    DigitalAdam

    Joined:
    Jul 18, 2007
    Posts:
    1,209
    Can someone help me take the above code, break it apart, and show me how to write a MonoBebavior script to attach it to the new UI please?
     
  9. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    my chatbot replacement... I assume yours does something a little more useful, this one just reverses the text string it's given

    Code (csharp):
    1.  
    2. using System.Linq;
    3.  
    4. public class Chatbot
    5. {
    6.     public Chatbot()
    7.     {
    8.  
    9.     }
    10.  
    11.     public string getOutput(string s)
    12.     {
    13.         return new string(s.ToCharArray().Reverse().ToArray());
    14.     }
    15. }
    16.  
    the script the button is going to be using

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4. using System.Collections;
    5.  
    6. public class ButtonPushScript : MonoBehaviour
    7. {
    8.     private Chatbot bot;
    9.  
    10.     public Text myOutputTextField;
    11.     public InputField myInputField;
    12.  
    13.     void Start()
    14.     {
    15.         bot = new Chatbot();
    16.     }
    17.  
    18.     public void FunctionToCallWhenAskButtonIsPushed()
    19.     {
    20.         myOutputTextField.text = bot.getOutput(myInputField.text);
    21.     }
    22. }
    23.  
    the canvas needs to be setup something like this


    something needs to have the ButtonPushScript attached to it, I've just put it onto the root canvas, it doesn't really matter what it's attached to so long as you know where it is when you setup the button's OnClick() function call. Might make sense to put it on the button, or have it somewhere else depending on how you're organising things and what you're doing.

    once you've added that script to something, drag the inputfield from the hierarchy into the "myInputField" slot in the script's inspector, drag the text field into the script's "myOutputTextField" slot in the inspector:


    now we just need to configure the button. Click on it in the hierarchy and go to the OnClick() event section in the inspector. Drag the gameobject you put the above script on into the object slot (lower left) then pick the function "FunctionToCallWhenAskButtonIsPushed" from the drop down list.


    jobs done






    all of the sizing/layout/ratio stuff is now done in the scene view by working with the canvas and ui elements, none of that needs to be done in code anymore

    learn section on the new ui
    https://unity3d.com/learn/tutorials/topics/user-interface-ui
     
    Last edited: Aug 4, 2015
  10. DigitalAdam

    DigitalAdam

    Joined:
    Jul 18, 2007
    Posts:
    1,209
    This worked perfectly. I really appreciate it!

    I worked through the UI videos and I understood what I needed to do, the scripting part is where I had all my issues. I have to ask, whats that first section of code used for?
     
  11. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    not sure what you mean by first section... but in order, the top code is just a class so I can keep the chatbot the same as you did in the original, it's a "pure" (i.e. not using anything in the unity engine, not a component, not hooked in to the game loop etc.) c# class with a constructor (which does nothing) so I can "create" a chatbot object to work with. This is done in the start function of the component. Basically that entire first block of code was there so I can do line 49 of your original code without compiler errors about a missing chatbot class.
     
  12. DigitalAdam

    DigitalAdam

    Joined:
    Jul 18, 2007
    Posts:
    1,209
    I mean this:
    Code (csharp):
    1.  
    2. using System.Linq;
    3.  
    4. public class Chatbot
    5. {
    6.     public Chatbot()
    7.     {
    8.  
    9.     }
    10.  
    11.     public string getOutput(string s)
    12.     {
    13.         return new string(s.ToCharArray().Reverse().ToArray());
    14.     }
    15. }
    16.  
    17.  
    But now I understand what you mean by "pure". Thanks again!