[Unity3D]利用Raycast实现物体的选择与操作
本文系作者原创 转载请注明出处
如果是一个2D的平面项目或者说需要在三维空间选择一个物体时(经常表现为抓取物件),我们需要用到Raycast事件
那么首先先说说什么是Raycast 按照字面上来理解的话,就是投射射线=.=的确也是这样
Raycast有几种重载函数,所以按照惯例,先看看官方文档怎么说的
-------------------------------------------------------------------
Physics.Raycast 光线投射
static function Raycast (origin : Vector3, direction : Vector3, distance : float = Mathf.Infinity, layerMask : int = kDefaultRaycastLayers) : bool
Parameters参数
- originThe starting point of the ray in world coordinates.
在世界坐标,射线的起始点。 - directionThe direction of the ray.
射线的方向。 - distanceThe length of the ray
射线的长度。 - layerMaskA Layer mask that is used to selectively ignore colliders
when casting a ray.
只选定Layermask层内的碰撞器,其它层内碰撞器忽略。
Returns返回
bool - True when the ray intersects any collider, otherwise false.
当光线投射与任何碰撞器交叉时为真,否则为假。
Description描述
Casts a ray against all colliders in the scene.
在场景中投下可与所有碰撞器碰撞的一条光线。
Note: This function will return false if you cast a ray from inside a sphere to the outside; this in an intended behaviour.
注意:如果从一个球型体的内部到外部用光线投射,返回为假。
static function Raycast (origin : Vector3, direction : Vector3, out hitInfo : RaycastHit, distance : float = Mathf.Infinity, layerMask : int = kDefaultRaycastLayers) : bool
Parameters参数
- originThe starting point of the ray in world coordinates.
在世界坐标,射线的起始点。 - directionThe direction of the ray.
射线的方向。 - distanceThe length of the ray
射线的长度。 - hitInfoIf true is returned, hitInfo will contain more information
about where the collider was hit (See Also: RaycastHit).
如果返回true,hitInfo将包含碰到器碰撞的更多信息。 - layerMaskA Layer mask that is used to selectively ignore colliders
when casting a ray.
只选定Layermask层内的碰撞器,其它层内碰撞器忽略。
Returns
bool - True when the ray intersects any collider, otherwise false.
当光线投射与任何碰撞器交叉时为真,否则为假。
Description描述
Casts a ray against all colliders in the scene and returns detailed
information on what was hit.
在场景中投下可与所有碰撞器碰撞的一条光线,并返回碰撞的细节信息。
static function Raycast (ray : Ray, distance : float = Mathf.Infinity, layerMask : int = kDefaultRaycastLayers) : bool
Parameters参数
- rayThe starting point and direction of the ray.
射线的起点和方向 - distanceThe length of the ray
射线的长度。 - layerMaskA Layer mask that is used to selectively ignore colliders
when casting a ray.
只选定Layermask层内的碰撞器,其它层内碰撞器忽略。
Returns
bool - True when the ray intersects any collider, otherwise false.
当光线投射与任何碰撞器交叉时为真,否则为假。
Description描述
Same as above using ray.origin and ray.direction instead of origin and
direction.
使用ray.origin和ray.direction同上,替代origin和direction。
static function Raycast (ray : Ray, out hitInfo : RaycastHit, distance : float = Mathf.Infinity, layerMask : int = kDefaultRaycastLayers) : bool
Parameters参数
- rayThe starting point and direction of the ray.
射线的起点和方向 - distanceThe length of the ray
射线的长度 - hitInfoIf true is returned, hitInfo will contain more information
about where the collider was hit (See Also: RaycastHit).
如果返回true,hitInfo将包含碰到器碰撞的更多信息。 - layerMaskA Layer mask that is used to selectively ignore colliders
when casting a ray.
只选定Layermask层内的碰撞器,其它层内碰撞器忽略。
Returns
bool - True when the ray intersects any collider, otherwise false.
当光线投射与任何碰撞器交叉时为真,否则为假。
Description描述
Same as above using ray.origin and ray.direction instead of origin and
direction.
使用ray.origin和ray.direction同上,替代origin和direction
-------------------------------------------------------------------
其中,提到了几个很关键的参数:距离、hitInfo、layerMask
距离,可以用来实现“有效抓取距离”,比如说人的手臂假如说是0.5米长,那我们不能抓到0.5米以外的东西
Layer Mask可以理解为我们用来做标记的物体
而重中之重的是hitInfo,它用来储存我们所投出去的射线的关键信息
比如说射线射到了哪个物体?距离多远?物体的位置?
那么怎么获取它呢?
我们仔细看看Physics.Raycast函数,里面有个参数是out hitInfo,也就是说我们在投射这个射线的时候可以直接利用函数所给的参数获取hitInfo,也就是投出去的射线的关键信息
有了这些背景知识,我们就可以随时用射线实现“选择物体”、“抓取物体”这些动作了(二位尤其需要)
那么现在又出现一个问题,我们怎么去发出这样一条射线??
众所周知,射线从一个固定端点出发,向一个方向无限延伸,我们首先就要找到这个固定端点,然后表示出这个方向简单的是,我们可以用当前的渲染相机作为这个固定端点,因为我们实时在用它观察四周,那么我们所要做的只是找到一个好的投射方向。
请看官方文档里面的一个函数及其解释
-----------------------------------------------------------------------------------------------------------------------------
Camera.ScreenPointToRay 屏幕位置转射线
function ScreenPointToRay (position : Vector3) : Ray
Description描述
Returns a ray going from camera through a screen point.
返回一条从相机发射的,穿过屏幕位置上一点的射线
Resulting
ray is in world space, starting on the near plane of the camera and
going through position's (x,y) pixel coordinates on the screen
(position.z is ignored).
产生的射线是在世界空间中,从相机的近裁剪面发出并穿过屏幕position(x,y)像素坐标(position.z被忽略)。
Screenspace is defined in pixels. The bottom-left of the screen is (0,0); the right-top is (pixelWidth,pixelHeight).
屏幕空间以像素定义。屏幕的左下为(0,0);右上是(pixelWidth,pixelHeight)。
-----------------------------------------------------------------------------------------------------------------------------
请注意特意标出来的红色字体
我们可以看出,它能够返回一条从相机发射的射线,并且函数返回的是一个Ray对象,也就是说我们必须创建一个对象来容纳它
特别注意的是最后几句关于屏幕空间的定义!!
那么现在步骤就清晰了
利用Raycast事件选择一个物体并实现对其的相关操作的步骤:
1.找到一个作为投射起点的相机
2.分别创建两个对象,一个用来容纳返回的射线,一个用来容纳返回的这条射线的所有相关信息(如位置、距离、投射到的物体等)
3.选择这个被射线投射到的物体,之后可以进行相关操作
于是乎放代码了
using UnityEngine; using System.Collections; [AddComponentMenu("Raycast/CastObjects")] public class Raycast_CastObj : MonoBehaviour { private GameObject selectedObj=null; private Camera validCam; //有效触摸距离 public float validTouchDistance = 5.0F; //用户选择的Layer Mask public string selectedLayerMask = "Default"; // Use this for initialization void Start () { //寻找一个合理的相机 validCam = FindObjectOfType<Camera>(); if (validCam == null) Debug.LogWarning("Warning!\nFailed to find camera!"); else Debug.Log("Find camera\nName:" + validCam.name); } // Update is called once per frame void Update () { var raycast = validCam.ScreenPointToRay(Input.mousePosition); RaycastHit raycastInfo; if(Physics.Raycast(raycast, out raycastInfo, validTouchDistance, LayerMask.GetMask(selectedLayerMask))) { //选择这个被射线投射到的物体 selectedObj = raycastInfo.collider.gameObject; Debug.Log("Ray cast to one OBJ\nName:" + selectedObj.name); } ) && selectedObj) { //如果射线没有(在用户设置的有效范围内)投射到任何物体 if (selectedObj == null) { Debug.Log("Didn't select any Obj\nCheck if it's out of Valid Touch Distance"); } //如果射线(在用户设置的有效范围内)投射到了物体 else { Debug.Log("Selected Obj Position in World\n" + selectedObj.transform.position); } } )) { //必须清空 selectedObj = null; } } }
[Unity3D]利用Raycast实现物体的选择与操作的更多相关文章
- JQUERY选择和操作DOM元素(利用正则表达式的方法匹配字符串中的一部分)
JQUERY选择和操作DOM元素(利用正则表达式的方法匹配字符串中的一部分) 1.匹配属性的开头 $("[attributeName^='value']"); 2.匹配属性的结尾 ...
- C#利用SqlDataAdapte对DataTable进行批量数据操作
C#利用SqlDataAdapte对DataTable进行批量数据操作,可以让我们大大简化操作数据的代码量,我们几乎不需要循环和不关心用户到底是新增还是修改,更不用编写新增和修改以及删除的SQL语句, ...
- Java网络编程:利用apache的HttpClient包进行http操作
本文介绍如何利用apache的HttpClient包进行http操作,包括get操作和post操作. 一.下面的代码是对HttpClient包的封装,以便于更好的编写应用代码. import java ...
- oracle读写文件--利用utl_file包对磁盘文件的读写操作
oracle读写文件--利用utl_file包对磁盘文件的读写操作 摘要: 用户提出一个需求,即ORACLE中的一个表存储了照片信息,字段类型为BLOB,要求能导出成文件形式. 本想写个C#程序来做, ...
- jQuery碎语(1) 基础、选择要操作的元素、处理DOM元素
1.基础 jquery对象集: $():jquery对象集合 获取jquery对象集中的元素: 使用索引获取包装器中的javascript元素:var temp = $('img[alt]')[0] ...
- 利用反射技术实现POJO的数据库操作
记得第一次写项目的时候,傻傻的数据库一张表,代码里就写一个DAO类,几张表就写几个DAO类,大量的反复代码,自己粘着都嫌烦,后来接触了Hibernate,不得不说对我们这样的小白用处还是非常大的.那么 ...
- 利用modelarts和物体检测方式识别验证码
近来有朋友让老山帮忙识别验证码.在github上查看了下,目前开源社区中主要流行以下几种验证码识别方式: tesseract-ocr模块: 这是HP实验室开发由Google 维护的开源 OCR引擎,内 ...
- Unity3D 利用欧拉角实现实体的旋转
本文系作者原创,转载请注明出处 刚刚入门U3D,也是很多东西搞不懂,最先接触的就是自己尝试去获取键盘上的GetPress之类的事件了吧 官方的API DOC也是帮了不少忙,到处吸收了各位博主的文章也是 ...
- 【Unity3D基础】让物体动起来②--UGUI鼠标点击逐帧移动
背景 上一篇通过鼠标移动的代码很简单,所以看的人也不多,但是还是要感谢“武装三藏”在博客园给出的评论和支持,希望他也能看到第二篇,其实可以很简单,而且是精灵自控制,关键是代码少是我喜欢的方式,也再次印 ...
随机推荐
- .NET 4.6.2正式发布带来众多特性
虽然大多数人的注意力都集中在.NET Core上,但与原来的.NET Framework相关的工作还在继续..NET Framework 4.6.2正式版已于近日发布,其重点是安全和WinForms/ ...
- Hyper-v 安装CentOS 7 (其他虚拟机一样参考)
平台之大势何人能挡? 带着你的Net飞奔吧!http://www.cnblogs.com/dunitian/p/4822808.html hyper-v安装很多人没弄过,我这里介绍一下.(其他虚拟机参 ...
- Canvas坐标系转换
默认坐标系与当前坐标系 canvas中的坐标是从左上角开始的,x轴沿着水平方向(按像素)向右延伸,y轴沿垂直方向向下延伸.左上角坐标为x=0,y=0的点称作原点.在默认坐标系中,每一个点的坐标都是直接 ...
- .NET Core采用的全新配置系统[9]: 为什么针对XML的支持不够好?如何改进?
物理文件是我们最常用到的原始配置的载体,最佳的配置文件格式主要由三种,它们分别是JSON.XML和INI,对应的配置源类型分别是JsonConfigurationSource.XmlConfigura ...
- android通过webview调起支付宝app支付
webview在加载网页的时候会默认调起手机自带的浏览器加载网页,用户体验不好.但当用户设置浏览器客户端(setWebViewClient)设置这样的监听事件之后,当请求url的时候就不会打开手机自带 ...
- 【Machine Learning】机器学习及其基础概念简介
机器学习及其基础概念简介 作者:白宁超 2016年12月23日21:24:51 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本系列文章是作者结 ...
- Tomcat启动报错org.springframework.web.context.ContextLoaderListener类配置错误——SHH框架
SHH框架工程,Tomcat启动报错org.springframework.web.context.ContextLoaderListener类配置错误 1.查看配置文件web.xml中是否配置.or ...
- 【Java每日一题】20170106
20170105问题解析请点击今日问题下方的"[Java每日一题]20170106"查看(问题解析在公众号首发,公众号ID:weknow619) package Jan2017; ...
- 【原】无脑操作:express + MySQL 实现CRUD
基于node.js的web开发框架express简单方便,很多项目中都在使用.这里结合MySQL数据库,实现最简单的CRUD操作. 开发环境: IDE:WebStorm DB:MySQL ------ ...
- BPM任务管理解决方案分享
一.方案概述任务是企业管理者很多意志的直接体现,对于非常规性事务较多的企业,经常存在各类公司下达的各种任务跟进难.监控难等问题,任务不是完成效果不理解,就是时间超期,甚至很多公司管理层下达的任务都不了 ...