I'm currently designing a custom inventory in Unity. Although OnClick method works properly for each slot, the OnHovered one does not go the same way. The latter was added through an EventTrigger component.
https://i.imgur.com/hxQGzl1.png
OnHovered can be found in InventorySlot script linked to the button, it only contains a one-line print, but, which prints nothing actually. Besides, I specify that there's an EventSystem in the scene which includes the Standalone Input Module.
public void OnHovered()
{
Debug.Log("HOVERED");
}
I know this is some very basic stuff but I'm unable to figure out what's the problem about, thank you!
I'm afraid simply adding the event trigger component isn't enough.
You have two options:
1. Have your inventory slot script derive from EventTrigger and implement the desired method.
2. Add the IPointerEnter interface implentation to your script and use the OnPointerEnter method.
Hope I was clear
Good luck
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).
I'm trying to make a restart button on top of a game over screen. But it seems that the button doesn't work. I've put it on the On Click() menu and it kept doing nothing when i clicked on it.
My code:
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
public class ButtonCodes:MonoBehaviour
{
public void RestartGame()
{
SceneManager.LoadScene(0);
}
}
Look into 4.6 UI Buttons.
Create the button in your scene, and in OnClick, drag the gameObject with your ButtonCodes into the target field (left), and choose RestartGame in the right, which will be an option under ButtonCodes.
This might be what you've already done.. if that's the case, try using some Debug.Log("Button was Clicked"); statements. If these show up, it's likely you haven't set up the Build settings to include any levels. (Unity does not add levels here just by pressing play - you must do this yourself)
Assumming there are no errors, the most likely reason it's not working is that you didn't specify any scenes in File/Build Settings (Ctrl+Shift+B)
https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager.LoadScene.html
That shows that you need to order your scenes in the Build Settings if you use the sceneBuildIndex. You could also use the second LoadScene that uses sceneName which may be more reliable if you constantly reorder scenes in Build Settings.
Also, if you haven't already, try using Debug.Log to make sure that that part of the code is actually being called.
try to put the name of the scene in the scenemanager and make sure your scene you gonna load is on your build settings
public void RestartGame()
{
SceneManager.LoadScene(//name of your scene);
}
1- Sometimes when i duplicate a button and use it with other functions, it doesn't work.
2- Another reason that i faced was when i use inherited class, it doesn't work many times too.
3- Sometimes you forget to add your "0" scene in to build setting as well.
Thank you all for answering. All of the things that you said is already been done and still, the button won't work. In the end, i solved the problem myself. I realized that my Canvas doesn't have an EventSystem that was an important thing for a button to work.
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.
I'm trying to swap "Scenes", the equivalent of levels in a game. I already know that Forms is not good for gaming, but what I'm making isn't so much a game as it is an interactive movie built out of some dialog options and animated .gifs.
I plan on building each "Scene" in a separate User Control, and then load up those User Controls onto the main form with a separate script that handles all of the scenes. In this separate script, I was going to add the "ChangeScene" method, so I could essentially trigger a scene to change once it finished, and have all scene changes in one script. I've run into two problems so far.
1: I can't seem to call anything from this Scene Handler script. I've been trying to use "Form1.SuspendLayout" and "Form1.ResumeLayout" to swap between Scenes smoothly, but I can't seem to call that, and then when I try to set a boolean in a Scene to true once the scene finishes, I can't actually check that bool from the Scene Handler script. How can I let this one script use the bools from each of the Scenes?
2: Can I call the "Form1.SuspendLayout" method from this Scene Handler script? So far, I was told I needed a reference to 'System.Windows.Forms.Control.SuspendLayout()', although I don't know how to reference that. It's not a namespace or assembly, so how do I reference it?
Sorry if this question seems like a simple mistake. I'm new to Windows Forms and not too well experienced with C#, so any question I could find about this used terms too complicated for me to understand.
Scene Handler here: class SceneHandler :
{
public virtual UserControl changeScene(UserControl currentScene, UserControl newScene)
{
Form1.SuspendLayout();
currentScene.Visible = false;
currentScene.Dock = DockStyle.None;
newScene.Visible = true;
newScene.Dock = DockStyle.Fill;
return newScene; //use "this.SuspendLayout" and "ResumeLayout"
}
}
Forget SuspendLayout.
Load all the UCs upfront but hidden.
Don't worry about performance before you run into problems!
Put all methods that involve more than one UC in the Form as public methods.
Put a public reference to your mainform in each UC and set it right after loading the UC.
Now each control can call mainform.someMethod().
Feel free to ask for more advice and help!