在unity项目里3D场景中如果有用到射线的,鼠标点击UI会发生UI会被穿透,导致3D场景里的射线触发。
举个例子:下面场景里,在3D场景里点击地面人物(红色的cube)会移动到点击的地方,现在有个button(下图中“显示游戏介绍”按钮)重叠在地面上,当点击按钮时会显示出游戏介绍的界面,但同时人物也会移动到点击的地方(这不是我们预期的效果)
。
运行cube默认位置:
当点击按钮时候cube的位置:
这种问题的原因就是当点击鼠标时射线穿透了UI按钮导致了3D场景的射线触发。
具体原理参考网上这篇文章:http://www.tuicool.com/articles/yy2aA3E
这里我只讲实现功能方法
直接上源码(注释很全面):
纯文本查看 复制代码
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: