unity3d————射线检测

2

  1. 射线(Ray)

    • Ray结构体包含两个主要部分:一个起点(origin)和一个方向(direction
  2. 射线检测(Raycast)

    • Physics.Raycast方法用于执行射线检测。
    • 参数包括:
      • 射线(Ray或起点和方向向量)。
      • 检测的最大距离。
      • 检测指定层级(使用LayerMask)。
      • 是否忽略触发器(QueryTriggerInteraction)。
  3. LayerMask

    • 用于指定射线检测应该考虑哪些层级的物体。
    • LayerMask.NameToLayer方法将层级的名称转换为对应的层级索引。
  4. QueryTriggerInteraction

    • 控制射线检测是否应该与触发器(Collider带有Is Trigger属性的)发生交互。
    • 选项包括:
      • UseGlobal:使用全局设置(Physics.queriesHitTriggers)。
      • Collide:总是与触发器交互。
      • Ignore:忽略触发器。
  5. 重载方法

    • Physics.Raycast有多个重载版本,允许不同的参数传递方式。

代码示例分析:

// 1. 最原始的射线检测
// 准备一条射线
Ray r3 = new Ray(Vector3.zero, Vector3.forward);
// 进行射线检测 如果碰撞到对象 返回true
// 参数一:射线
// 参数二: 检测的最大距离 超出这个距离不检测
// 参数三:检测指定层级(不填检测所有层)
// 参数四:是否忽略触发器 UseGlobal-使用全局设置 Collide-检测触发器 Ignore-忽略触发器 不填使用UseGlobal
// 返回值:bool 当碰撞到对象时 返回 true 没有 返回falseif (Physics.Raycast(r3, 1000, 1 << LayerMask.NameToLayer("Monster"), QueryTriggerInteraction.UseGlobal))
{print("碰撞到了对象");
}// 还有一种重载 不用传入 射线 直接传入起点 和 方向 也可以用于判断
// 就是把 第一个参数射线 变成了 射线的 两个点 一个起点 一个方向
if (Physics.Raycast(Vector3.zero, Vector3.forward, 1000, 1 << LayerMask.NameToLayer("Monster"), QueryTriggerInteraction.UseGlobal))
{print("碰撞到了对象2");
}

3.

法线与射线的关系

  1. 碰撞检测

    • 当射线投射(Raycasting)与物体发生碰撞时,法线提供了碰撞点处表面的朝向信息。
    • 法线的方向可以帮助确定物体表面的朝向,这对于物理模拟(如反弹、摩擦等)和视觉效果(如反射、折射等)非常重要。
  2. 光照和着色

    • 在渲染过程中,法线用于计算物体在不同光照条件下的明暗变化。
    • 法线与光源方向的夹角影响光照强度,从而影响物体的颜色和亮度。

法线的作用

  • 表面朝向:法线垂直于物体表面,指向物体外部。这有助于确定物体表面的朝向。
  • 光照计算:在光照模型中,法线用于计算光照效果,如漫反射、镜面反射等。
  • 碰撞处理:在物理模拟中,法线用于计算碰撞后物体的反弹方向和摩擦力。

在射线投射中的法线

在射线投射中,如果射线与物体发生碰撞,RaycastHit 结构体中的 normal 属性会存储碰撞点处物体表面的法线。这可以用于:

  • 确定碰撞点的朝向:通过法线的方向,可以知道物体在碰撞点的朝向。
  • 物理模拟:在物理引擎中,法线用于计算碰撞后的反弹方向和摩擦力。
  • 视觉效果:在渲染中,法线用于计算光照效果,如反射和折射。 

在 Unity 中,您可以使用 RaycastHit 结构体中的 normal 属性来获取碰撞点处的法线。

  1. Raycasting (射线投射):

    • Physics.Raycast 是 Unity 中用于检测射线是否与游戏世界中的物体发生碰撞的方法。
    • 射线有一个起点和一个方向,可以检测一定距离内的碰撞。
  2. RaycastHit (射线击中信息):

    • RaycastHit 是一个结构体,用于存储射线投射的结果。
    • 当射线与物体发生碰撞时,RaycastHit 会包含碰撞点、法线、碰撞物体等信息。
  3. LayerMask (层级遮罩):

    • LayerMask 用于指定射线投射应该检测哪些层级的物体。
    • 通过 LayerMask.NameToLayer 方法可以将层级的名称转换为层级索引。
  4. QueryTriggerInteraction (触发器交互):

    • 控制射线投射是否应该与触发器发生交互。
    • UseGlobal 使用全局设置,Collide 表示检测触发器,Ignore 表示忽略触发器。
  5. out 参数:

    • out 关键字用于定义一个输出参数,允许方法返回额外的信息。
  6. 重载方法:

    • Physics.Raycast 有多个重载版本,可以传入射线或起点和方向。

   代码示例分析: 

using UnityEngine;public class RaycastExample : MonoBehaviour
{void Update(){// 定义射线的起点和方向Ray ray = new Ray(transform.position, transform.forward);// 物体信息类 RaycastHitRaycastHit hitInfo;// 射线// RaycastHit 是结构体,是值类型。Unity 会通过 out 关键字在函数内部处理后,得到碰撞数据后返回到该参数中// 距离// 检测指定层级(不填检测所有层)// 是否忽略触发器 UseGlobal-使用全局设置 Collide-检测触发器 Ignore-忽略触发器 不填使用 UseGlobalif (Physics.Raycast(ray, out hitInfo, 1000, 1 << LayerMask.NameToLayer("Monster"), QueryTriggerInteraction.UseGlobal)){Debug.Log("碰撞到了物体 得到了信息");// 碰撞器信息Debug.Log("碰撞到物体的名字: " + hitInfo.collider.gameObject.name);// 碰撞到的点Debug.Log("碰撞到的点: " + hitInfo.point);// 法线信息Debug.Log("法线信息: " + hitInfo.normal);// 得到碰撞到对象的位置Debug.Log("碰撞到对象的位置: " + hitInfo.transform.position);// 得到碰撞到对象 离自己的距离Debug.Log("离自己的距离: " + hitInfo.distance);}else{Debug.Log("没有碰撞到任何物体");}// 另一种重载,不用传入射线,直接传入起点和方向if (Physics.Raycast(Vector3.zero, Vector3.forward, out hitInfo, 1000, 1 << LayerMask.NameToLayer("Monster"), QueryTriggerInteraction.UseGlobal)){Debug.Log("使用起点和方向的射线投射也碰撞到了物体");}else{Debug.Log("使用起点和方向的射线投射没有碰撞到任何物体");}}
}

 4.

  1. Physics.RaycastAll 方法用于从射线发出点开始,沿着射线方向检测所有碰撞到的物体。它返回一个 RaycastHit 数组,每个元素包含碰撞信息。

  2. 参数说明:

    • 参数一:射线(Ray 或 Vector3 起点和 Vector3 方向的组合)。
    • 参数二:最大检测距离。
    • 参数三:层级掩码(LayerMask),用于指定检测哪些层级的物体。
    • 参数四:触发器交互设置(QueryTriggerInteraction),用于决定是否检测触发器。
  3. RaycastHit 结构体包含碰撞信息,如碰撞点、碰撞物体的 GameObject、碰撞法线等。

  4. Physics.RaycastAll 有一个重载版本,允许直接使用起点和方向来创建射线。

  5. Physics.RaycastNonAlloc 方法用于检测射线与物体的碰撞,但它不会分配新的数组,而是使用传入的数组来存储碰撞信息。如果发生碰撞,它会返回碰撞的数量。

根据这些知识点,下面是补全的代码:

// 定义射线的起点和方向
Ray ray = new Ray(Vector3.zero, Vector3.forward);// 定义最大检测距离
float maxDistance = 1000f;// 定义层级掩码,只检测名为"Monster"的层
LayerMask monsterLayer = 1 << LayerMask.NameToLayer("Monster");// 使用Physics.RaycastAll检测射线与物体的碰撞
RaycastHit[] hits = Physics.RaycastAll(ray, maxDistance, monsterLayer, QueryTriggerInteraction.UseGlobal);// 遍历所有碰撞结果并打印碰撞物体的名称
for (int i = 0; i < hits.Length; i++)
{print("碰到的所有物体 名字分别是 " + hits[i].collider.gameObject.name);
}// 使用重载版本的Physics.RaycastAll,直接传入起点和方向
hits = Physics.RaycastAll(Vector3.zero, Vector3.forward, maxDistance, monsterLayer, QueryTriggerInteraction.UseGlobal);// 使用Physics.RaycastNonAlloc检测射线与物体的碰撞,并使用已有的数组来存储结果
if (Physics.RaycastNonAlloc(ray, hits, maxDistance, monsterLayer, QueryTriggerInteraction.UseGlobal) > 0)
{// 如果有碰撞发生,遍历碰撞结果并打印碰撞物体的名称for (int i = 0; i < hits.Length; i++){if (hits[i].collider != null) // 确保hits数组中的元素不是空的{print("碰撞到的物体 名字是 " + hits[i].collider.gameObject.name);}}
}

5.

  1. 参数类型明确性

    • 在使用 Physics.Raycast 或相关方法时,需要明确每个参数的类型和它们代表的意义。
    • 第二个参数应该是一个 float 类型,代表射线的最大检测距离。
    • 第三个参数应该是一个 int 类型,代表层级掩码(LayerMask),用于指定检测哪些层级的物体。
  2. 错误的参数传递

    • 在您的示例中,Physics.Raycast(r3, 1000, 1 << LayerMask.NameToLayer("Monster")) 是错误的,因为第二个参数 1000 应该是一个 float 类型,而不是 int 类型。
  3. 正确的参数传递

    • 正确的调用方式应该是将距离参数传递为 float 类型,例如 Physics.Raycast(r3, maxDistance, 1 << LayerMask.NameToLayer("Monster")),其中 maxDistance 是一个 float 类型的变量。
  4. 层级掩码的使用

    • 层级掩码(LayerMask)是一个 int 类型的位掩码,用于指定哪些层级的物体应该被射线检测到。
    • 使用 1 << LayerMask.NameToLayer("Monster") 可以创建一个只检测名为 "Monster" 层的层级掩码。
  5. 参数顺序

    • 确保参数的顺序正确,即射线、距离、层级掩码、触发器交互设置。
  6. 触发器交互设置

    • QueryTriggerInteraction 枚举用于控制是否检测触发器。它可以是 UseGlobalCollide 或 Ignore

总结这些知识点,您可以修正代码如下:

// 定义射线
Ray r3 = new Ray(Vector3.zero, Vector3.forward);// 定义最大检测距离,注意这里是float类型
float maxDistance = 1000.0f;// 定义层级掩码,只检测名为"Monster"的层
LayerMask monsterLayer = 1 << LayerMask.NameToLayer("Monster");// 正确的调用方式,注意距离参数是float类型
if (Physics.Raycast(r3, maxDistance, monsterLayer))
{// 碰撞检测到的逻辑
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/19377.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

PMP–一、二、三模、冲刺–分类--5.范围管理--技巧--需求跟踪矩阵

文章目录 技巧一模反例不选“需求跟踪矩阵”4.整合管理86、 [单选] 项目经理加入一个项目&#xff0c;但项目经理在该项目所涉及的行业经验有限&#xff0c;在该项目的整个生命周期中&#xff0c;项目经理精心记录每个差距、问题和不一致性。但是&#xff0c;无论项目经理如何记…

掌握Golang中的数据竞争检测:runtime/race包全面教程

掌握Golang中的数据竞争检测&#xff1a;runtime/race包全面教程 引言数据竞争问题概述数据竞争的定义数据竞争对程序的影响常见数据竞争场景 Golang runtime/race包概述runtime/race包简介启用数据竞争检测使用 go run使用 go build使用 go test 基本用法与示例单元测试中的使…

ThreadLocal父子线程、线程池数据传递解决

多线程并发数据访问&#xff0c;确保数据安全至关重要&#xff0c;常用保证数据安全的方法有对代码synchronized锁、Lock锁&#xff0c;以及基于CAS的原子类&#xff0c;这些都是通过数据共享保障数据安全的&#xff0c;今天聊一聊另一种方案ThreadLocal线程副本&#xff0c;实…

Docker 从入门到精通全攻略

一、Docker 初印象 Docker 诞生于 2013 年&#xff0c;由 dotCloud 公司发起&#xff0c;最初是一个公司内部项目。其诞生背景源于程序员们苦于应用部署环境的复杂性&#xff0c;开发、测试、部署过程中各种库的依赖纷繁复杂&#xff0c;版本差异以及测试环境与部署环境不一致等…

WordPress设置自动更新CSS版本号

WordPress 通常会在引用 CSS 文件时添加版本号参数&#xff08;?verx.x.x&#xff09;。如果版本号未更新&#xff0c;浏览器可能继续加载旧的文件。 解决方法&#xff1a;确保你在 functions.php 文件中正确加载了 CSS 文件&#xff0c;并动态更新版本号。例如在functions.p…

达梦 DG

监视器 switchover 关于达梦DG switchover的细节&#xff0c;以下是一些关键步骤和注意事项&#xff1a; • 切换前检查确认&#xff1a; • 确认数据库版本和DG架构&#xff0c;包括IP信息及切换角色前后的情况。 • 检查DG切换方式&#xff0c;是switch over还是fail ove…

c#基本数据类型占用字节长度/取值范围/对应.net类型

具体前往&#xff1a;c#基本数据类型占用字节数/取值范围/包装类-各基本类型.net类型,占用bit位数,默认值及取值范围

多品牌NVR管理工具/设备EasyNVR多个NVR同时管理支持RTSP接入

在当今数字化浪潮席卷全球的背景下&#xff0c;视频监控行业正经历着前所未有的变革。传统的本地录像存储模式正逐步向云端集中管理转型&#xff0c;这一技术的飞跃不仅极大地提升了监控效率与安全性&#xff0c;更为各行各业的智能化管理开辟了新路径。在这一转型过程中&#…

初学者指南:知识库问答(KBQA)多跳路径的核心与应用

初学者指南&#xff1a;知识库问答&#xff08;KBQA&#xff09;多跳路径的核心与应用 知识库问答&#xff08;Knowledge Base Question Answering, KBQA&#xff09;旨在利用结构化知识库&#xff08;如Wikidata、Freebase&#xff09;回答自然语言问题。在实际应用中&#x…

利用Python爬虫获取淘宝店铺详情

在数字化时代&#xff0c;数据已成为企业最宝贵的资产之一。对于电商平台&#xff0c;尤其是淘宝这样的大型电商平台&#xff0c;店铺详情数据的获取和分析对于商家来说至关重要。它不仅可以帮助商家了解市场趋势&#xff0c;还可以优化营销策略&#xff0c;提升销售业绩。本文…

卡尔曼滤波学习资料汇总

卡尔曼滤波学习资料汇总 其实&#xff0c;当初的目的&#xff0c;是为了写 MPU6050 的代码的&#xff0c;然后不知不觉学了那么多&#xff0c;也是因为好奇、感兴趣吧 有些还没看完&#xff0c;之后笔记也会同步更新的 学习原始材料 【卡尔曼滤波器】1_递归算法_Recursive P…

【HCIP]——OSPF综合实验

题目 实验需求 根据上图可得&#xff0c;实验需求为&#xff1a; 1.R5作为ISP&#xff1a;其上只能配置IP地址&#xff1b;R4作为企业边界路由器&#xff0c;出口公网地址需要通过PPP协议获取&#xff0c;并进行CHAP认证。&#xff08;PS&#xff1a;因PPP协议尚未学习&#…

MarkDown笔记记录app——待更新

1&#xff0c;语雀&#xff1a; 容易整理&#xff0c;直接上手&#xff0c;直接导出到csdn或者是github中 2&#xff0c;notion&#xff1a;注意及时清理 平时主要资料整理部分&#xff0c;注意每个page里面包含子page不能超过5MB&#xff0c; 所有的老资料笔记需要导出为htm…

vxe-table 4.9+ 实现在表格列中直接拖拽排序,列拖拽排序

Vxe UI vue vxe-table v4.9 实现在表格列中直接拖拽排序&#xff0c;列拖拽排序 安装 npm install vxe-pc-ui4.3.3 vxe-table4.9.0main.js // ... import VxeUI from vxe-pc-ui import vxe-pc-ui/lib/style.css import VxeUITable from vxe-table import vxe-table/lib/styl…

《勇者斗恶龙3:HD-2D重制版》找幽灵船攻略分享

《勇者斗恶龙3&#xff1a;HD-2D重制版》中的幽灵船是游戏里非常独特的一个区域&#xff0c;而想要找到幽灵船的话还是比较麻烦的&#xff0c;首先是听到关于幽灵船在世界海域上航行的传闻&#xff0c;包括在海盗巢穴中&#xff0c;但幽灵船的出现有一些具体条件。 勇者斗恶龙3…

《通往人工智能深度学习专家之路:全面解析学习路线图》

《通往人工智能深度学习专家之路&#xff1a;全面解析学习路线图》 一、人工智能深度学习简介1.1 人工智能与深度学习的关系1.2 深度学习的应用领域1.3 深度学习的重要性 二、深度学习路线图总览2.1 学习路线图的结构2.2 各阶段学习目标与重点 三、深度学习基础阶段3.1 数学基础…

力扣题解661 图片平滑器

题目&#xff08;简单&#xff09; 图像平滑器 是大小为 3 x 3 的过滤器&#xff0c;用于对图像的每个单元格平滑处理&#xff0c;平滑处理后单元格的值为该单元格的平均灰度。 每个单元格的 平均灰度 定义为&#xff1a;该单元格自身及其周围的 8 个单元格的平均值&#xff0c…

基于SpringBoot的“致远汽车租赁系统”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“致远汽车租赁系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 致远汽车租赁系统总体功能模块图 系统首页界面…

DSP28335 DMA 官方例程解析以及拓展(一)

文章目录 概述官方例程1 内部RAM to RAM Example_2833xDMA_ram_to_ram源码解析 要点方法拓展 外部固定地址 TO RAM完整程序: 对DMA 和 DMA有关的API请看这篇文章 DSP28335 DMA API介绍 概述 本篇主要分析官方提供的28335 DMA 有关的例程 在此基础上有一定的拓展 官方例程1 内…

【Java SE】JDBC

JDBC&#xff08;Java DataBase Connectivity&#xff09;是一套用于在 Java 中操作关系型数据库的 API。它允许开发者使用统一的 Java 代码来访问不同的关系型数据库。 JDBC 的本质&#xff1a;JDBC 是由官方&#xff08;Sun 公司&#xff09;定义的一套接口规范&#xff0c;…