在unity项目里3D场景中如果有用到射线的,鼠标点击UI会发生UI会被穿透,导致3D场景里的射线触发。举个例子:下面场景里,在3D场景里点击地面人物(红色的cube)会移动到点击的地方,现在有个button(下图中“显示游戏介绍”按钮)重叠在地面上,当点击按钮时会显示出游戏介绍的界面,但同时人物也会移动到点击的地方(这不是我们预期的效果)。
运行cube默认位置:
当点击按钮时候cube的位置:
这种问题的原因就是当点击鼠标时射线穿透了UI按钮导致了3D场景的射线触发。
具体原理参考网上这篇文章:http://www.tuicool.com/articles/yy2aA3E
这里我只讲实现功能方法
直接上源码(注释很全面):
[C#]纯文本查看复制代码
usingUnityEngine;
usingSystem.Collections;
usingUnityEngine.UI;
usingUnityEngine.EventSystems;
usingSystem.Collections.Generic;
//该代码实现,在地面上一个位置点击鼠标,player就会慢慢移动到点击的位置
publicclasspersonmove : MonoBehaviour
{
intmoveSpeed = 500;//player移动速度
publicTransform player;//定义一个人物的Transform
privateVector3 endposition, startpos;
//下面是用来UI事件和射线
EventSystem eventSystem;
GraphicRaycaster RaycastInCanvas;//Canvas上有这个组件
voidStart()
{
RaycastInCanvas =this.gameObject.GetComponent();//这个脚本要绑定到Canvas
endposition = player.transform.position;
}
voidUpdate()
{
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);
}
}
boolCheckGuiRaycastObjects()//测试UI射线
{
PointerEventData eventData =newPointerEventData(eventSystem);
eventData.pressPosition = Input.mousePosition;
eventData.position = Input.mousePosition;
List list =newList();
RaycastInCanvas.Raycast(eventData, list);
//Debug.Log(list.Count);
returnlist.Count > 0;
}
//人物移动方法
voidPlayerMove()
{
Vector3 cursorScreenPosition = Input.mousePosition;//鼠标在屏幕上的位置
Ray ray = Camera.main.ScreenPointToRay(cursorScreenPosition);//在鼠标所在的屏幕位置发出一条射线(暂名该射线为x射线)
RaycastHit hit;
if(Physics.Raycast(ray,outhit, 1000))
{
if(hit.collider.gameObject.tag =="Terrain")
{//设置地形Tag为Terrain
endposition = hit.point;
}
}
}
}
注意:GraphicRaycaster组件默认在canvas上就有的,所以将上面脚本绑定到Canvas上就OK。
然后运行看到当点击按钮时3D场景不会受到影响了。
Look:









网友评论