First of all I´m still new to Unity so this might be easy for the Pros here. But I could not find a solution yet. I try to create a pulldown menu with the Unity GUI. 1st option selected , other options only visible on change. Could somebody give me a little hint ? Thanks Marc
You need a label, a button, a selection grid and a ScrollView The label will display the name of the selected item. The button activates the drop-down. This can be done simply with a flag like Code (csharp): if(Button(icon)) { showDropdown=true; lastSelection=currentGridSelection; } Then the drop-down consists of the selection grid with the columns parameter set to 1 inside a ScrollView. Put the code for that in an Code (csharp): if(showDropdown){ //code for Scrollview SelectionGrid BeginScrollView(..); currentSelection=SelectionGrid(...); if(currentSelection!=lastSelection) showDropdown=false; EndScrollView(); } This is just one way to do it. You could use a bunch of buttons instead of a SelectionGrid.
Hi Jeff, Thanks for the quick tips. Tried it out but i get several errors. Hope you can help again :wink: First if I use selectionGrid i get the following error (That happens for some reason always if i try to use SelectionGrid) error BCE0023: No appropriate version of 'UnityEngine.GUI.SelectionGrid' for the argument list '(UnityEngine.Rect, int, (String), int, int)' was found. Thats how my code looks so far: Code (csharp): // For dropdownselect var showDropdown= false; var dropdownGridInt : int = 0; var dropdownStrings : String[] = ["drop1", "drop 2"]; var scrollViewVector : Vector2 = Vector2.zero; function OnGUI () { if(GUI.Button (Rect (100, 50, 150, 30), "Select")) { showDropdown = true; lastSelection = currentGridSelection; } if(showDropdown){ //code for Scrollview SelectionGrid GUI.BeginScrollView (Rect (100, 50, 150, 10), scrollViewVector, Rect (0, 0, 10, 10)); currentSelection= GUI.SelectionGrid (Rect (100, 50, 150, 10), dropdownGridInt, dropdownStrings, 1, 1); if(currentSelection!=lastSelection) showDropdown=false; GUI.EndScrollView(); } } Copy/Pasted the code for the SelectionGrid from the GUI Basics, But if i try it i get an error. Also i get Unknown identifier: 'currentGridSelection'. so how do I init that upfront? lastSelection = currentGridSelection; As I said I´m still a newbie, so please be patient. Thanks again.
Here is working code. Not too much different. You needed to assign the Vector2 returned from the Scrollview to scrollViewVector. Also dropdownGridInt and currentSelection were the same so I replaced all instances of currentSelection with dropdownGridInt. Also adjusted the sized of things a bit. You had them all drawn on top of each other and didn't give the scrollview much space to render in. I've been converting a lot of my GUI to use the GUILayout class, then you don't have to worry about the Rects for the internal structures. Code (csharp): // For dropdownselect var showDropdown= false; var dropdownGridInt : int = 0; private var dropdownStrings : String[] = ["drop1", "drop 2","drop3", "drop 4","drop5", "drop 6"]; private var scrollViewVector : Vector2 = Vector2.zero; private var lastSelection = 0; function OnGUI () { if(GUI.Button (Rect (100, 50, 200, 30), "Select Stuff - Current Selection: " + dropdownGridInt)) { showDropdown = !showDropdown; lastSelection = dropdownGridInt; } if(showDropdown){ //code for Scrollview SelectionGrid scrollViewVector=GUI.BeginScrollView (Rect (120, 80, 200, 100), scrollViewVector, Rect (0, 0, 180, 300),false,true); dropdownGridInt= GUI.SelectionGrid (Rect (0, 0, 170, 200), dropdownGridInt, dropdownStrings, 1); if(dropdownGridInt!=lastSelection) showDropdown=false; GUI.EndScrollView(); } }
Just a plug for GUI.Layout -- I use it for everything and I prefer it. In a word, it's the best thing to use for any complex window, etc., that has multiple elements. It all flows into the area or window rect you define first and it's much easier to do. Vertical and Horizontal groups and flexible spaces are your friends! To save typing, add: Code (csharp): import UnityEngine.GUILayout; to the beginning of your .js scripts and then you can just say: Code (csharp): BeginVertical(); etc.
Thanks a lot fo your help the suggestions. It is a great support. And I m learnig a lot thru this. Jeff, thanks to code you posted works fine. Regarding GUILayout i just started to check it out you are right it is very convinient. Two more question to that: 1. How can I say draw that group at exactly this position? Lets say I have a psd mockup want to rebuild it using GUILayout. eg. : Draw MyButtonGroup at positon 200,150. 2. the evaluation of the events (button pressed , selection grid etc. goes still in the OnGUI (), or better in an Update() ?
Here's a dropdown selection control I wrote a while back. It sounds like what you want. You can reassign the button items GUIStyle to suit your look and feel. Code (csharp): using UnityEngine; using System.Collections; using System.Collections.Generic; public class NewBehaviourScript : MonoBehaviour { private Rect DropDownRect; private Vector2 ListScrollPos; private bool DropdownVisible; private int SelectedListItem; public class GuiListItem //The class that contains our list items { public bool Selected; public string Name; public GuiListItem(bool mSelected, string mName) { Selected = mSelected; Name = mName; } public GuiListItem(string mName) { Selected = false; Name = mName; } public void enable() { Selected = true; } public void disable() { Selected = false; } } private List<GuiListItem> MyListOfStuff; //Declare our list of stuff void Start() { DropDownRect = new Rect(100, 300, 160, 28);//We need to manually position our list, because the dropdown will appear over other controls DropdownVisible = false; SelectedListItem = -1; MyListOfStuff = new List<GuiListItem>(); //Initialize our list of stuff for (int i = 0; i < 32; i++)//Fill it with some stuff { MyListOfStuff.Add(new GuiListItem("Item Number" + i.ToString())); } } void OnGUI() { //Show the dropdown list if required (make sure any controls that should appear behind the list are before this block) if (DropdownVisible) { GUILayout.BeginArea(new Rect(DropDownRect.left, DropDownRect.top + DropDownRect.height, 160, 256), "", "box"); ListScrollPos = GUILayout.BeginScrollView(ListScrollPos, false, true); GUILayout.BeginVertical(GUILayout.Width(120)); for (int i = 0; i < MyListOfStuff.Count; i++) { if (!MyListOfStuff[i].Selected GUILayout.Button(MyListOfStuff[i].Name)) { if (SelectedListItem != -1) MyListOfStuff[SelectedListItem].disable();//Turn off the previously selected item SelectedListItem = i;//Set the index for our currrently selected item MyListOfStuff[SelectedListItem].enable();//Turn on the item we clicked DropdownVisible = false; //Hide the list } } GUILayout.EndVertical(); GUILayout.EndScrollView(); GUILayout.EndArea(); } //Draw the dropdown control GUILayout.BeginArea(DropDownRect, "", "box"); GUILayout.BeginHorizontal(); string SelectedItemCaption = (SelectedListItem == -1) ? "Select an item..." : MyListOfStuff[SelectedListItem].Name; string ButtonText = (DropdownVisible) ? "<<" : ">>"; GUILayout.TextField(SelectedItemCaption); DropdownVisible = GUILayout.Toggle(DropdownVisible, ButtonText, "button", GUILayout.Width(32), GUILayout.Height(20)); GUILayout.EndHorizontal(); GUILayout.EndArea(); } }
Really you don't want to try to reproduce a comp pixel for pixel. The beauty of GUILayout is that it will adjust things for you if something like the length of text in a label changes. Comps are great for getting a feeling for how it can be. And if you need a specific element to be a specific size, you can force it using GUILayout.Height and GUILayout.Width parameters in your element calls. But that I love about using it, compared to manually laying out windows in Flash, say, is I don't have to calculate exact pixel dimensions and offsets for everything! Button actions are often taken in the button block, since they are constructed as if (Button ()) { } For other controls, you can have an if (GUI.changed) { } block in OnGUI to evaluate new values and act on them. If you are trying to to abstract your control system from your display layer completely, then you would want your GUI to set flags and then have Update or even other scripts read those flags and perform the actual evaluations and actions. That is good programming practice, but it can be overkill, too, depend on how complex your GUI system is overall and the types of events you are influencing with your GUI. For example, GUI elements that are deeply integrated into your gameplay should probably abstract the display from the action. A save window or alert box can probably do its own work directly.
Hi guys, thanks a lot for all your tips. Really great help! Shaun thanks a lot for that code. That is really a nice solution. Will try to implement that in my menu.
I think it is nice to be able to click the item to get the drop down to appear, not just the ">>" arrows. To do this, change the GUILayout.TextField line of shaun's code to: Code (csharp): DropdownVisible = GUILayout.Toggle(DropdownVisible, SelectedItemCaption, "textField");
After using this for a bit, I realized that if there were less than 10 items, i.e. no need to scroll vertically, a horizontal scroll bar showed. I fixed this by removing the scroll bar when appropriate. Also this looks nicer, since the buttons fill to the sides if they don't need to scroll vertically: Code (csharp): if (DropdownVisible) { GUILayout.BeginArea(new Rect(DropDownRect.left, DropDownRect.top + DropDownRect.height, 160, 256), "", "box"); if (MyListOfStuff.Count > 10) { ListScrollPos = GUILayout.BeginScrollView(ListScrollPos, false, true); GUILayout.BeginVertical(GUILayout.Width(120)); } else { GUILayout.BeginVertical(); } for (int i = 0; i < MyListOfStuff.Count; i++) { if (!MyListOfStuff[i].Selected GUILayout.Button(MyListOfStuff[i].Name)) { if (SelectedListItem != -1) MyListOfStuff[SelectedListItem].disable();//Turn off the previously selected item SelectedListItem = i;//Set the index for our currrently selected item MyListOfStuff[SelectedListItem].enable();//Turn on the item we clicked DropdownVisible = false; //Hide the list } } GUILayout.EndVertical(); if (MyListOfStuff.Count > 10) { GUILayout.EndScrollView(); } GUILayout.EndArea(); }
how would i assign an action to each of the items in the drop down. ive got a script to link to a file from a button, but how would i assign this script to the dropdown items?
You can use a "switch" statement to take different actions depending on the value of the selected item variable:- Code (csharp): switch (selectedItem) { case 0: // Action for button 0 break; case 1: // Action for button 1 break; // etc... }
Hey Andeeee -- I used the case code you posted above for my dropdown list. It works great, except that the action keeps repeating. In the case below, the action is to launch a webpage, but the web page keeps launching until a different item is selected then that one repeats. Something I'm missing? Thanks! Code (csharp): switch (dropdownGridInt) { case 0: dropdownGridString = "Overview"; Application.OpenURL ("http://baybridgeinfo.org/projects/corridor-overview"); break;
In that case, you need to store the selected button index on each OnGUI call. Then, on the next call, check to see if the new selected button is the same as the old one. Only if they're different do you enter the switch statement:- Code (csharp): var lastSelectedItem: int; function OnGUI() { selectedItem = ... // as before... if (selectedItem != lastSelectedItem { switch (...) { // as before } lastSelectedItem = selectedItem; } }
I just mean that the switch statement itself has the same structure as in the previous example and doesn't need to be altered to make this work.
im having trouble figuring this out. Here is my script - Code (csharp): // For dropdownselect var showDropdown= false; var dropdownGridInt : int = 0; private var dropdownStrings : String[] = ["MTCL", "GOOGLE","drop3", "drop 4","drop5", "drop 6", "drop 7", "drop 8", "drop 9", "drop 10"]; private var scrollViewVector : Vector2 = Vector2.zero; private var lastSelection = 0; function OnGUI () { if(GUI.Button (Rect(10, Screen.height/7, Screen.width/8, Screen.height/20), "Information")) { showDropdown = !showDropdown; lastSelection = dropdownGridInt; } if(showDropdown){ //code for Scrollview SelectionGrid scrollViewVector=GUI.BeginScrollView (Rect (10, Screen.height/5, Screen.width/8, Screen.height/14), scrollViewVector, Rect (0, 0, Screen.width/12, 300),false,true); dropdownGridInt= GUI.SelectionGrid (Rect (0, 0, Screen.width/10, Screen.height/3), dropdownGridInt, dropdownStrings, 1); if(dropdownGridInt!=lastSelection) showDropdown=true; GUI.EndScrollView(); } var lastSelectedItem: int; function OnGUI(); { selectedItem = dropdownGridInt if (selectedItem != lastSelectedItem { switch (dropdownGridInt) { case 0: dropdownGridString = "MTCL"; Application.OpenURL ("www.mtcl.net"); break; if (selectedItem != lastSelectedItem { switch (dropdownGridInt) { case 0: dropdownGridString = "GOOGLE"; Application.OpenURL ("www.google.co.uk"); break; lastSelectedItem = selectedItem; } } it is coming up with the errors - and any ideas what is goin wrong? my brain is fried.
You've got a semicolon after the name of the OnGUI function. Also, you have defined OnGUI twice, which will also not work - you need to take the code out of one of the OnGUI functions and add it to the other one.
ive tried doin what you said, but i am getting more errors that i dont understand. Here is the script - Code (csharp): // For dropdownselect var showDropdown= false; var dropdownGridInt : int = 0; private var dropdownStrings : String[] = ["MTCL", "GOOGLE","drop3", "drop 4","drop5", "drop 6", "drop 7", "drop 8", "drop 9", "drop 10"]; private var scrollViewVector : Vector2 = Vector2.zero; private var lastSelection = 0; function OnGUI () { if(GUI.Button (Rect(10, Screen.height/7, Screen.width/8, Screen.height/20), "Information")) showDropdown = !showDropdown; lastSelection = dropdownGridInt; var lastSelectedItem: int; selectedItem = dropdownGridInt ; if (selectedItem != lastSelectedItem switch (dropdownGridInt); case 0: dropdownGridString = "MTCL"; Application.OpenURL ("www.mtcl.net"); break; if (selectedItem != lastSelectedItem switch (dropdownGridInt); case 0: dropdownGridString = "GOOGLE"; Application.OpenURL ("www.google.co.uk"); break; lastSelectedItem = selectedItem; } if(showDropdown){ //code for Scrollview SelectionGrid scrollViewVector=GUI.BeginScrollView (Rect (10, Screen.height/5, Screen.width/8, Screen.height/14), scrollViewVector, Rect (0, 0, Screen.width/12, 300),false,true); dropdownGridInt= GUI.SelectionGrid (Rect (0, 0, Screen.width/10, Screen.height/3), dropdownGridInt, dropdownStrings, 1); if(dropdownGridInt!=lastSelection) showDropdown=true; GUI.EndScrollView(); } im getting these errors - and and
You don't appear to understand the basic syntax of these statements. More or less every statement (apart from single-line statements) has the following structure:- Code (csharp): if (...) { // Code } while (...) { // Code } You really need to get your head around the basic language constructs before attempting anything more complicated. It's all but impossible to write code by making well-meaning changes to an existing script in the hope that they will work.
While I haven't read the whole topic, I just wanted to share my own pulldown menu I've build with little help from the code I've found here. Code (csharp): private var dropdown = true; private var dropdownAdjustWindow = false; private var currentScene; private var scene; var scenes : String[]; var sceneButtonNames : String[]; function Awake () { if (GameObject.Find("Level (Original)")) { currentScene = 0; } else { currentScene = 1; } scene = currentScene; } private var windowRect = Rect(20,20,200,0); function OnGUI () { // Make a popup window windowRect = GUILayout.Window(0, windowRect, DoControlsWindow, "Options"); // The window can be dragged around by the users - make sure that it doesn't go offscreen. windowRect.x = Mathf.Clamp(windowRect.x, 0.0, Screen.width - windowRect.width); windowRect.y = Mathf.Clamp(windowRect.y, 0.0, Screen.height - windowRect.height); } // Make the contents of the window function DoControlsWindow (windowID : int) { // Make the button or area to activate the dropdown dropdown = GUI.Toggle(Rect(0,0,16,16), dropdown, "");//, "label"); // Make the window be draggable in the top 20 pixels. GUI.DragWindow(Rect(0,0, System.Decimal.MaxValue, 20)); // Adjust the droped down window if (!dropdown) { GUILayout.Label("Click above to see the options"); if (dropdownAdjustWindow) { windowRect = Rect(windowRect.xMin,windowRect.yMin,200,0); dropdownAdjustWindow = false; } } else { dropdownAdjustWindow = true; GUILayout.Label("Select a scene to load..."); scene = GUILayout.Toolbar(scene, sceneButtonNames); if (GUI.changed scene != currentScene) { Application.LoadLevel(scenes[scene]); } } } This is mostly based on a script (CameraFocus.js) from 2D Platformer with our beloved Lerpz, but heavily modified. It will draw a window and a toggle button on the top which will "minimize" it, or pull up and down. I'm missing the proper word here. Anyway, thanks guys for sharing code!