I have three buttons, when you tap one button, a panel with a text appear.
The problem is when I attached the script, nothing happens.
The "click" is registered but the the panel never appears.
My script is attached to each of the button and is something like this:
public GameObject panel; //i use to put the panel in unity
bool selected = false;
void Start () {
panel.SetActive(false);
}
void OnSelect() {
selected = !selected;
panel.SetActive(true);
}
I probably have to do something else with the panel but I can't figure it out.
Do it like this:
(1) Add the canvas to your project
(2) BIG TIP - be sure to select Scale with screen size.
That's the only one you ever use. Unity accidentally set the wrong default there, they have not fixed it yet.
(3) In your Canvas, add a BUTTON Make it say perhaps "Test"
(3) In your Canvas, add another BUTTON Make it say perhaps "Another Test"
(4) Make a script something like this...
public class MainScreen:MonoBehaviour
{
public void UserClickedTest()
{
Debug.Log("test..");
}
public void UserClickedAnotherTest()
{
Debug.Log("another test..");
}
}
(5) put ONE copy of that script on ANY object you like. You can put it on your camera, on the canvas, or anywhere else that makes sense
For now let's say you put it on your CAMERA object, for example.
(6) Click on the button "Test" .....
And do this ...
click the PLUS button under OnClick
you see the slot that says "_main" in this example. DRAG your CAMERA item from HEIRARCHY, to that slot
Using the drop down menu:
select the "UserClickedTest()" function ...
good eh?
Now for the other button, do the same but select the "UserClickedAnotherTest()" function.
You're done! Run and test!
You can't use the OnSelect system unless you use ISelectHandler and more stuff: it is difficult for beginners. I strongly recommend the OP masters the simpler technique I explain here. Enjoy!
Maybe you attached the script to the panel. If so, your scripts can not be executed as long as your GameObject is SetActive(false).
I hope I was able to help you.
Related
I'm having trouble assigning two Buttons to the Prefab after it is instantiated.
The buttons are in the scene and i don't know how to assign them.
Drag and Drop doesn't work of course. I'm aware of that.
When I make something like
btnnext = GameObject.Find("Next").GetComponent<Button>();
in the Start() function of the Prefabs script it doesn't work either.
Are there any other workarounds?
As #slowikowskiarkadiusz said GameObject.Find is not the best solution, because it's slow and error prone. But there is an easy solution.
On the script which is placed on the prefab make a public function, called AssignButton:
class ScriptOnPrefab : MonoBehaviour {
public void AssignButton(Button button) {
btnnext = button;
}
}
In the script where you instantite the prefab, you then link the buttons and assign them:
var instance = Instantiate(prefab);
var scriptOnPrefab = instance.GetComponent<ScriptOnPrefab>();
scriptOnPrefab.AssignButton(button);
Note: For this to work that the ScriptOnPrefab has to be on the root of the prefab, note on child objects.
Note: prefab is linked as a GameObject.
Note: If you link the prefab as ScriptOnPrefab you can skip the GetComponent step and immediatelly call the Assign method.
By 'doesn't work either' you mean that btnnext is null or you mean that .GetComponent<Button>() throws an exception? The first case would mean the object named "Next" that was found doesn't have a Button component on it. You can check if you're expecting it to have the Button component or maybe something slightly different. You could also have multiple objects named "Next" and the one you're getting is not the one you expect to get. The second case would mean that your object is most likely inactive. Find(string) doesn't search within inactive objects.
That being said - Find(string) is not reliable in any capacity and I would advice to avoid it (it's also terribly slow). Instead I would create a script to be placed on the object with the button. Inside of that script in the Awake() method I would assign the instance of the Button component to some kind of a public static field, so the other script can later pick it up (if you are dealing with two buttons it might be a list or two separate fields. Depends on your case I guess).
So I'm using the AttachToController script to attach a window floated on top of the controller - which works great. In the script that calls up the window, I figure out which hand pressed the controller's menu button and set the Handedness field appropriately (Left or Right). The problem I'm trying to solve is this: Let's say the user clicks on the right controller's menu button and then later on, the left menu button is clicked. The problem I'm experiencing is that even though I've altered the Handedness field, the window still appears attached to the right controller.
private void InteractionManager_InteractionSourcePressed(InteractionSourcePressedEventArgs args)
{
hand = args.state.source.handedness;
...
}
private void SetHandednessAndActivate(GameObject go)
{
AttachToController script = go.GetComponentInChildren<AttachToController>();
if (script != null)
{
script.Handedness = hand;
}
go.SetActive(true);
}
Just to be clear, if the user clicks the left controller menu button first, the window is always on the left and the same holds true for the right controller. What I want is for the window to move to whichever controller is used.
Instead of
script.Handedness = hand;
Use
script.ChangeHandedness(hand);
All the other bits are handled by the script.
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);
}
}
}
I currently work on Unity and using C# language.
By far, I need to do something (in smallest case, load another scene).
My question is, how to make this something happens after a few seconds I put the cursor on the area?
this is my code right now.
if (_newGameButton.Contains (Event.current.mousePosition)) {
Application.LoadLevel (1);
Destroy (this);
}
I want to add delay when _newGameButton actives. Right now, when I move my cursor over _newGameButton it'll load scene 1 immediately. I have tried many ways such as using Invoke and WaitForSeconds. None works. If the mistake is how I use it, how's the right way? Thank you so much for your help.
EDIT: This question is answered and I have another question in Activate and Deactivate Invoke function.
To make timers and delays in Unity, simply use Invoke
void Start()
{
Debug.Log("hello from Start.");
Invoke("Test", 3f);
}
private void Test()
{
Debug.Log("hello from 'Test'");
}
Also very handy is InvokeRepeating
Invoke("Test", 5f, 0.5f);
It's that easy.
In your case
if (_newGameButton.Contains (Event.current.mousePosition))
{
Invoke("YourSceneName");
}
private void ChangeScenes()
{
UnityEngine.SceneManagement.SceneManager.LoadScene("ScreenMain");
}
You MUST USE the scene name. Don't forget you MUST HAVE DRAGGED THE SCENE, TO YOUR SCENE LIST. Look at "Build Settings" "Scenes in Build".
Note
That's not really how you load scenes in Unity these days. They changed the syntax. it's more like this...
UnityEngine.SceneManagement.SceneManager.LoadScene("ScreenMain");
If you want to load asynchronously
AsyncOperation ao;
ao = UnityEngine.SceneManagement.SceneManager.LoadSceneAsync("SceneName");
while (!ao.isDone)
{
Debug.Log("loading " +ao.progress.ToString("f2"));
yield return null;
}
If you have any questions about scene loading, ask them separately as a new question. Note that you should almost certainly NOT do this "Destroy(this);".
Well ill help you understand something a bit bigger then just pausing cause it seems you are trying to create on OnClick event, nowadays its being used differently.
what you realy want to do is just create the SceneLoader script which can be a very general script such as the following,
using UnityEngine;
using UnityEngine.UI;
public class UIController : MonoBehaviour {
public int numOfSceneToLoad; // number of the scene from the build settings
public void LoadSceneNumber(numOfSceneToLoad){
UnityEngine.SceneManagement.SceneManager.LoadScene(numOfSceneToLoad);
}
}
and then you want to attach this script to your main UI Canvas/Holderplace, go to your button and at the bottom of the inspector you will see onClick(),
click on the + sign and then make the setup as follows, drag the Object you have attached this script to and put it under the "runtime" laber in that small onClick() window, then scroll and find this specific function we just created and in there you can modify the value of numOfSceneToLoad to the scene you want to load, and woilla you have a Dynamic script to load any scene you wish to.
on this note ill reffer you to some pretty amazing toturials made by unity that will teach you how to make a proper UI in unity5.
http://unity3d.com/learn/tutorials/topics/user-interface-ui/ui-button
From your description, it looks to me that your _newGameButton is set to inactive by default and you want it to active and user intractable after few delay.
For that you can create a script and keep reference of _newGameButton in it, something like this:
public GameObject _newGameButton;
and on an event say GameOver, implement like this:
void GameOver()
{
Invoke("EnableNewGameButtonAfterDelay", 5f);
}
void EnableNewGameButtonAfterDelay()
{
_newGameButton.SetActive(true);
// now this game object is active and user can click on it.
}
In this example i demonstrated that the game has been over and after 5 second delay user have new game button set to enable. [This code is not in executable form and just to give you an idea]
Hope this helps!
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.