I am creating a small application which is instantiated by a client. In my application I have 2 classes MessageQueueSingleton.cs and DataObject.cs
MessageQueueSingleton is a singleton class which contains a static Dictionary of the objects of DataObject class. MessageQueueSingleton has some methods which will manipulate the attributes of the DataObject class according to the instructions from the client.
My problem is I also need a Unity GUI which can call few methods of MessageQueueSingleton, i.e. if I press a button on UI, a method will be called from the MessageQueueSingleton.
I am new to unity programming and I tried to look the examples which shows how to connect scripts to buttons, but I still can't see my method in the "Inspector" onClick() section. I am using Unity 5.5.1f1
Any small example or link describing the process to do it would be helpful.
Thanks.
On your GameObject with a Button component you can add a script component with the following code to set up a listener and method for that button:
void Start() {
var button = GameObject.Find("GameObjectWithMyButton").GetComponent<Button>();
button.onClick.AddListener(MyMethod);
}
void MyMethod() {
// Do something when button is clicked.
}
And if you want to drag & select it in the inspector, make sure the methods you want to select in the inspector button onclick GUI thing are public methods! To make the public methods of a script shows up in the Inspector Button Onclick GUI you place the script on a GameObject then drag that object to the button onclick GUI and select them from the dropdown. They won't show unless they're public methods. (public void DoSomething() { })
Related
I'm trying to execute a function using a Button in Unity, but the dropdown menu for the funtions only shows me the default functions that all GameObjects have
I have created an empty GameObject that has the HighscoreList script and draged this object onto the onClick() Object selector, but I can't find any of the functions that I created
What the editor shows me:
The function im trying to call:
public void AddItem(int score, string name)
{
Node n = new Node(new HighscoreData(score, name));
start = start.addItem(n);
}
Through unity event you can only have functions with a maximum of 1 parameter.
If the script does not compile errors and inherits MonoBehavior.
This reason may be caused by directly mounting the script to the OnClick event. However, the OnClick event should use the GameObject containing the script.
Here are relevant steps:
Mount the script on the parent object.
GameObject should be mounted on the OnClick event.
The results are as follows.
I'm looking for a way to add a dropdown box to the OnClick editor in the inspector (circled in the image below)
I would like the dropdown to be populated by a custom enum.
Is this possible at all or do I need to find another way to do this?
Goal:
Have an enum of audio clips and be able to assign a clip to a button all from the inspector without having to go into the code.
Assuming you know how the editor and C# script interface with each other I would simply use:
public static bool DropdownButton(GUIContent content, FocusType focusType, params GUILayoutOption[] options);
More info can be found here: https://docs.unity3d.com/ScriptReference/EditorGUILayout.DropdownButton.html
It is currently not supported and is not that easy to code yourself. It would require some deep hacks into the source code of UnityEventDrawer and UnityEventBase and kind of reproducing the entire UnityEventDrawer (source is avalable though ...)
However there is a very simple workaround (at least if every Button shall playback exactly one sound)
Have a separate component like
[RequireComponent(typeof(Button))]
public class PlayASound : MonoBehaviour
{
// reference via inspector
[SerializeField] private AudioSelector _audioSelector;
// your enum type here
public AudioMessageType MessageType;
public void Play()
{
_audioSelector.PublishAudioMesssage(MessageType);
}
private Button _button;
private void Awake()
{
_button = GetComponent<Button>();
if (!_button)
{
Debug.LogError("No Button found on this GameObject!", this);
return;
}
_button.onClick.AddListener(Play);
}
// Just to to be sure
// usually the button should be destroyed along with this component
// anyway ... but you never know ;)
private void OnDestroy()
{
_button.onClick.RemoveListener(Play);
}
}
attach it to the same GameObject as the Button component, select the according enum value there, done. The Listener to onClick will not appear in the Inspector but will be added on runtime.
If you prefer to add it manually (I sometimes prefer to have it visible) then simply remove the Awake and OnDestroy and rather drag it in manually as usual and select the Play method.
I'm developing a game and I've reached a stage in which I need to dynamically create a list of buttons.
My approach was to create a scroll view and then add the buttons through scripting.
I've already created the button prefab. This button purpose is to open a specific link outside the application, so I created the button prefab with two text components: One saying "Show Path" which is what I want the buttons to show, and the other text component is the link I need to open, which isn't visible to the user.
I'm running into several problems:
I need to create the buttons as I am going through a list of user data. I display the data right beside the button, in another scroll view, correctly. However, only one button is created.
I'm unable to access the prefab link text component to change it to the link I need to open.
Thank you for your time!
What I'd recommend you do is create your own class to handle this, so it's easier to visualise in the inspector.
[System.Serializable]
public class RelevantClassName
{
public string link = "http://defaultbackuplink";
public string text = "Default content";
[Space]
public Transform button;
public Transform contentHolder;
}
And in a seperate class, you use this information to generate your scroll views and buttons:
public class UIController : MonoBehaviour
{
public List<RelevantClassName> contentToDisplay;
[Header("References"]
public Transform buttonParent;
public Transform contentParent;
public GameObject buttonPrefab;
public GameObject contentPrefab;
public void DisplayUI()
{
foreach(RelevantClassName content in contentToDisplay)
{
content.contentHolder = Instantiate(contentPrefab, contentParent);
content.button = Instantiate(buttonPrefab, buttonParent);
// And here you can run any custom changes, for example finding a text
// component on the content holder and changing the description:
content.contentHolder.GetComponent<Text>().text = content.text;
}
}
Naturally I heavily advise you use a pooling system, and if you're planning to access a component, cache it in that class.
Hope this helps!
I'm Working on a game, and i want to create a mute button. So i wrote a script for that and i attach this script into a gameObject that don't destroy on load.
I link the script with a UI Button present in a main menu. This UI button is destroy when i'm changing scenes.
when i start my game, and i click on the button, the audio turns off, and when i click back, it turns on.
But when i change to another scene, and i go back to the main menu, my script doesn't have the UI Button attach to it. so when i touch the button the audio doesn't change is behavior
I would like to know if it's possible to maintain the link between the UI Button and the script (attach to a normal GameObject), even if the UI Button is destroyed?
i tried this:
ButtonGameObject = GameObject.Find("UI Button");
but it doesn't work.
How can i fix that?
Thanks a lot.
There are many ways to work around this, but here's one:
Step 1: If you haven't already done so, implement a weak singleton pattern on your mute script (let's call it MuteScript.cs for now).
private static MuteScript singleton {get; private set;}
private void Awake() {
if (singleton == null) singleton = this;
[whatever other stuff you were already doing in Awake()]
}
public static void ToggleMute(Graphic graphic)
{
singleton._ToggleMute(graphic);
}
private void _ToggleMute(Graphic graphic)
{
[whatever code you were running in your original mute method]
}
Step 2: Attach a simple script to your UI button:
public class MuteButton: MonoBehaviour
{
Graphic myGraphic;
private void Awake() {
myGraphic = GetComponent<Graphic>();
}
public void OnClick() {
MuteScript.ToggleMute(myGraphic);
//I assume you want to do something like change the colour of the button when
//the player toggles it. Passing the Graphic to the MuteScript is the easiest
//way of doing this. If you really want to keep your code clean, though,
//I recommend expanding the MuteButton class with methods to take care of
//the UI side of things.
}
}
Step 3: In Unity Editor, setup your button to call its own OnClick() method, not the MuteScript method.
-
Now when you click the button, it will call the static MuteScript.ToggleMute(), which accesses the static-cached singleton reference, which in turn points back to your original object.
Singletons and static accessors are great for efficiency in Unity because they save you from having to call expensive search functions like FindObjectsOfType(). The only gotcha is that you have to be careful about not having multiple copies of a singleton-class object lying around, especially when using DontDestroyOnLoad().
So a better approach rather than having a script search and grab the component is to use a PlayerPrefs class from Unity. Essentially, it will hold onto all important aspects of the game and auto fill information.
This is a great tool for a lot of user customization aspects of a game. When using this, have a script (sceneController would be a good name) that will run when the scene starts (create a blank object at 0,0,0) and then under void Start() have the script grab the mute/unmute button: GameObject.Find("MuteButton") or (my favorite) give it a tag called MuteButton and run: GameOject.FindWithTag("MuteButton"). Also once you get a link to the button, add a listener to it for when the button is pressed.
Also store the sound manager in a gameController that will be passed throughout the game. This would control the soundManager and have access to that. So sceneManager will also need a reference to gameManager.
Using a script that is just for player preferences (a controller if you will) is a better way to organize and contain any preferences for the users. Just better clarity and separation.
Example
SceneController Object Script
class SceneController {
GameObject muteButton;
void Start() {
muteButton = GameObject.FindWithTag("muteButton");
muteButton.AddListener(muteButtonCheck);
}
void muteButtonClick() {
if (PlayerPrefs.GetInt("playerMute")) {
// If 1 (on)
// Set sound off
PlayerPref.SetInt("playerMute", 0);
} else {
// It's 0 (off)
// Set sound on
PlayerPrefs.SetInt("playerMute", 1);
}
}
}
void OnMouseDown() {
SceneManager.LoadScene ("Scene2");
}
I have tried every conceivable method. The method posted has worked for me using GameObjects with colliders. Instead, this time I am using a button on a 2D canvas. It does not work in this context.
How do I load a new scene using a button in a canvas? I have tried so many different things. This should be simple.
Thanks for any advice.
Here (link: Unity page) you can find a video tutorial how to use Button on canvas in UnityGUI. It's for Unity 4.6 but its really simillar to newest (5.3.1).
It's quite simple. U can make a script with public method e.g
public void LoadScene2()
{
SceneManager.LoadScene ("Scene2");
}
Attach this script to some GameObject e.g Controller. And add event in Button inspector.
In my opinion there is a better solution for the one shown by #Paweł Marecki
I use this in my projects.
OK so you will simply create a script called ButtonManager and inside it you can make a method like this
public void ChangeToScene(string sceneName)
{
Application.LoadLevel(sceneName);
OR
SceneManager.LoadScene(sceneName);
}
Now you have your canvas button, you will select it and look for "Event Trigger"
(i got this image from google to help) add a new mouse down event.
Create an empty GameObject on your Scene, name it "ButtonManager" and drag it onto the event box.
Now you need to click that dropDown list and find your "ChangeToScene" method.
You will see that an editor field appears below, type your desired scene name and hit play :P
This way you will always use this script when you want to change scenes.
You can add other methods and add functionality, but the beautiful part is that you dont need to create a method each time the name of the scene changes.