How to make a sprite clickable?
Asked Answered
E

5

12

I have googled plenty and only come up with really complicated methods of doing it. I also found the function OnMouseDown() but I haven't been able to make it work.

At the moment the sprite activates when you tap anywhere on screen.

EDIT - Yes it has a 2d Box collider

My code below:

using UnityEngine;
using System.Collections;

public class mute : MonoBehaviour 
{
    public bool isMuted = false;
    public Sprite mute1, mute2;

    private SpriteRenderer spriteRenderer; 

    private void Start () 
    {
        spriteRenderer = GetComponent<SpriteRenderer>();

        if (spriteRenderer.sprite == null) 
            spriteRenderer.sprite = mute1;
    }
    private void Update () 
    {
        if (Input.GetKeyDown (KeyCode.Mouse0)) 
        {
            if (!isMuted)
            {
                AudioListener.pause = true;
                AudioListener.volume = 0;

                isMuted = true;
                ChangeSprite();

            }
            else
            {
                AudioListener.pause = false;
                AudioListener.volume = 1;

                isMuted = false;
                ChangeSprite();
            }
        }
    }
    private void ChangeSprite() => spriteRenderer.sprite = 

spriteRenderer.sprite == mute1 ? mute2 : mute1; }

Epochal answered 26/1, 2015 at 8:8 Comment(4)
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);Hydrogeology
I will make that change now, Hopefully that was what my issue was.Epochal
@Hydrogeology where would i use that? I changed Input.GetKeyDown (KeyCode.Mouse0) to Input.GetMouseButtonDown(0) and it still activates no matter where i clickEpochal
Sorry but if im asking how to make a "Sprite" clickable.. not how to make the whole screen clickable and activate a sprite..Epochal
H
26

Using OnMouseDown

The easiest method is to add this function into any script component attached to the gameObject containing the sprite:

void OnMouseDown(){
    Debug.Log("Sprite Clicked");
}

The gameObject also need to have a collider. Both 2D and 3D colliders work.

Comparison to other methods

Raycasting only works on one collider type at the time Physics.Raycast works only against 3D colliders and Physics2D.Raycastworks only against 2D colliders. OnMouseDown works on both, but it is possible that its performance is as bad as the performance of executing both of the raycasts.

Position based methods stated in other answers are good for performance. Couple of if statements is much faster to compute than ray casting, but ray casting is still fast enough for basic scenes. The disadvantage of the position checks is that if you change anything (scale or position) you are likely to break your if clauses. Also the ifs are quite complicated if you want sprites to be on top of each other.

Hedley answered 26/1, 2015 at 19:42 Comment(4)
Thanks so much and sorry for late reply... yes exactly why i do not want to use code that is position based as I keep changing my mind and moving things around.. I will give this a go.. I was unaware of raycast 2d... i Googled it and it came up that ray cast does not work on 2d but thanks for letting me know about that :P I will give this a go in a few hrs and fingers crossed it's what i'm after :P thanks again.Epochal
No problem. I just realized that your suggestion OnMouseDown works as well. I edited my answer to that. It is much better because it has to be done only when the user has clicked.Hedley
Thanks so much! We have a winner! I knew there was an easy way to do this and you found it!!! If i could buy you a beer i would!Epochal
Wow! This is a great answer! Didn't know it was this easy!Hydrogeology
D
3

I'm not 100% sure about how unity handles 2D things compared to 3D things, but I'm fairly sure the principal of ray-casting is the same, so try something like the following and stick it under the update in your script you want clicked.

if (Input.GetMouseButtonDown(0))
{
    RaycastHit hit;
    if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit))
    {
        if (hit.collider == collider)
        {
            //Do your thing.
        }
    }
}

So what this is doing is checking to see if the mouse is clicked, checking to see if where the mouse clicked there actually was anything, and then checking that what was clicked is the thing with the script on it.

Discordancy answered 26/1, 2015 at 9:7 Comment(8)
Looks like a much easier option, but i guess i have to import raycasting? at the moment it says Assets/mute.cs(33,37): error CS0117: UnityEngine.Physics' does not contain a definition for RayCast'Epochal
Sorry @MIke, I had meant Raycast; no capital letter half way through. I've changed the answer now.Discordancy
oh no problem, sorry i should have noticed that.Epochal
bugger it doesn't work.. unsure why.. doesn't pose any errors just doesn't activate the sprite at all now.Epochal
The code has been put in the object you are trying to click, and it does have a collider of some description on it too?Discordancy
yes it has a 2d collieder, and yes i have a gameobject called mute, then inside that i have the sprite.. on the game object i have the script mute.cs and inside that script i placed this code.Epochal
Is the collider in the right place is all I can think of to ask then? If the collider is not over the sprite, it won't work. If it is in the right place, then I'm afraid my lack of knowledge of using Unity for 2D things means I can't help any further, in which case I can only offer my apologies.Discordancy
Yes it is, Thanks anyways.. It seems i cannot find a simple way to do this.. I shall try a few more of the complicated options below.Thanks again.Epochal
D
1

First I think you should have a collider with your gameobject and for clicking you should use sort of raycasting. And you can use Input.GetMouseButtonDown (0) instead of Input.GetKeyDown (KeyCode.Mouse0)

Derris answered 26/1, 2015 at 8:26 Comment(2)
Thanks for the advice, If i make that change will that work now? I'm not up tp speed with raycasting yetEpochal
I have changed it but still actiavtes no matter where i click. any simple ideas?Epochal
H
1

I changed Input.GetKeyDown (KeyCode.Mouse0) to Input.GetMouseButtonDown(0) and it still activates no matter where i click

It is not that weird that it activates no mater where you click, because you are not limiting it to a specific location. Right now you are just checking

input.GetMouseButtonDown(0)

You will want to check if the click is within a certain area, or hits a certain object. So you can limit it by the current mouse position you have, with something like this.

if(mousePosition.x < 100 && mousePosition.x > 10)
    if(mousePosition.y < 500 && mousePosition.y > 10

Or you could use a raycast to determine which object you are currently hitting. Which I would actively advice in pretty much every scenario. For more about raycasting please check out the unity tutorials

Hickory answered 26/1, 2015 at 9:6 Comment(1)
Thanks for the help offered anyways :P I ended up getting onmousedown to work i just needed to make it a void and not input.get but ahh finally... Thanks so much.Epochal
L
1

As I saw in the comments you can get the real touch position

if (Input.GetTouch(0) /*|| buttondown or what you want*/)
{
    fingerPos =  Input.GetTouch(0).position; // or buttondown
    Vector3 realPos = Camera.main.ScreenToWorldPoint(fingerPos);

    if (realPos.transform.position.x >= SpriteRenderer.transform.position.x -10
        && realPos.transform.position.x <= SpriteRenderer.transform.position.x +10)
        && realPos.transform.position.y >= SpriteRenderer.transform.position.y -10
        && realPos.transform.position.y <= SpriteRenderer.transform.position.y +10)
    {
        ChangeSprite();
    }
}

I may have missed the condition of check xD The idea is to check if your tap is within a reasonable range where your sprite should be. I put plain number there, you can of course use SpriteRenderer size x and size y.

Landgraviate answered 26/1, 2015 at 9:27 Comment(1)
Thanks for helping out with a repsonse, however i ended up getting mousedown to work.. I did not want to go with a position one as i may need to move the sprites later and i didn't want to have to recode it all.Epochal

© 2022 - 2024 — McMap. All rights reserved.