[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鼠标点击逐帧移动
背景 上一篇通过鼠标移动的代码很简单,所以看的人也不多,但是还是要感谢“武装三藏”在博客园给出的评论和支持,希望他也能看到第二篇,其实可以很简单,而且是精灵自控制,关键是代码少是我喜欢的方式,也再次印 ...
随机推荐
- 前端极易被误导的css选择器权重计算及css内联样式的妙用技巧
记得大学时候,专业课的网页设计书籍里面讲过css选择器权重的计算:id是100,class是10,html标签是5等等,然后全部加起来的和进行比较... 我只想说:真是误人子弟,害人不浅! 最近,在前 ...
- expect用法
1. [#!/usr/bin/expect] 这一行告诉操作系统脚本里的代码使用那一个shell来执行.这里的expect其实和linux下的bash.windows下的cmd是一类东西. 注意: ...
- .NET 4.6.2正式发布带来众多特性
虽然大多数人的注意力都集中在.NET Core上,但与原来的.NET Framework相关的工作还在继续..NET Framework 4.6.2正式版已于近日发布,其重点是安全和WinForms/ ...
- c#语言规范
0x00 分类 C#语言规范主要有两个来源,即我们熟知的ECMA规范和微软的规范.尽管C#的ECMA规范已经前后修订4次,但其内容仅仅到C# 2.0为止.所以慕容为了方便自己和各位方便查询,在此将常见 ...
- 趣说游戏AI开发:曼哈顿街角的A*算法
0x00 前言 请叫我标题党!请叫我标题党!请叫我标题党!因为下面的文字既不发生在美国曼哈顿,也不是一个讲述美国梦的故事.相反,这可能只是一篇没有那么枯燥的关于算法的文章.A星算法,这个在游戏寻路开发 ...
- 内存映射文件MemoryMappedFile使用
参考资料: http://blog.csdn.net/bitfan/article/details/4438458 所谓内存映射文件,其实就是在内存中开辟出一块存放数据的专用区域,这区域往往与硬盘上特 ...
- Sass之坑Compass编译报错
前段时间在使用Compass时遇到了其为难处理的一个坑,现记录到博客希望能帮助到各位. 一.问题: 利用Koala或者是gulp编译提示如下,截图为koala编译提示错误: 二.解决办法 从问题截图上 ...
- 《动手实现一个网页加载进度loading》
loading随处可见,比如一个app经常会有下拉刷新,上拉加载的功能,在刷新和加载的过程中为了让用户感知到 load 的过程,我们会使用一些过渡动画来表达.最常见的比如"转圈圈" ...
- Atitit.技术管理者要不要自己做开发??
Atitit.技术管理者要不要自己做开发?? 1. 为什么很多管理者不能自己亲自做了1 1.1. 沟通成本多了1 1.2. .组织分散. 1 1.3. 会议多 .协调多 1 1.4. 问题的根源在于我 ...
- SymmetricDS 快速和灵活的数据库复制
开始谈谈开源的SymmetricDS,谈谈实际使用中,遇到的一些问题和解决办法.持续更新: SymmetricDS 快速和灵活的数据库复制 实际使用 和 埋过的坑 (一)知识篇 SymmetricDS ...