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!
using UnityEngine;
using System.Collections;
public class ChatWindowExample2 : MonoBehaviour
{
private Chatbot bot;
public GUISkin myskin;
private string messBox = "", messBoxAnswer = "", ask = "", user = "Me";
private Rect windowRect;
// Use this for initialization
void Start ()
{
bot = new Chatbot ();
}
void OnGUI ()
{
GUI.skin = myskin;
// Width of the text box; This formula sets the width according to the screen size
float W = (700 * Screen.height) / 800;
// Height of the text box; This formula adjust the height according to the screen size
float H = (210 * Screen.height) / 600;
if (Screen.width < Screen.height) {
windowRect = new Rect (0, Screen.height - H, Screen.width, H);
} else {
windowRect = new Rect (Screen.width / 2 - W / 2, Screen.height - H, W, H);
}
windowRect = GUI.Window (2, windowRect, windowFunc, "Chat");
}
private void windowFunc (int id)
{
// Question User
GUILayout.Label (user + ": " + messBox);
// Response bot
GUILayout.Label ("BOT: " + messBoxAnswer);
//Skip a few lines to the box question becomes more below.
//GUILayout.Label ("\n");
//
GUILayout.BeginHorizontal ();
// Where the player put the text
ask = GUILayout.TextField (ask);
//=================================================
if (GUILayout.Button ("Send", GUILayout.Width (75))) {
messBox = ask;
// Response Bot AIML
var answer = bot.getOutput (ask);
// Response BotAIml in the Chat window
messBoxAnswer = answer;
ask = "";
}
//==================================================
GUILayout.EndHorizontal ();
}//close windowFunc
}
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.
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.
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.
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?
my chatbot replacement… I assume yours does something a little more useful, this one just reverses the text string it’s given
using System.Linq;
public class Chatbot
{
public Chatbot()
{
}
public string getOutput(string s)
{
return new string(s.ToCharArray().Reverse().ToArray());
}
}
the script the button is going to be using
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class ButtonPushScript : MonoBehaviour
{
private Chatbot bot;
public Text myOutputTextField;
public InputField myInputField;
void Start()
{
bot = new Chatbot();
}
public void FunctionToCallWhenAskButtonIsPushed()
{
myOutputTextField.text = bot.getOutput(myInputField.text);
}
}
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
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?
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.
using System.Linq;
public class Chatbot
{
public Chatbot()
{
}
public string getOutput(string s)
{
return new string(s.ToCharArray().Reverse().ToArray());
}
}
But now I understand what you mean by “pure”. Thanks again!