Unity - 射线检测
本文简要分析了Unity中各类 射线检测 的基本原理及用法,及不同检测手段的性能对比。内容包括: Ray 射线 RaycastHit 光线投射碰撞信息 Raycast 光线投射 BoxCast/Sph
Unity - 射线检测
本文简要分析了Unity中各类射线检测的基本原理及用法,及不同检测手段的性能对比。包括:Ray/RaycastHit/Raycast/XXXCast/OverlapXXX/OverlapXXXNonAlloc/常用射线Debug方法/GC消耗分析
本文简要分析了Unity中各类 射线检测 的基本原理及用法,及不同检测手段的性能对比。内容包括:
- Ray 射线
- RaycastHit 光线投射碰撞信息
- Raycast 光线投射
- BoxCast/SphereCast/CapsuleCast 体投射
- OverlapBox/OverlapSphere/OverlapCapsule 相交体
- OverlapBoxNonAlloc/OverlapSphereNonAlloc/OverlapCapsuleNonAlloc 无GC相交体
- 常用射线Debug方法
- GC消耗分析
博客园:Unity - Raycast
项目地址:Raycast - SouthBegonia
Ray 射线#
- 含义:官方解释为一条无穷的线,开始于origin点,朝向direction方向(但是,根据项目验证来看其默认长度为单位向量,只有对direction进行乘以倍率,才可实现延长射线,而非无穷)
- 用法:
Ray ray = new Ray(transform.position,transform.forward)
:从物体中心创建一条指向前方的射线rayRay camerRay = Camera.main.ScreenPointToRay(Input.mousePosition)
:产生一条从摄像机产生、经过屏幕上光标的射线。当相机为perspective模式,射线在相机梯形视野内发散;若为orthoGraphic,则为垂直与相机面的直线段(见上图)
RaycastHit 光线投射碰撞信息#
- 含义:取得从Raycast函数中得到的碰撞信息(注意不是collider哈,是包含collider信息)
- 关键变量:point、collider、rigidbody、transform
检测方法 - 线型检测#
Physics.Raycast 光线投射#
- 功能:在已有一条射线(也可无)的基础上,使用射线(新建射线)进行一定距离内的定向检测。可修改射线长度,限制其检测的Layer层,并且可以得到射线检测到的碰撞信息。但仅能检测到第一个被射线碰撞的物体,后面的物体无法被检测到
- 用法:
Raycast(transform.position, Vector.forward, distance, LayerMask.GetMask("Enemy"))
: 从物体中心点起,朝向Vector3.forward方向发射一条射线,该射线长度为distance,射线可检测到的层为Enemy层,返回bool类型Raycast(transform.position, Vector.forward, distance, out RaycastHitInformation ,LayerMask.GetMask("Enemy"))
:从物体中心点起,朝向Vector3.forward方向发射一条射线,该射线长度为distance,将碰撞信息反馈到RaycastHitInformation上,射线可检测到的层为Enemy层,返回bool类型Raycast (MyRay, distance, LayerMash.GetMask("Enemy"))
:从已有的射线MyRay出发,长度延伸至distance,射线可检测到的层为Enemy层,返回bool类型Raycast (MyRay, out RaycastHitInformation, distance, LayerMask.GetMask("Enemy"))
- 适用场合:配合相机坐标转换实现各类交互
Physics.RaycastAll 所有光线投射#
- 功能:机理用法大致同Raycast,区别在于可检测射线路径上的所有物体,返回RaycastHit[] 。其他带All后缀的方法也同理
- 用法:
RaycastHit[] hits = RaycastAll(Vector3.zero, Vector.forward, distance, LayerMask.GetMask("Enemy"))
RaycastHit[] hits = RaycastAll(MyRay, distance, LayerMash.GetMask("Enemy"))
- 适用场合:穿透性检测
Physics.Linecast 线段投射#
- 功能:建立某两点之间的射线进行检测,返回bool类型
- 用法:
Linecast(startPos, endPos, LayerMask.GetMask("Enemy"))
Linecast(startPos, endPos, out RaycastHit, LayerMask.GetMask("Enemy"))
- 适用场合:特定地点局部距离射线检测
检测方法 - 体型检测#
Physics.XXXCast 体投射#
- BoxCast 立方体投射:
- 功能:检测范围是正立方,返回bool。但是该投射用法需要万分小心,见下
- 用法:
BoxCast(originPos, halfExtents, direction, out RaycastHit, distance, LayerMask.GetMask("Enemy"))
:含义是在originPos点创建半径halfBoxLength的立方体(Vector3型,代表为正立方体在三个方向上的大小,一般用localScale/2);以朝向direction方向的平面为起始面(另一面舍弃),移动distance距离,期间经过的区域即为检测区域。(见下补充分析) - 适用场合:检测目的地是否可抵达,从而判断可移动性
- SphereCast 球体投射:
- 功能:扩展检测范围为球形,返回bool类型。
- 用法:
SphereCast(originPos, radius, direction, out RaycastHit, distance, LayerMask.GetMask("Enemy"))
:含义是在originPos点创建半径为radius的球体;以朝向direction方向的球面为起始面(另一面舍弃),移动distance距离,期间半球面经过的区域即为检测区域。那么originPos到originPos+radius内的半球区域呢?答案是舍弃,用官方的话来说,是边界而不是包围体 。(立体结构:以左右球球心为轴线,建立半径为radius、高为distance的圆柱体,左球挖去右半体积,右球添加右半体积)SphereCast (Ray, radius, out RaycastHit, distance, LayerMask.GetMask("Enemy"))
- CapsuleCast 胶囊体投射:
- 功能:检测范围是胶囊体,返回bool
- 用法:
Physics.CapsuleCast(pos1, pos2, radius, direction, out RaycastHit, maxDistance, LayerMask.GetMask("Anchor"))
:机理和SphereCast类似,在pos1、pos2两点创建半径为0.5f的球体,以此作为胶囊体模型两端;以朝向direction方向的半胶囊体面为起始面,移动maxDistance距离,期间该面经过的区域即为检测区域。(注:maxDistance和上面的distance必须非0否则无用) - 项目示例:见下图,pos1、pos2均为胶囊体两球坐标,视角右侧为forward,移动距离为0.1f,从实验结果我们不仅可以直观感受maxDistance的含义,更印证上面所说的 是边界不是包围体 ,代码:
Physics.CapsuleCast(pos1, pos2, 0.5f, Vector3.forward, out RaycastHit, 0.1f, LayerMask.GetMask("Anchor"))
- XXXCastAll 穿透投射:
- 功能:上述三种投射都只返回bool,只能检测单个物体,但是All方法的可检测射线上的所有物体,返回 RaycastHit[],产生GC极多
Physics.OverlapXXX 相交体#
- OverlapBox 相交盒:
- 功能:检测与正立方体接触、重叠、或者处于其内的所有collider
- 用法:
Collider[] hits = OverlapBox(Pos, halfExtents, Quaternion.identity, LayerMask.GetMask("Enemy"))
:以Pos点为中心创建三维半径halfExtents的正立方体,不对其进行旋转,检测层为Enemy - 适用场合:检测挂载物体范围内是否存在碰撞,常用方法
- OverlapSphere 相交球:
- 功能:检测与球体接触、重叠、或者处于其内的所有collider,即包围体。但注意,自身collider也会被检测到(下列Overlap方法都是)
- 用法:
Collider[] hits = Physics.OverlapSphere(Pos, radius, LayerMask.GetMask("Enemy"))
:以Pos为原点,创建半径为radius的球形,检测区域为整个球形包围体(实心),检测Enemy层上的物体,返回所有碰撞物体的collider而不是RaycastHit(注意:存在于球内部的物体也会被检测到)
- OverlapCapsule 相交胶囊体:
- 功能:检测与胶囊体接触、重叠、或者处于其内的所有collider
- 用法:
Collider[] hits = OverlapCapsule(pos1, pos2, radius, LayerMask.GetMask("Enemy"))
:在pos1、pos2两点创建半径为radius的球体,加上中间部分组成胶囊体,检测Enemy层
Physics.OverlapXXXNonAlloc 无GC相交体#
- OverlapBoxNonAlloc 无GC相交盒:
- 功能:实现OverlapBox的所有功能,但是另传递进colliders[] ,返回相交物体数量,从而杜绝GC的产生
- 用法:
CollAmount = Physics.OverlapBoxNonAlloc(Pos, halfExtents, colliders, Quaternion.identity, LayerMask.GetMask("Enemy"))
- OverlapSphereNonAlloc 无GC相交球:
- 功能:参考上面
- 用法:
CollAmount = OverlapSphereNonAlloc(Pos, radius, colliders, LayerMask.GetMask("Enemy"))
- OverlapCapsuleNonAlloc 无GC相交胶囊体:
- 功能:参考上面
- 用法:
CollAmount = OverlapCapsuleNonAlloc(pos1, pos2, radius, colliders, LayerMask.GetMask("Enemy"))
Physics.CheckXXX 检验体#
- CheckBox 检验盒:
- 功能:创建检测盒,检测是否被碰撞。较比与上面的检测方法,该类方法特点在于检验是否发生了碰撞,而不是取得碰撞体信息,效率最高。注此方法同样也会检验自身collider
- 用法:
IsOverlapAnyCollider = Physics.CheckBox(transform.position, transform.localScale / 2, Quaternion.identity, LayerMask.GetMask("Enemy"))
:在物体中心创建检验盒,一定大小,不旋转,检测Enemy层,若有检测到碰撞则返回True
- CheckSphere 检验球:
- 功能:参考上面
- 用法:
IsOverlapAnyCollider = Physics.CheckSphere(transform.position, radius, LayerMask.GetMask("Enemy"))
- CheckCapsule 检验胶囊体:
- 功能:参考上面
- 用法:
IsOverlapAnyCollider = Physics.CheckCapsule(pos1, pos2,radius, LayerMask.GetMask("Enemy"))
Physics.IgnoreCollision 忽略碰撞#
- 功能:屏蔽两个collider的碰撞,第三个参数为bool
- 用法:
IgnoreCollision (collider1, collider2, ignore)
DEBUG手段#
- 绘制线段:
DrawLine(startPos, endPos, color)
:绘制一条从startPos到endPos点、颜色为color的线段
- 绘制射线:
DrawRay(startPos, direction, color)
:绘制一条从startPos出发,指向direction的、颜色color的射线(默认长度为单位向量,再乘以倍率即可边长;在下一次绘制才会覆盖上一次的射线)Debug.DrawRay(startPos , direction, color, duration)
:同理绘制一定方向射线,但射线持续时间为duration :
- Gimos.DrawXXX方法:
void OnDrawGizmos() { Gizmos.DrawCube(transform.position, transform.localScale );}
GC开销问题#
从上面对几种检测方法的分析及对比其返回值不难发现,不同方法产生GC情况相差甚远,因此在工程项目上应该慎重使用。此处引用网友 HONT的测试作为GC情况参考:
- 同方法下不同模型GC开销:Box < Sphere < Capsule
- 同模型下不同方法GC开销:CheckXXX < OverlapXXX < XXXCast
参考#
- Physics.Raycast - UnityDocumentation
- Unity常用射线检测方法 - 昵称好难写
- Unity的学习笔记(射线检测) - 小鸟游
- Unity3DAPI射线检测 - 码迷
- Unity中各类物理投射性能横向比较 - HONT
作者: SouthBegonia
出处:https://www.cnblogs.com/SouthBegonia/p/11732340.html
版权:本文采用「署名-非商业性使用-相同方式共享 4.0 国际」知识共享许可协议进行许可。
Unity - 射线检测相关推荐
- unity 射线检测 碰撞点不准确的原因分析
unity 射线检测 碰撞点不准确的原因分析 射线检测的时候,出现了碰撞的那个点位置总是上下不准确,但屏幕中心位置不受影响,越远离中心,越偏移. 无论是用鼠标,还是ui上的坐标都不准确. 下面是代码 ...
- [Unity][射线检测]检测两个物体之间是否有其他物体阻挡
1.用Physics.Raycast进行射线检测 物体必须有Collider碰撞组件. //定义一条射线,起点为GO1的物体坐标,终点为GO2的物体坐标 Ray ray = new Ray(GO1.t ...
- Unity射线检测的用法总结
RayCast 射线检测 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人! (拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享. ...
- unity射线检测高速飞行的子弹是否打到敌人
利用射线检测,检测两帧子弹位置连线是否碰撞敌人,并改变敌人状态. 控制敌人射出的子弹的类如下: using System.Collections; using System.Collections.G ...
- 《Unity 射线检测》球形方向投射
球形方向投射有两种. 1.Physics.SphereCast 粗略的返回碰撞信息以及碰撞到的第一个碰撞详细信息,如果不需要获得全部的碰撞信息的话,可以用这个. 2.Physics.SphereCas ...
- 直播笔记 | Unity中射线检测详解
本文首发于洪流学堂微信公众号. 洪流学堂,学Unity快人几步 你好,我是郑洪智,你的技术探路者. 这周三我们直播剖析了Unity中射线检测的功能,以下是直播内容精华部分笔记. 完整录播:https: ...
- Unity学习之Physic.Raycast(射线检测)个人理解分享
Physics.Raycast参数 public static bool Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitIn ...
- Unity 射线与碰撞范围检测【踩坑记录】
射线检测 射线检测在2D和3D的区别比较大 一定要加上对应的Collider组件 对应的函数只检测对应的Collider,Physics.Raycast是不会检测到Collider 2D的(这个让我有 ...
- Unity中的射线检测
using System.Collections; using System.Collections.Generic; using UnityEngine;public class Lesson23 ...
- Unity 2019 射线检测失效
之前在做毕设的一个FPS游戏时,遇到了使用射线检测失效的情况,特此记录以下. 前因 在FPS游戏中,对于子弹的发射主要通过两种方式来实现. 一种可以通过实例化子弹的GameObject对其施加物理效果 ...
最新文章
- 离开英伟达仅19个月,他交出了一块国产全功能GPU
- flex textinput 输入限制(数字、字母)
- matlab学习笔记之常用命令(一)
- 攻防世界 适合做桌面_空间“狭小”的二人世界,适合情侣们做浪漫的事情
- ESLint共享配置的两种方式eslint-plugin和eslint-config
- QT中的QButtonGroup
- qt lighthouse相关
- 次短路 Yen氏算法 凸包
- Essential SQLAlchemy2th学习笔记之反射Reflection
- Yandex.Algorithm 2011 Round 2 D. Powerful array 莫队算法
- 拦截游戏窗口被移动_家中最值得购入的17款儿童游戏,教你如何从IPAD中夺回小朋友的注意力...
- 解决linux下sudo更改文件权限报错xxxis not in the sudoers file. This incident will be reported.
- android studio在夜神上打开_Android Studio 调用夜神模拟器
- 运放失真罪魁祸首之压摆率和增益带宽积
- 数据运营平台-基础架构
- 初中计算机试题戏曲进校园,戏曲进校园的作文(精选5篇)
- BLE协议栈学习2——OSAL
- 对抗拖延症最直接有效的方法
- Mac卸载postgresql
- vue一些utils
热门文章
- mysql实现开始时间和结束时间的查询
- 计算机一级exc除法函数,excel除法函数 excel除法如何表示
- linux卸载phpstudy_phpStudy Linux 面板安装教程
- 英语好文22.6.23
- Excel怎么将数据数据首尾倒置
- ansys分析遇到的几个问题解决方案【文件保存】【网格划分】【steps controls】【应力应变动画】【力负载】【干涉】【part打散】【merge合并】【分析计算量】
- 解除excel打开密码
- 关于一次生产环境项目线程数一直增长问题排查记录
- 电脑耳机没声音怎么设置?Windows系统适用
- linux创建目录快捷方式,linux创建快捷方式命令