Unity中的OnMouseDown()方法有时执行,有时不执行
Sometimes OnMouseDown() method in Unity executes, sometimes it does not
所以我将此代码附加到 Quad。
public class ShapeGrid : MonoBehaviour {
public GameObject[] shapes;
void Start(){
GameObject[,] shapeGrid = new GameObject[3,3];
StartCoroutine(UpdateGrid());
}
IEnumerator UpdateGrid(){
while (true) {
SetGrid ();
yield return new WaitForSeconds(2);
}
}
void SetGrid(){
int col = 3, row = 3;
for (int y = 0; y < row; y++) {
for (int x = 0; x < col; x++) {
int shapeId = (int)Random.Range (0, 4.9999f);
GameObject shape = Instantiate (shapes[shapeId]);
shape.AddComponent<ShapeBehavior>();
Vector3 pos = shapes [shapeId].transform.position;
pos.x = (float)x*3;
pos.y = (float)y*3;
shapes [shapeId].transform.position = pos;
}
}
}
上面的脚本在 运行 时生成游戏对象,我为其分配了另一个脚本:
public class ShapeBehavior : MonoBehaviour {
void OnMouseDown(){
Debug.Log ("Destroy");
Destroy (gameObject);
}
}
问题是,OnMouseDown() 有时执行,有时不执行。我不知道为什么,也不知道如何解决它。
可能您必须为所有对象添加碰撞器,因为 OnMouse 事件基于碰撞。详细信息如下:Unity Docs - OnMouseDown
编辑:经过一番讨论,我们发现问题是由 Instantiate 方法引起的。
在 Instantiate 方法中填充所有参数总是更好的方法,例如
Instantiate(prefab, Vector3.zero, Quaternion.Identity)
如果需要,您可以在实例化对象后更改任何这些参数。
有很多可能的原因。
- 对撞机冲突。 OnMouseDown() 是引擎盖下的光线投射。如果来自鼠标位置的射线撞击到另一个碰撞体(可见或不可见),则不会调用 OnMouseDown()。
- 与相机的距离。 OnMouseDown 实现使用光线投射的深度限制,这可能会导致对象无法注册点击。
- 刚体。如果层次结构中某处存在 RigidBody,则 OnMouseDown 的工作方式完全不同。它实际上不会在单击的对象上调用 OnMouse 函数,而是会在 RigidBody 的游戏对象上调用它们(又是一个错误)。
- 缺少对撞机。当用户在 GUIElement 或 Collider 上按下鼠标按钮时调用 OnMouseDown,因此您必须向对象添加碰撞器。
- 多个摄像头。由于光线投射,有多个相机可能会导致问题。
- Collider 正在与鼠标位置上的另一个 Collider 发生碰撞。
- 简直是野虫。关闭并重新打开 Unity 编辑器作为最后的希望。
如果以上都没有帮助,您应该实现 IPointerDownHandler 接口并使用它代替 OnMouseDown。
所以我将此代码附加到 Quad。
public class ShapeGrid : MonoBehaviour {
public GameObject[] shapes;
void Start(){
GameObject[,] shapeGrid = new GameObject[3,3];
StartCoroutine(UpdateGrid());
}
IEnumerator UpdateGrid(){
while (true) {
SetGrid ();
yield return new WaitForSeconds(2);
}
}
void SetGrid(){
int col = 3, row = 3;
for (int y = 0; y < row; y++) {
for (int x = 0; x < col; x++) {
int shapeId = (int)Random.Range (0, 4.9999f);
GameObject shape = Instantiate (shapes[shapeId]);
shape.AddComponent<ShapeBehavior>();
Vector3 pos = shapes [shapeId].transform.position;
pos.x = (float)x*3;
pos.y = (float)y*3;
shapes [shapeId].transform.position = pos;
}
}
}
上面的脚本在 运行 时生成游戏对象,我为其分配了另一个脚本:
public class ShapeBehavior : MonoBehaviour {
void OnMouseDown(){
Debug.Log ("Destroy");
Destroy (gameObject);
}
}
问题是,OnMouseDown() 有时执行,有时不执行。我不知道为什么,也不知道如何解决它。
可能您必须为所有对象添加碰撞器,因为 OnMouse 事件基于碰撞。详细信息如下:Unity Docs - OnMouseDown
编辑:经过一番讨论,我们发现问题是由 Instantiate 方法引起的。
在 Instantiate 方法中填充所有参数总是更好的方法,例如
Instantiate(prefab, Vector3.zero, Quaternion.Identity)
如果需要,您可以在实例化对象后更改任何这些参数。
有很多可能的原因。
- 对撞机冲突。 OnMouseDown() 是引擎盖下的光线投射。如果来自鼠标位置的射线撞击到另一个碰撞体(可见或不可见),则不会调用 OnMouseDown()。
- 与相机的距离。 OnMouseDown 实现使用光线投射的深度限制,这可能会导致对象无法注册点击。
- 刚体。如果层次结构中某处存在 RigidBody,则 OnMouseDown 的工作方式完全不同。它实际上不会在单击的对象上调用 OnMouse 函数,而是会在 RigidBody 的游戏对象上调用它们(又是一个错误)。
- 缺少对撞机。当用户在 GUIElement 或 Collider 上按下鼠标按钮时调用 OnMouseDown,因此您必须向对象添加碰撞器。
- 多个摄像头。由于光线投射,有多个相机可能会导致问题。
- Collider 正在与鼠标位置上的另一个 Collider 发生碰撞。
- 简直是野虫。关闭并重新打开 Unity 编辑器作为最后的希望。
如果以上都没有帮助,您应该实现 IPointerDownHandler 接口并使用它代替 OnMouseDown。