当前位置: 首页 > news >正文

家具公司网站建设做金融的看哪些网站

家具公司网站建设,做金融的看哪些网站,如何开发游戏,wordpress 发件邮箱Unity基础-范围检测 七、范围检测 概述 范围检测(Overlap Detection)是Unity物理系统中的一种常用技术,用于在不产生实际物理碰撞或不依赖刚体的情况下,判断指定区域内是否存在或有哪些碰撞器。它常用于游戏中瞬时的攻击范围判…

Unity基础-范围检测

七、范围检测

概述

范围检测(Overlap Detection)是Unity物理系统中的一种常用技术,用于在不产生实际物理碰撞或不依赖刚体的情况下,判断指定区域内是否存在或有哪些碰撞器。它常用于游戏中瞬时的攻击范围判断、技能效果判定、区域触发等场景,例如:

  • 玩家在前方5米处释放一个范围,检测此范围内的对象是否受到伤害。
  • 玩家攻击,在前方1米圆形范围内检测对象是否受到伤害。
  • 类似这种并没有实体物体,只是想检测在指定某一范围是否让敌方受到伤害时便可以使用。

简而言之,在指定位置进行范围判断,我们可以得到处于指定范围内的对象,目的是对这些对象进行处理(比如受伤、减血等)。

必备条件与注意点

  • 必备条件:想要被范围检测到的对象,必须具备碰撞器(Collider)!
  • 注意点
    1. 范围检测相关API是瞬时的,只有当执行该代码时才进行一次范围检测。
    2. 范围检测相关API并不会真正产生一个碰撞器,它仅仅是进行碰撞判断计算。

层级 (LayerMask)

在进行范围检测时,我们通常需要检测指定层级(Layer)上的物体,以避免检测到不相关的对象,提高效率和精确性。Unity使用位运算来表示层级信息。

  • 通过名字得到层级编号:LayerMask.NameToLayer("LayerName")
  • 层级编号是0~31,刚好32位,是一个int数。
  • 每一个编号都代表二进制的一位。通过将1左移对应层级编号,可以得到该层级的二进制表示。
    • 0 层:1 << 00000 0000 0000 0000 0000 0000 0000 0001 (= 1)
    • 1 层:1 << 10000 0000 0000 0000 0000 0000 0000 0010 (= 2)
    • 2 层:1 << 20000 0000 0000 0000 0000 0000 0000 0100 (= 4)
    • 3 层:1 << 30000 0000 0000 0000 0000 0000 0000 1000 (= 8)
    • 4 层:1 << 40000 0000 0000 0000 0000 0000 0001 0000 (= 16)
  • 好处:一个int就可以表示所有想要检测的层级信息。我们可以通过位运算来选择想要检测的层级。
    • 检测单层:1 << LayerMask.NameToLayer("Default")
    • 检测多层:(1 << LayerMask.NameToLayer("Layer1")) | (1 << LayerMask.NameToLayer("Layer2"))
    • 检测所有层(默认):不传入层级参数,或传入-1

范围检测API

Unity Physics 类提供了一系列范围检测的API。它们通常分为两类:

  • 直接返回Collider[]数组的方法(有GC开销):例如 Physics.OverlapBox,每次调用会创建一个新的数组。
  • 非分配式方法(NonAlloc,无GC开销):例如 Physics.OverlapBoxNonAlloc,需要传入一个预先分配好的Collider[]数组来存储结果,推荐在频繁调用时使用。
1. 盒形范围检测 (Box Overlap)

在指定的一个立方体范围内检测所有碰撞体。

  • Physics.OverlapBox(center, halfExtents, orientation, layerMask)

    • center:立方体的中心点(世界坐标)。
    • halfExtents:立方体各边一半的长度(Vector3)。
    • orientation:立方体的旋转(Quaternion)。
    • layerMask:可选参数,要检测的层级(int)。
    • 返回值Collider[]数组,包含在该范围内的所有碰撞器。
  • Physics.OverlapBoxNonAlloc(center, halfExtents, results, orientation, layerMask)

    • results:预先分配好的Collider[]数组,用于存储检测结果。
    • 返回值int,表示实际检测到的碰撞器数量。

示例代码:

// 声明一个Collider数组用于NonAlloc方法
Collider[] boxColliders = new Collider[10]; // 使用OverlapBox(会产生GC)
Collider[] detectedColliders = Physics.OverlapBox(transform.position + Vector3.forward * 1, Vector3.one / 2, Quaternion.identity, 1 << LayerMask.NameToLayer("Default"));
if (detectedColliders.Length > 0)
{Debug.Log($"OverlapBox检测到 {detectedColliders.Length} 个碰撞体。");
}// 使用OverlapBoxNonAlloc(无GC)
int numColliders = Physics.OverlapBoxNonAlloc(transform.position + Vector3.forward * 1, Vector3.one / 2, boxColliders, Quaternion.identity, 1 << LayerMask.NameToLayer("Default"));
if (numColliders > 0)
{Debug.Log($"OverlapBoxNonAlloc检测到 {numColliders} 个碰撞体。");for (int i = 0; i < numColliders; i++){Debug.Log($"  - {boxColliders[i].name}");}
}
2. 球形范围检测 (Sphere Overlap)

在指定的一个球形范围内检测所有碰撞体。

  • Physics.OverlapSphere(position, radius, layerMask)

    • position:球体的中心点(世界坐标)。
    • radius:球体的半径。
    • layerMask:可选参数,要检测的层级(int)。
    • 返回值Collider[]数组,包含在该范围内的所有碰撞器。
  • Physics.OverlapSphereNonAlloc(position, radius, results, layerMask)

    • results:预先分配好的Collider[]数组。
    • 返回值int,表示实际检测到的碰撞器数量。

示例代码:

// 声明一个Collider数组用于NonAlloc方法
Collider[] sphereColliders = new Collider[10];// 使用OverlapSphere(会产生GC)
Collider[] detectedSphereColliders = Physics.OverlapSphere(transform.position + Vector3.down * 1, 10f, 1 << LayerMask.NameToLayer("Default"));
if (detectedSphereColliders.Length > 0)
{Debug.Log($"OverlapSphere检测到 {detectedSphereColliders.Length} 个碰撞体。");
}// 使用OverlapSphereNonAlloc(无GC)
int numSphereColliders = Physics.OverlapSphereNonAlloc(transform.position + Vector3.down * 1, 10f, sphereColliders, 1 << LayerMask.NameToLayer("Default"));
if (numSphereColliders > 0)
{Debug.Log($"OverlapSphereNonAlloc检测到 {numSphereColliders} 个碰撞体。");for (int i = 0; i < numSphereColliders; i++){Debug.Log($"  - {sphereColliders[i].name}");}
}
3. 胶囊范围检测 (Capsule Overlap)

在指定的一个胶囊体范围内检测所有碰撞体。

  • Physics.OverlapCapsule(point1, point2, radius, layerMask)

    • point1:胶囊体底部半球的中心点(世界坐标)。
    • point2:胶囊体顶部半球的中心点(世界坐标)。
    • radius:胶囊体的半径。
    • layerMask:可选参数,要检测的层级(int)。
    • 返回值Collider[]数组,包含在该范围内的所有碰撞器。
  • Physics.OverlapCapsuleNonAlloc(point1, point2, radius, results, layerMask)

    • results:预先分配好的Collider[]数组。
    • 返回值int,表示实际检测到的碰撞器数量。

示例代码:

// 声明一个Collider数组用于NonAlloc方法
Collider[] capsuleColliders = new Collider[10];// 使用OverlapCapsule(会产生GC)
Collider[] detectedCapsuleColliders = Physics.OverlapCapsule(transform.position, transform.position + Vector3.forward * 5, 0.5f, 1 << LayerMask.NameToLayer("Default"));
if (detectedCapsuleColliders.Length > 0)
{Debug.Log($"OverlapCapsule检测到 {detectedCapsuleColliders.Length} 个碰撞体。");
}// 使用OverlapCapsuleNonAlloc(无GC)
int numCapsuleColliders = Physics.OverlapCapsuleNonAlloc(transform.position, transform.position + Vector3.forward * 5, 0.5f, capsuleColliders, 1 << LayerMask.NameToLayer("Default"));
if (numCapsuleColliders > 0)
{Debug.Log($"OverlapCapsuleNonAlloc检测到 {numCapsuleColliders} 个碰撞体。");for (int i = 0; i < numCapsuleColliders; i++){Debug.Log($"  - {capsuleColliders[i].name}");}
}

实际应用示例:WASD移动与多类型范围检测

这个示例提供一个PlayController脚本,用于控制一个游戏对象的移动,并实现三种不同形状的碰撞范围检测:盒形、胶囊体和球形。移动通过Transform.Translate实现,碰撞检测则利用Unity的Physics.Overlap系列方法。

核心思想:

  • WASD 移动控制:通过获取水平和垂直输入,使用Transform.Translate方法实现游戏对象的移动。
  • 多种碰撞检测
    • Physics.OverlapBox:用于检测一个指定盒子范围内的所有碰撞体。
    • Physics.OverlapCapsule:用于检测一个指定胶囊体范围内的所有碰撞体。
    • Physics.OverlapSphere:用于检测一个指定球形范围内的所有碰撞体。
  • LayerMask (层掩码):用于过滤碰撞检测,只检测指定层上的对象,提高效率和精度。

代码实现 (PlayController.cs)

点击展开/折叠 PlayController.cs 代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PlayController : MonoBehaviour
{// 用于存储移动向量private Vector3 movement;// 移动速度,可在Inspector面板中调整public float moveSpeed = 2f; // 用于存储碰撞检测结果的Collider数组,预设大小为10个,避免频繁GCprivate Collider[] colliders = new Collider[10];// Update是MonoBehaviour的生命周期函数,每帧调用一次void Update(){// 处理对象的移动逻辑HandleMovement();// 处理对象的碰撞检测逻辑HandleOverLap();}/// <summary>/// 处理碰撞检测逻辑。/// 根据按键(J、K、L)执行不同类型的范围检测。/// </summary>void HandleOverLap(){// J键按下时执行盒形(Box)范围检测if(Input.GetKeyDown(KeyCode.J)){// Physics.OverlapBox:检测一个立方体范围内的所有碰撞体// transform.position + transform.forward * 1:检测中心点在物体前方1个单位// Vector3.one:检测盒子的尺寸为1x1x1// transform.rotation:检测盒子的旋转与物体当前旋转一致// 1 << LayerMask.NameToLayer("Default"):只检测"Default"层上的物体int numDetected = Physics.OverlapBoxNonAlloc(transform.position + transform.forward * 1, Vector3.one / 2, // 半尺寸,所以实际尺寸是Vector3.onecolliders, transform.rotation, 1 << LayerMask.NameToLayer("Default"));// 清空数组中未检测到的部分for (int i = numDetected; i < colliders.Length; i++){colliders[i] = null;}if (numDetected > 0){Debug.Log($"J键:盒形检测到 {numDetected} 个碰撞体!");}else{Debug.Log("J键:盒形检测未发现碰撞体。");}}// K键按下时执行胶囊体(Capsule)范围检测if(Input.GetKeyDown(KeyCode.K)){// Physics.OverlapCapsule:检测一个胶囊体范围内的所有碰撞体// transform.position:胶囊体的底部中心点// transform.position + transform.forward * 5:胶囊体的顶部中心点,在物体前方5个单位// 0.5f:胶囊体的半径// 1 << LayerMask.NameToLayer("Default"):只检测"Default"层上的物体int numDetected = Physics.OverlapCapsuleNonAlloc(transform.position, transform.position + transform.forward * 5, 0.5f, colliders, 1 << LayerMask.NameToLayer("Default"));// 清空数组中未检测到的部分for (int i = numDetected; i < colliders.Length; i++){colliders[i] = null;}if (numDetected > 0){Debug.Log($"K键:胶囊形检测到 {numDetected} 个碰撞体!");}else{Debug.Log("K键:胶囊形检测未发现碰撞体。");}}// L键按下时执行球形(Sphere)范围检测if(Input.GetKeyDown(KeyCode.L)){// Physics.OverlapSphere:检测一个球形范围内的所有碰撞体// transform.position + Vector3.down * 1:球体的中心点在物体下方1个单位// 10f:球体的半径为10个单位// 1 << LayerMask.NameToLayer("Default"):只检测"Default"层上的物体int numDetected = Physics.OverlapSphereNonAlloc(transform.position + Vector3.down * 1, 10f, colliders, 1 << LayerMask.NameToLayer("Default"));// 清空数组中未检测到的部分for (int i = numDetected; i < colliders.Length; i++){colliders[i] = null;}if (numDetected > 0){Debug.Log($"L键:球形检测到 {numDetected} 个碰撞体!");}else{Debug.Log("L键:球形检测未发现碰撞体。");}}// 如果检测到碰撞体,则遍历并打印所有检测到的碰撞体名称// 这里使用循环来确保只处理实际检测到的数量for(int i = 0; i < colliders.Length; i++){// 确保当前元素不为空才打印if (colliders[i] != null) {Debug.Log($"检测到碰撞体: {colliders[i].name}"); }}}/// <summary>/// 处理移动逻辑。/// 根据WASD键的输入控制物体的移动和旋转。/// </summary>void HandleMovement(){// 获取水平轴(A/D键或左右箭头)的输入float horizontal = Input.GetAxis("Horizontal");// 获取垂直轴(W/S键或上下箭头)的输入float vertical = Input.GetAxis("Vertical");// 基于垂直输入前后移动// Time.deltaTime 用于使移动速度与帧率无关transform.Translate(Vector3.forward * vertical * moveSpeed * Time.deltaTime);// 基于水平输入左右旋转// 旋转速度可以根据moveSpeed调整,或者单独设置一个rotateSpeedtransform.Rotate(Vector3.up * horizontal * moveSpeed * 50 * Time.deltaTime); // 乘以一个系数使旋转更明显}
}

使用建议

  1. 性能优化:在频繁进行范围检测的场景,优先使用NonAlloc系列方法(如OverlapBoxNonAlloc),以避免每次调用都产生新的Collider[]数组,从而减少GC(垃圾回收)开销。
  2. 精确控制:善用LayerMask参数来精确控制只检测特定层级的对象,提高检测效率和准确性。
  3. 调试可视化:在开发过程中,可以使用Debug.DrawBoxDebug.DrawLine等方法来可视化检测范围,帮助理解和调试。
  4. 触发器设置:范围检测通常用于获取范围内的对象信息,而不是模拟物理碰撞。确保被检测对象上的碰撞器如果设置为Is Trigger,则它们不会产生物理交互。
http://www.yayakq.cn/news/94099/

相关文章:

  • 建设银行员工网站微信开发哪家公司好
  • 重庆网站建设哪家做的好展示网站欣赏
  • 急切网seo的含义
  • iis php服务器搭建网站网站首页设计
  • 网站制作电话多少钱卓越网站建设的优点
  • 所有爱做网站电商企业网站建设的一般要素有哪些6
  • 西安vi设计公司免费seo排名软件
  • 哈尔滨市哪里做淘宝网站建立微信群怎么建
  • 自己做网站用哪个软件开网店需要什么条件
  • 有哪些做封面的网站南京推广平台有哪些
  • 公司网站设计图付网站建设服务费的会计分录
  • 网站建设如何站内搜索汕头网站推广多少钱
  • 聊城哪里网站做的好自己做网站好还是购买网站好
  • 做网站哪些深圳市腾讯天游科技有限公司
  • 自适应网站好建们网站上面的内容里面放照片怎么做的
  • 网站建设需要交文化建设税吗公司注册资金1000万意味着什么
  • 做的网站需要什么技术北京大型网站建设
  • 宝安做棋牌网站建设哪家服务好网站透明背景
  • 免费网站软件哪个好公司长沙建站
  • 营销型网站建设市场做一个网站需要多少时间
  • 房产类网站建设费用wordpress设计网页游戏
  • 做兼职网站的项目方案桂林市简介
  • 做自媒体网站如何免费做一个网页
  • 网站开发质量屋海东市公司网站建设
  • 网站架构图一般包括什么安徽省建筑信息平台
  • 搭建专业网站服务器服装网站建设论文范文
  • 上海网站建设找缘魁34线城市做网站推广
  • 网站的建立男和男人怎么做那个视频网站
  • 用js做网站小程序网站开发机构
  • 广州达美网站建设公司xp花生壳做自己的网站