6

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?

Fattie
  • 27,874
  • 70
  • 431
  • 719
Maxim Lavrov
  • 326
  • 5
  • 14
  • 2DToolkit does this absolutely perfectly, it has all the functions built-in. (2DTK is still incredibly useful in many ways: we would never do any 2D project without it.) ngui is not a solution. Or you can create your own, **as Programmer explains perfectly below**. I have to wonder though - why wouldn't you just use Unity's UI? What's the issue? – Fattie Jun 19 '16 at 12:43
  • I wonder the-same thing too. You have a complete Unity uGUI but he's talking about using NGUI or even re-making all controls from scratch... – Programmer Jun 19 '16 at 13:09
  • May be I just got it wrong, but using Unity UI button in 2D game looks weird for me. I can't put it in my objects hierarchy, it has different scale than my sprites, I can't attach it to a particular sorting layer etc. So I got a little lost. – Maxim Lavrov Jun 19 '16 at 13:34
  • 1
    You are right. You can't put it in your objects hierarchy. The UI must be under Canvas GameObject. This is good because your UI is supposed to be separated from from your GameObjects. The-same thing applies to your UI code. It should be separated from your game logic for easy troubleshooting and portability. That shouldn't be a problem at-all. Is there anything you want to do with the UI that you couldn't because of objects hierarchy? – Programmer Jun 19 '16 at 13:43
  • Also, you **can** change Canvas sorting layer. For the sorting layers of UI components under the Canvas, they are rendered from top to bottom. You can re-arrange them if there is any problem. – Programmer Jun 19 '16 at 13:45
  • 1
    @MaximLavrov You can make the canvas a child of your game objects. See [the Tank Health video](https://unity3d.com/learn/tutorials/projects/tanks-tutorial/tank-health?playlist=20081) in the tanks tutorial on unity's website – Scott Chamberlain Jul 07 '16 at 18:55

2 Answers2

4

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.

Programmer
  • 121,791
  • 22
  • 236
  • 328
  • Great answer, thank you! You just forgot to mention than you also need to add a collider to the sprite. – Maxim Lavrov Jul 06 '16 at 11:15
  • 1
    Raycast will not detect gameobjects without colliders. I thought you knew that already. – Programmer Jul 06 '16 at 15:55
  • Everything is new for a newbie like me. I don't even know what Raycast is :) For me it's just a magic for now. I believe it's better to add it to the answer for other newbies. – Maxim Lavrov Jul 07 '16 at 16:20
  • Just updated the question. If you are new to Unity, then you should follow this http://unity3d.com/learn/tutorials It has many good things for newbies. – Programmer Jul 07 '16 at 18:53
  • Crikey, this is absolutely incredible. Works perfectly. Thanks for your help. – hiroki Nov 13 '20 at 11:33
4

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 :

  1. void OnMouseOver()
  2. void OnMouseDown()
  3. 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.

Peter Suwara
  • 781
  • 10
  • 16