unity3d————范围检测
目录
Physics.queriesHitTriggers 怎么查看是不是true?
QueryTriggerInteraction.UseGlobal 参数意味着是否检测触发器将依据全局设置 Physics.queriesHitTriggers 来决定 能不能通俗易懂讲解?
4. 非分配胶囊形范围检测(Capsule NonAlloc)
知识点一:什么是范围检测
范围检测是一种在游戏开发中常用的技术,用于判断某个特定区域内是否存在游戏对象。这种检测通常是瞬时的,用于实现如技能伤害、效果施加等不需要物理碰撞响应的交互。
-
应用场景:
- 玩家释放技能,如地刺或火球,需要判断技能范围内是否有敌人。
- 玩家使用近战攻击,需要判断周围一定范围内是否有可攻击的目标。
- 游戏中的区域触发事件,如进入特定区域触发剧情或机关。
-
特点:
- 范围检测不涉及物理碰撞的响应,如弹力或摩擦力。
- 范围检测可以是瞬时的,也可以是持续的(如每帧检测)。
知识点二:如何进行范围检测
-
必备条件:
- 想要被范围检测到的对象必须具备碰撞器(Collider),因为范围检测是基于碰撞器的形状和位置进行的。
-
注意点:
- 范围检测API只在执行该代码时进行一次检测,它是瞬时的。
- 范围检测API并不会真正产生一个碰撞器,它只是进行碰撞判断计算。
-
范围检测API:
- 盒状范围检测(OverlapBox):
- 参数:
- 参数一:立方体中心点(Vector3)
- 参数二:立方体三边大小(Vector3)
- 参数三:立方体角度(Quaternion)
- 参数四:检测指定层级(LayerMask)
- 参数五:是否忽略触发器(QueryTriggerInteraction)
- 返回值:在该范围内的碰撞器数组(Collider[])
- 参数:
- 盒状范围检测(OverlapBox):
-
其他范围检测API:
- 球状范围检测(OverlapSphere):
- 参数一:球体中心点
- 参数二:球体半径
- 参数三:检测指定层级
- 参数四:是否忽略触发器
- 返回值:在该范围内的碰撞器数组
- 胶囊状范围检测(OverlapCapsule):
- 参数一:胶囊的中心点
- 参数二:胶囊的半径
- 参数三:胶囊的高度
- 参数四:胶囊的角度
- 参数五:检测指定层级
- 参数六:是否忽略触发器
- 返回值:在该范围内的碰撞器数组
- 球状范围检测(OverlapSphere):
-
层级检测:
- 通过
LayerMask.NameToLayer
方法可以通过层级名称获取层级编号。 - 使用位运算(左移)构建二进制数来表示想要检测的层级。
- 层级编号是0~31,对应一个int数的32位。
- 通过
-
示例代码:
using UnityEngine;
public class RangeDetectionScript : MonoBehaviour
{
void Update()
{
// 盒状范围检测示例
Vector3 center = new Vector3(5, 0, 0); // 中心点
Vector3 halfExtents = new Vector3(1, 1, 1); // 半大小
Quaternion direction = Quaternion.identity; // 角度
LayerMask layerMask = (1 << LayerMask.NameToLayer("Enemy")); // 只检测"Enemy"层
Collider[] hits = Physics.OverlapBox(center, halfExtents, direction, layerMask);
foreach (var hit in hits)
{
Debug.Log("检测到对象:" + hit.gameObject.name);
}
}
}
int uiLayer = LayerMask.NameToLayer("UI");
int defaultLayer = LayerMask.NameToLayer("Default");
Collider[] colliders = Physics.OverlapBox(Vector3.zero, Vector3.one, Quaternion.AngleAxis(45, Vector3.up),
(1 << uiLayer) | (1 << defaultLayer), QueryTriggerInteraction.UseGlobal);
for (int i = 0; i < colliders.Length; i++)
{
Debug.Log(colliders[i].gameObject.name);
}
// 使用Physics.OverlapBoxNonAlloc进行范围检测,传入一个数组进行存储
int count = Physics.OverlapBoxNonAlloc(Vector3.zero, Vector3.one, colliders, Quaternion.AngleAxis(45, Vector3.up),
(1 << uiLayer) | (1 << defaultLayer), QueryTriggerInteraction.UseGlobal);
if (count > 0)
{
Debug.Log("检测到 " + count + " 个碰撞器");
}
问题:
Physics.queriesHitTriggers 怎么查看是不是true?
-
通过 Unity 编辑器界面检查:
- 打开 Unity 编辑器。
- 转到 "Edit" > "Project Settings" > "Physics"(在 Unity 2020 及以后的版本中,这个选项可能在 "Edit" > "Settings" > "Project" > "Physics" 中)。
- 查看 "Queries Hit Triggers" 选项。如果这个选项被勾选,那么
Physics.queriesHitTriggers
的值就是true
;如果没有勾选,那么它的值就是false
。
QueryTriggerInteraction.UseGlobal 参数意味着是否检测触发器将依据全局设置 Physics.queriesHitTriggers 来决定 能不能通俗易懂讲解?
这里的“全局老大”指的是Unity的一个全局设置,名字叫做 Physics.queriesHitTriggers
。这个设置决定了在物理查询中是否考虑触发器。
- 如果
Physics.queriesHitTriggers
设置为true
(开启状态),那么使用QueryTriggerInteraction.UseGlobal
时,物理查询(比如Physics.OverlapBox
)就会检测触发器。 - 如果
Physics.queriesHitTriggers
设置为false
(关闭状态),那么即使使用了QueryTriggerInteraction.UseGlobal
,物理查询也不会检测触发器。
简单来说,QueryTriggerInteraction.UseGlobal
就是让物理查询是否检测触发器,取决于Unity编辑器中的那个全局设置。如果全局设置允许检测触发器,它就检测;如果全局设置不允许,它就不检测。这样,你可以通过修改全局设置来统一控制所有物理查询是否检测触发器,而不需要在每个物理查询中单独设置。
1. 球形范围检测(Sphere)
- 用途:用于检测指定球形区域内的对象。
- 参数:
- 参数一:球体中心点(
Vector3
)。 - 参数二:球体半径(
float
)。 - 参数三:检测指定层级(
LayerMask
)。如果不填,则检测所有层。 - 参数四:是否忽略触发器(
QueryTriggerInteraction
)。UseGlobal
使用全局设置,Collide
检测触发器,Ignore
忽略触发器。
- 参数一:球体中心点(
- 返回值:在该球形范围内的碰撞器数组(
Collider[]
)。
2. 非分配球形范围检测(Sphere NonAlloc)
- 用途:与
OverlapSphere
类似,但使用预先分配的数组来存储结果,提高性能。 - 参数:
- 参数一:球体中心点(
Vector3
)。 - 参数二:球体半径(
float
)。 - 参数三:用于存储结果的碰撞器数组(
Collider[]
)。
- 参数一:球体中心点(
- 返回值:碰撞到的碰撞器数量(
int
)。
3. 胶囊形范围检测(Capsule)
- 用途:用于检测指定胶囊形区域内的对象。
- 参数:
- 参数一:胶囊的一个中心点(
Vector3
)。 - 参数二:胶囊的另一个中心点(
Vector3
)。 - 参数三:胶囊的半径(
float
)。 - 参数四:检测指定层级(
LayerMask
)。如果不填,则检测所有层。 - 参数五:是否忽略触发器(
QueryTriggerInteraction
)。UseGlobal
使用全局设置,Collide
检测触发器,Ignore
忽略触发器。
- 参数一:胶囊的一个中心点(
- 返回值:在该胶囊形范围内的碰撞器数组(
Collider[]
)。
4. 非分配胶囊形范围检测(Capsule NonAlloc)
- 用途:与
OverlapCapsule
类似,但使用预先分配的数组来存储结果,提高性能。 - 参数:
- 参数一:胶囊的一个中心点(
Vector3
)。 - 参数二:胶囊的另一个中心点(
Vector3
)。 - 参数三:胶囊的半径(
float
)。 - 参数四:用于存储结果的碰撞器数组(
Collider[]
)。
- 参数一:胶囊的一个中心点(
- 返回值:碰撞到的碰撞器数量(
int
)。
代码补全
using UnityEngine;
public class RangeDetectionScript : MonoBehaviour
{
void Start()
{
// 球形范围检测
int defaultLayer = LayerMask.NameToLayer("Default");
Collider[] colliders = Physics.OverlapSphere(Vector3.zero, 5, 1 << defaultLayer, QueryTriggerInteraction.UseGlobal);
foreach (var collider in colliders)
{
Debug.Log("球形检测到对象:" + collider.gameObject.name);
}
// 非分配球形范围检测
Collider[] sphereBuffer = new Collider[100]; // 假设最多检测100个
int sphereCount = Physics.OverlapSphereNonAlloc(Vector3.zero, 5, sphereBuffer, 1 << defaultLayer, QueryTriggerInteraction.UseGlobal);
for (int i = 0; i < sphereCount; i++)
{
Debug.Log("非分配球形检测到对象:" + sphereBuffer[i].gameObject.name);
}
// 胶囊形范围检测
int uiLayer = LayerMask.NameToLayer("UI");
colliders = Physics.OverlapCapsule(Vector3.zero, Vector3.up, 1, 1 << uiLayer, QueryTriggerInteraction.UseGlobal);
foreach (var collider in colliders)
{
Debug.Log("胶囊形检测到对象:" + collider.gameObject.name);
}
// 非分配胶囊形范围检测
Collider[] capsuleBuffer = new Collider[100]; // 假设最多检测100个
int capsuleCount = Physics.OverlapCapsuleNonAlloc(Vector3.zero, Vector3.up, 1, capsuleBuffer, 1 << uiLayer, QueryTriggerInteraction.UseGlobal);
for (int i = 0; i < capsuleCount; i++)
{
Debug.Log("非分配胶囊形检测到对象:" + capsuleBuffer[i].gameObject.name);
}
}
}
原文地址:https://blog.csdn.net/2401_82978699/article/details/143855235
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!