在unity项目里3D场景中如果有用到射线的,鼠标点击UI会发生UI会被穿透,导致3D场景里的射线触发。
举个例子:下面场景里,在3D场景里点击地面人物(红色的cube)会移动到点击的地方,现在有个button(下图中“显示游戏介绍”按钮)重叠在地面上,当点击按钮时会显示出游戏介绍的界面,但同时人物也会移动到点击的地方(这不是我们预期的效果)
。
运行cube默认位置:
当点击按钮时候cube的位置:
这种问题的原因就是当点击鼠标时射线穿透了UI按钮导致了3D场景的射线触发。
具体原理参考网上这篇文章:http://www.tuicool.com/articles/yy2aA3E
这里我只讲实现功能方法
直接上源码(注释很全面):
注意:GraphicRaycaster组件默认在canvas上就有的,所以将上面脚本绑定到Canvas上就OK。
然后运行看到当点击按钮时3D场景不会受到影响了。
Look:
运行cube默认位置:
当点击按钮时候cube的位置:
这种问题的原因就是当点击鼠标时射线穿透了UI按钮导致了3D场景的射线触发。
具体原理参考网上这篇文章:http://www.tuicool.com/articles/yy2aA3E
这里我只讲实现功能方法
直接上源码(注释很全面):
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
using
UnityEngine;
using
System.Collections;
using
UnityEngine.UI;
using
UnityEngine.EventSystems;
using
System.Collections.Generic;
//该代码实现,在地面上一个位置点击鼠标,player就会慢慢移动到点击的位置
public
class
personmove : MonoBehaviour
{
int
moveSpeed = 500;
//player移动速度
public
Transform player;
//定义一个人物的Transform
private
Vector3 endposition, startpos;
//下面是用来UI事件和射线
EventSystem eventSystem;
GraphicRaycaster RaycastInCanvas;
//Canvas上有这个组件
void
Start()
{
RaycastInCanvas =
this
.gameObject.GetComponent<GraphicRaycaster>();
//这个脚本要绑定到Canvas
endposition = player.transform.position;
}
void
Update()
{
if
(CheckGuiRaycastObjects())
return
;
//如果射线检测到UI上直接返回
if
(Input.GetMouseButtonUp(0))
{
//LeftMouse是在inputManager中设置的,左键值为mouse 0
PlayerMove();
}
if
(endposition != player.transform.position)
{
player.position = Vector3.MoveTowards(player.position, endposition, Time.deltaTime * moveSpeed);
}
}
bool
CheckGuiRaycastObjects()
//测试UI射线
{
PointerEventData eventData =
new
PointerEventData(eventSystem);
eventData.pressPosition = Input.mousePosition;
eventData.position = Input.mousePosition;
List<RaycastResult> list =
new
List<RaycastResult>();
RaycastInCanvas.Raycast(eventData, list);
//Debug.Log(list.Count);
return
list.Count > 0;
}
//人物移动方法
void
PlayerMove()
{
Vector3 cursorScreenPosition = Input.mousePosition;
//鼠标在屏幕上的位置
Ray ray = Camera.main.ScreenPointToRay(cursorScreenPosition);
//在鼠标所在的屏幕位置发出一条射线(暂名该射线为x射线)
RaycastHit hit;
if
(Physics.Raycast(ray,
out
hit, 1000))
{
if
(hit.collider.gameObject.tag ==
"Terrain"
)
{
//设置地形Tag为Terrain
endposition = hit.point;
}
}
}
}
|
注意:GraphicRaycaster组件默认在canvas上就有的,所以将上面脚本绑定到Canvas上就OK。
然后运行看到当点击按钮时3D场景不会受到影响了。
Look: