为什么同一个对象会调用不同的两个事件方法? (鼠标点击-拖动-取消点击)
Why would supposedly different two event methods be called by the same object? (Mouse Click-Drag-Unclick)
版本:Unity3D 4.6.2f1
我有一个方块网格(附有 Tile
脚本的立方体 GameObject
s)。它们位于它们的索引位置 [x][y] = (x, y, z=0) World Coordinates
.
我正在尝试实现类似于扫雷器的行为:当释放左键时,除非有向下的右键单击,否则会显示释放鼠标的瓦片。下面,我尝试获取释放鼠标左键的图块的坐标。
进入代码之前:
OnMouseDown()
- OnMouseDown is called when the user has pressed the mouse button while over the GUIElement or Collider.
OnMouseUp()
- OnMouseUp is called when the user has released the mouse button.
根据这些定义,我假设(错误?)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)
如果我可以在 OnMouseUp()
函数上获得 (14,15)
,我会直接找到要显示的图块,但显然我做不到。我认为我的目标的解决方法是保留 static bool _isDragging
并在 if
块中的 OnMouseEnter()
中使用它来分配要正确显示的图块。这是——通过同一个对象调用两个函数,即使我按下左键单击某个对象并将其释放到其他对象上? - 故意的?对于这种情况有更好的解决方法吗?
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 调用您单击的磁贴的原因很简单。这种行为在大多数时候是最安全,也是最值得期待的方式。将游戏对象的鼠标事件视为 "user clicked on me" 和 "user released the button after clicked on me".
假设在释放鼠标按钮时为光标下的对象调用 OnMouseUp。想一想从鼠标单击开始并在释放鼠标按钮(如拖放)时完成的操作。然后你会痛苦地发现如果鼠标不再指向你最初点击的对象, OnMouseUp 将不会被调用。您将无法完成操作。你必须自己捕捉鼠标释放事件。
对于您的情况,仅靠 OnMouseUp 和 OnMouseDown 无法满足您的需求。您正在尝试做的事情对您的应用程序来说太具体了。不幸的是,Unity 的输入系统默认不涵盖这种交互。幸运的是 Unity 足够灵活,可以轻松实现这一点。
作为更好的解决方法,不使用 static bool _isDragging
,而是使用 void OnMouseOver()
函数:
void OnMouseOver()
{
if(Input.GetMouseButtonUp(0)) // left click released
RevealTile();
if(Input.GetMouseButtonUp(1)) // right click released
FlagTile();
}
版本:Unity3D 4.6.2f1
我有一个方块网格(附有 Tile
脚本的立方体 GameObject
s)。它们位于它们的索引位置 [x][y] = (x, y, z=0) World Coordinates
.
我正在尝试实现类似于扫雷器的行为:当释放左键时,除非有向下的右键单击,否则会显示释放鼠标的瓦片。下面,我尝试获取释放鼠标左键的图块的坐标。
进入代码之前:
OnMouseDown()
- OnMouseDown is called when the user has pressed the mouse button while over the GUIElement or Collider.OnMouseUp()
- OnMouseUp is called when the user has released the mouse button.
根据这些定义,我假设(错误?)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)
如果我可以在 OnMouseUp()
函数上获得 (14,15)
,我会直接找到要显示的图块,但显然我做不到。我认为我的目标的解决方法是保留 static bool _isDragging
并在 if
块中的 OnMouseEnter()
中使用它来分配要正确显示的图块。这是——通过同一个对象调用两个函数,即使我按下左键单击某个对象并将其释放到其他对象上? - 故意的?对于这种情况有更好的解决方法吗?
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 调用您单击的磁贴的原因很简单。这种行为在大多数时候是最安全,也是最值得期待的方式。将游戏对象的鼠标事件视为 "user clicked on me" 和 "user released the button after clicked on me".
假设在释放鼠标按钮时为光标下的对象调用 OnMouseUp。想一想从鼠标单击开始并在释放鼠标按钮(如拖放)时完成的操作。然后你会痛苦地发现如果鼠标不再指向你最初点击的对象, OnMouseUp 将不会被调用。您将无法完成操作。你必须自己捕捉鼠标释放事件。
对于您的情况,仅靠 OnMouseUp 和 OnMouseDown 无法满足您的需求。您正在尝试做的事情对您的应用程序来说太具体了。不幸的是,Unity 的输入系统默认不涵盖这种交互。幸运的是 Unity 足够灵活,可以轻松实现这一点。
作为更好的解决方法,不使用 static bool _isDragging
,而是使用 void OnMouseOver()
函数:
void OnMouseOver()
{
if(Input.GetMouseButtonUp(0)) // left click released
RevealTile();
if(Input.GetMouseButtonUp(1)) // right click released
FlagTile();
}