Unity button hover animation plays when the scene starts, not when the mouse pointer is over the gameobject - c#

ive made a hoveron and hoveroff animation which when the mouse pointer is over the button (hovering) it slides the button out slightly to the left, and hover off the opposite animation where it slides back to its original position.
however it plays hoveron when the scene starts and i cant get hoveroff to play at all, anybody know a fix?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class hoverscript : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
public RectTransform NewGameMenuButton;
// Start is called before the first frame update
void Start()
{
NewGameMenuButton.GetComponent<Animator>().Play("Hover Off");
}
public void OnPointerEnter(PointerEventData eventData)
{
NewGameMenuButton.GetComponent<Animator>().Play("Hover On");
}
public void OnPointerExit(PointerEventData eventData)
{
NewGameMenuButton.GetComponent<Animator>().Play("Hover Off");
}
}

I hadn't dragged the button on the script.

Related

Unity - How to Interact With Objects Between UI and World Space

I am new to unity and want to make a card - board game. I want to be able to place a card on a particular tile on the board. However, my draggable script that is attached to my card seems to not interact with the world space tile (it will interact with other UI). The world space tile has a droppable script, that currently doesn't have any real functionality, but should at least output a message to the console when a user hover overs it with their cursor. It doesn't even do that. (Again, droppable works with other UI elements) I thought that maybe because when the user is selecting their cards from their hand, and the canvas is in render mode - screen space camera - that had an effect, so I wrote a script that changes the render mode of the canvas to world space and it still seems to not interact. I will attach as much as I can for a clearer explanation, but at this point all I wish is for the board or tile to be able to recognize the user is hovering over it with the cursor.
Any help or information is appreciated, I am trying to absorb as much knowledge as I can, so even if you don't have a solution, advice is useful!
Dropzone.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class Dropzone : MonoBehaviour, IDropHandler, IPointerEnterHandler, IPointerExitHandler
{
public void OnPointerEnter(PointerEventData eventData)
{
Debug.Log("OPEnt");
}
public void OnPointerExit(PointerEventData eventData)
{
Debug.Log("OPExt");
}
public void OnDrop(PointerEventData eventData)
{
Debug.Log("on drop " + gameObject.name);
}
}
Draggable.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class Draggable : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
Transform originalParent = null;
private RectTransform RectTransform;
private void Awake()
{
RectTransform = GetComponent<RectTransform>();
}
public void OnBeginDrag(PointerEventData eventData)
{
originalParent = this.transform.parent;
this.transform.SetParent(this.transform.root);
GetComponent<CanvasGroup>().blocksRaycasts = false;
this.transform.parent.gameObject.GetComponent<CameraRender>().ChangeState();
}
public void OnDrag(PointerEventData eventData)
{
RectTransform.anchoredPosition += eventData.delta;
}
public void OnEndDrag(PointerEventData eventData)
{
this.transform.parent.gameObject.GetComponent<CameraRender>().ChangeState();
this.transform.SetParent(originalParent);
GetComponent<CanvasGroup>().blocksRaycasts = true;
}
}
CameraRender.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraRender : MonoBehaviour
{
enum RenderModeStates { camera, overlay, world };
RenderModeStates m_RenderModeStates;
Canvas m_Canvas;
// Use this for initialization
public void Start()
{
m_Canvas = GetComponent<Canvas>();
}
// Update is called once per frame
public void Update()
{
//Press the space key to switch between render mode states
if (Input.GetKeyDown(KeyCode.Space))
{
ChangeState();
}
}
public void ChangeState()
{
switch (m_RenderModeStates)
{
case RenderModeStates.camera:
m_Canvas.renderMode = RenderMode.WorldSpace;
m_RenderModeStates = RenderModeStates.world;
break;
case RenderModeStates.world:
m_Canvas.renderMode = RenderMode.ScreenSpaceCamera;
m_RenderModeStates = RenderModeStates.camera;
break;
}
}
}
I have tried to add a script that transitions render modes from Screen Space to World Space, I have attached box colliders to the world space objects.
For non-UI 3D objects in order to receive the IPointerXYHandler etc messages you need
Collider on the according object(s)
a PhysicsRaycaster component attached to your Camera (and make sure the according Layers are selected as "Event Mask" in its Inspector)

I decided to keep both scenes loaded in the hierarchy since it's easier to reference variables between them. How can I restart then a new game?

In the Hierarchy I have two scenes when running the game first time.
The scene that contains all the gameplay objects all the objects are disabled.
The main menu scene objects are enabled.
Now this script is attached to the main menu and the function PlayGame is being called from a Play button On Click event :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class MainMenu : MonoBehaviour
{
public static bool sceneLoaded = false;
public void PlayGame()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
SceneManager.LoadScene(0, LoadSceneMode.Additive);
SceneManager.sceneLoaded += SceneManager_sceneLoaded;
}
private void SceneManager_sceneLoaded(Scene arg0, LoadSceneMode arg1)
{
sceneLoaded = true;
}
public void QuitGame()
{
Application.Quit();
}
}
And this script is attached to one active gameobject on the gameplay scene and all it does is to check if I'm in the main menu or not and then to decide if to setactive or not all the gameplay objects :
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
public class ActiveScene : MonoBehaviour
{
public GameObject gameData;
// Update is called once per frame
void Update()
{
if(MainMenu.sceneLoaded == true)
{
gameData.SetActive(true);
MainMenu.sceneLoaded = false;
}
if(BackToMainMenu.loadedMainMenuScene == true)
{
gameData.SetActive(false);
BackToMainMenu.loadedMainMenuScene = false;
}
}
}
This is a screenshot of the Hierarchy :
You can see that the GameObject name Active Scene in the top scene is enabled gameobject while all the other gameobjects are disabled. On this Active Scene I attached the script ActiveScene.
This way when I click the Play button a new game start and when I hit the escape key it's getting back to the main menu.
The problem is when I hit the escape key and then click the Play button again it will keep load to the Hierarchy the main menu scene over and over again.
And this is after few times I hit the escape key and then started a new game over again by clicking the Play button :
This is the script to return to the main menu using the escape key. The script is attached to the Game Manager object in the game scene :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class BackToMainMenu : MonoBehaviour
{
public static bool loadedMainMenuScene = false;
private void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
loadedMainMenuScene = true;
}
}
}
I want to keep both scenes in the Hierarchy all the time since it's easier then to reference between variables in both scenes.
When both scenes in the Hierarchy it's also easier to restart a new game by re loading the gameplay scene.
The problem is when restarting a new game I have to set the flag bool sceneLoaded to false but then next time since it's false it will load the main menu scene to the Hierarchy over and over again.

Unity Button dont want to close a canvas

Hello i made a canvas in unity.
when the player preses the Esc button a canvas opens
In the canvas i made a button when the player clicks on the button the
Canvas need to close but nothing happens when i press the button.
Can somebody help me with this problem?
The Canvas
using UnityEngine;
using System.Collections;
using System;
using UnityEngine.SceneManagement;
public class PauseMenu : MonoBehaviour
{
private Canvas PlayerPauseMenu;
// Use this for initialization
void Start()
{
PlayerPauseMenu = GetComponentInChildren<Canvas>();
}
// Update is called once per frame
void FixedUpdate()
{
HandleInput();
}
private void HandleInput()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
PlayerPauseMenu.enabled = true;
}
}
public void CloseCanvas()
{
PlayerPauseMenu.enabled = false;
}
}

Buttons in Unity, without using UI?

Is there a way in Unity to create a simple 2D button without using the UI layer. I have a game with a lot of buttons and I don't want to make the whole app in the UI. Some more controls are welcome too: switches, sliders etc.
PS. I saw NGUI and I don't like it so far. Anything else?
Is there a way in Unity to create a simple 2D button without using the
UI layer
You can use Sprite/Sprite Render as a Button.First Create a GameObject and attach EventSystem and StandaloneInputModule to it. Attach Physics2DRaycaster to the Camera, implement IPointerClickHandler and override OnPointerClick function. Create a 2D Sprite by going to GameObject->2D Object->Sprite then attach your script to the Sprite. Here is a complete code to do that:
using UnityEngine;
using UnityEngine.EventSystems;
using System.Collections;
public class SPRITEBUTTON: MonoBehaviour, IPointerClickHandler,
IPointerDownHandler, IPointerEnterHandler,
IPointerUpHandler, IPointerExitHandler
{
void Start()
{
//Attach Physics2DRaycaster to the Camera
Camera.main.gameObject.AddComponent<Physics2DRaycaster>();
addEventSystem();
}
public void OnPointerClick(PointerEventData eventData)
{
Debug.Log("Mouse Clicked!");
}
public void OnPointerDown(PointerEventData eventData)
{
Debug.Log("Mouse Down!");
}
public void OnPointerEnter(PointerEventData eventData)
{
Debug.Log("Mouse Enter!");
}
public void OnPointerUp(PointerEventData eventData)
{
Debug.Log("Mouse Up!");
}
public void OnPointerExit(PointerEventData eventData)
{
Debug.Log("Mouse Exit!");
}
//Add Event System to the Camera
void addEventSystem()
{
GameObject eventSystem = null;
GameObject tempObj = GameObject.Find("EventSystem");
if (tempObj == null)
{
eventSystem = new GameObject("EventSystem");
eventSystem.AddComponent<EventSystem>();
eventSystem.AddComponent<StandaloneInputModule>();
}
else
{
if ((tempObj.GetComponent<EventSystem>()) == null)
{
tempObj.AddComponent<EventSystem>();
}
if ((tempObj.GetComponent<StandaloneInputModule>()) == null)
{
tempObj.AddComponent<StandaloneInputModule>();
}
}
}
}
EDIT:
If this is a 3D GameObject/Mesh, then you need to add a simple collider to it. If it is just Sprite then you must add a 2D collider to the sprite.
Another approach that is even simpler, is to just add a BoxCollider2D component, then add the following methods to the a new componenent, say UIButton, where you will to perform the button actions :
void OnMouseOver()
void OnMouseDown()
void OnMouseUp()
This avoids the use of an EventSystem, StandaloneInputModule and Physics2DRaycaster.
Example :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class UIButton : MonoBehaviour {
public Sprite regular;
public Sprite mouseOver;
public Sprite mouseClicked;
public TextMeshPro buttonText;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
private void OnMouseDown()
{
}
private void OnMouseEnter()
{
}
private void OnMouseExit()
{
}
private void OnMouseUpAsButton()
{
}
}
Tested in unity 2018.1. One difference I initially noticed to this and the above approach is that the right mouse button click is not detected in this model, but is detected in the EventSystemModel.

UI Canvas Start - Quit Game

I have 2 Canvas UIs (Start and Exit) on the home screen of my game. I want to add 1 script that does the following:
When the UI Image Play is clicked
public void NextLevel(int level)
{
Score.Inicializar();
Application.LoadLevel (1);
}
When the UI Image Exit is clicked
Application.Quit ();
C# if possible.
Add this script to your Play image:
using UnityEngine;
using UnityEngine.EventSystems;
//using UnityEngine.SceneManagement; // uncomment this line in case you wanna use SceneManager
public class HandleClickOnPlayImage : MonoBehaviour, IPointerClickHandler {
int level = 1; // I'm assuming you're setting this value somehow in your application
public void OnPointerClick (PointerEventData eventData)
{
Score.Inicializar();
Application.LoadLevel (level);
// SceneManager.LoadScene (level); // <-- use this method instead for loading scenes
}
}
And add this script to your Exit image:
using UnityEngine;
using UnityEngine.EventSystems;
public class HandleClickOnExitImage : MonoBehaviour, IPointerClickHandler {
public void OnPointerClick (PointerEventData eventData)
{
Application.Quit();
}
}
And finally make sure no other ui blocking/overlapping your images, otherwise they won't receive any click event.
Not to mention that a script file's name should match the name of it class :)

Categories