为什么同一个对象会调用不同的两个事件方法呢? (鼠标点击 - 拖动 - 取消点击)

时间:2015-04-01 07:33:54

标签: c# events unity3d callback

版本: Unity3D 4.6.2f1

我有一个瓷砖网格(多维数据集GameObject s附加Tile脚本)。它们位于其索引位置[x][y] = (x, y, z=0) World Coordinates

我正在尝试实现类似于扫雷的行为:当释放左键时,除非右键单击,否则将显示释放鼠标的图块。下面,我尝试获取鼠标左键单击的图块坐标。

进入代码之前:

  
      
  • OnMouseDown() - 当用户在GUIElement或Collider上方按下鼠标按钮时,会调用OnMouseDown。
  •   
  • OnMouseUp() - 当用户释放鼠标按钮时调用OnMouseUp。
  •   

基于这些定义,我假设(错误?)OnMouseUp()将被其上方的对象调用,鼠标左键单击被释放。

Tile脚本上,我有以下内容:

public class Tile : MonoBehaviour
{
    // variables
    private Vector2 _gridPosition = Vector2.zero;

    public Vector2 GridPosition
    {
        get { return _gridPosition; }
        set { _gridPosition = value; }
    }

    // functions
    string Vec2toText(Vector2 v)
    {
        return String.Format("(" + v.x + ", " + v.y + ")");
    }

    void OnMouseDown()
    {
        Debug.Log("TILE:: ON_MOUSE_DOWN:: " + Vec2toText(_gridPosition));
    }

    void OnMouseUp()
    {
        Debug.Log("TILE:: ON_MOUSE_UP:: " + Vec2toText(_gridPosition));
    }

    void OnMouseEnter()
    {
        Debug.Log("TILE:: MOUSE_ENTER: " + Vec2toText(_gridPosition));
    }

    void OnMouseExit()
    {
        Debug.Log("TILE:: MOUSE_EXIT: " + Vec2toText(_gridPosition));
    }
}

here是输出:

TILE:: MOUSE_ENTER: (15, 15)
TILE:: MOUSE_DOWN: (15, 15)
TILE:: MOUSE_EXIT: (15, 15)
TILE:: MOUSE_ENTER: (14, 15)
TILE:: MOUSE_UP: (15, 15)    %% This line
TILE:: MOUSE_EXIT: (14, 15)

如果我可以在(14,15)函数上获得OnMouseUp(),我会直接找到要显示的图块,但显然我不能。我认为我的目标的解决方法是保留static bool _isDragging并在OnMouseEnter()块的if中使用它来指定要正确显示的磁贴。这是 - 由同一个对象调用两个函数,即使我按下左键单击某个对象并将其释放到其他对象上? - 打算?这种情况有更好的解决方法吗?

2 个答案:

答案 0 :(得分:1)

OnMouseDown仅针对鼠标左键发出。所以你必须自己实施右击。

一个选项是按下按钮时检查光线投射。

void Update()
{
    if (Input.GetMouseButtonDown(1))
    {
        var ray = camera.ScreenPointToRay(Input.mousePosition);
        RaycastHit hitInfo;
        if (Physics.Raycast(ray, out hitInfo))
        {
            var myObject = hitInfo.collider.GetComponent<MyScriptOrSomething>();
            // Do something here
        }
    }
}

另一个选项是使用OnMouseEnter来检查右键单击。类似的东西:

void OnMouseOver()
{
    if (Input.GetMouseButtonDown(1))
    {
        // Do something here
    }
}

修改

OnMouseUp调用您单击的磁贴的原因很简单。这种行为在大多数情况下是最安全和更预期的方式。将游戏对象的鼠标事件想象成&#34;用户点击我&#34;和&#34;用户在点击我之后发布了按钮&#34;。

因此,让我们说鼠标按钮释放时,光标下的对象会调用OnMouseUp。想象一下从鼠标点击开始的操作,并在鼠标按钮释放时完成(如拖放)。然后你会痛苦地发现,如果鼠标不再指向你最初点击的对象,就不会调用OnMouseUp。您无法完成操作。您必须自己捕捉鼠标释放事件。

在您的情况下,仅OnMouseUp和OnMouseDown就无法满足您的需求。您要做的事情对您的应用来说太具体了。不幸的是,Unity的输入系统默认不包括这种交互。幸运的是,Unity足够灵活,可以轻松实现这一点。

答案 1 :(得分:0)

作为更好的解决方法,请使用static bool _isDragging函数,而不是使用void OnMouseOver()

void OnMouseOver()
{
    if(Input.GetMouseButtonUp(0))  // left click released
        RevealTile();
    if(Input.GetMouseButtonUp(1))  // right click released
        FlagTile();
}