如何使一个精灵可点击?

11
我已经进行了大量的谷歌搜索,但只找到了一些非常复杂的方法。我还找到了OnMouseDown()函数,但我无法使其正常工作。
目前,当您在屏幕上任何地方轻敲时,精灵将被激活。 编辑 - 是的,它有一个2D框碰撞器。
以下是我的代码:
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。


1
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition); 三维向量鼠标位置 = 摄像机.Main.ScreenToWorldPoint(Input.mousePosition); - Barnstokkr
我现在会做出那个更改,希望那就是我的问题所在。 - MIke
@Barnstokkr 我在哪里可以使用它?我将 Input.GetKeyDown(KeyCode.Mouse0) 更改为 Input.GetMouseButtonDown(0),但无论我在哪里点击,它仍然会触发。 - MIke
抱歉,我问的是如何使“Sprite”可点击,而不是如何使整个屏幕可点击并激活Sprite。 - MIke
5个回答

25

使用OnMouseDown

最简单的方法是将此函数添加到任何附加在包含精灵的gameObject上的脚本组件中:

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

gameObject还需要一个collider。2D和3D collider都可以。

与其他方法的比较

射线投射只适用于一种collider类型,Physics.Raycast仅适用于3D碰撞体,而Physics2D.Raycast则仅适用于2D碰撞体。OnMouseDown可在两者上使用,但执行射线投射的性能可能与执行两个射线投射的性能一样差。

其他答案中提到的基于位置的方法对于性能很好。一对if语句的计算速度比射线投射快得多,但是射线投射对于基本场景仍然足够快。位置检查的缺点是,如果您更改任何内容(缩放或位置),您可能会破坏自己的if语句。此外,如果您希望精灵彼此重叠,则这些if语句相当复杂。


非常感谢,抱歉回复晚了...是的,这正是为什么我不想使用基于位置的代码,因为我经常改变主意并移动事物...我会尝试一下这个方法...我之前不知道有2D射线投射...我谷歌了一下,发现射线投射在2D上不起作用,但还是感谢您让我知道了这个:P 我会在几个小时后尝试一下,希望它是我想要的:P 再次感谢。 - MIke
1
没问题。我刚意识到你的建议 OnMouseDown 也可以起作用。我已经编辑了我的答案。这样做更好,因为它只需要在用户点击时执行。 - maZZZu
非常感谢!我们有个赢家了!我知道肯定有简单的方法来做这个,而你找到了!如果我能请你喝一杯啤酒就好了! - MIke
哇!这是一个很棒的答案!没想到这么简单! - Barnstokkr

3

我不完全确定Unity如何处理2D和3D的区别,但我相信射线投射的原理是相同的,因此请尝试以下操作,并将其放在您想要单击的脚本的更新下面。

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

这段代码的作用是检查鼠标是否被点击,检查鼠标点击的位置是否确实有内容,并检查被点击的内容是否具有脚本。


抱歉 @MIke,我本来是想说 Raycast 的,中途不应该有大写字母。我已经修改了答案。 - Benjamin James Drury
哦,没问题,抱歉我应该注意到的。 - MIke
代码已经放入您试图点击的对象中,并且它也有一些描述上的碰撞器? - Benjamin James Drury
“碰撞器是否放置正确?”这是我能想到的唯一问题。如果碰撞器没有覆盖精灵,它就不会起作用。如果已经放置在正确位置,那么我恐怕无法帮助你进一步了,因为我对使用Unity进行二维开发的知识缺乏了解,只能表示歉意。 - Benjamin James Drury
是的,无论如何还是谢谢你。看来我找不到一个简单的方法来做这件事。我将尝试下面更复杂的几个选项。再次感谢。 - MIke
显示剩余3条评论

1

我将Input.GetKeyDown(KeyCode.Mouse0)改为Input.GetMouseButtonDown(0),但无论我在哪里单击,它仍会触发

无论你在哪里点击,它都会触发并不奇怪,因为你没有限制它的特定位置。现在你只是检查了

input.GetMouseButtonDown(0)

您需要检查点击是否在特定区域内,或者是否击中了某个对象。因此,您可以通过当前的鼠标位置来限制它,例如:


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

或者您可以使用射线投射来确定当前所击中的对象。在几乎所有情况下,我都会积极建议使用此方法。有关射线投射的更多信息,请查看Unity教程

无论如何,感谢提供的帮助 :P 我最终成功让 onmousedown 工作了,我只需要将它变成 void 而不是 input.get,啊哈终于...非常感谢。 - MIke

1
正如我在评论中看到的,您可以获取真实的触摸位置。
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();
    }
}

我可能错过了检查 xD 的条件。

这个想法是检查你的点击是否在一个合理的范围内,这个范围应该是你的精灵所在的范围。我在那里放了一个简单的数字,当然你可以使用 SpriteRenderer 的大小 x 和 y。


谢谢您帮忙回答,但是我最终还是用mousedown解决了问题。我不想使用位置一,因为我可能需要稍后移动精灵,而且我不想重新编写代码。 - MIke

1

首先,我认为你应该为你的游戏对象添加一个碰撞体,并使用一种射线投射来进行点击检测。你可以使用 Input.GetMouseButtonDown (0) 代替 Input.GetKeyDown (KeyCode.Mouse0)


谢谢建议,如果我进行那个更改,现在会起作用吗?我对射线投射还不熟悉。 - MIke
我已经修改了它,但无论我在哪里点击,它仍然激活。有没有简单的想法? - MIke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接