Unity物理系统之范围检测详解

一、知识回顾 物理系统之碰撞检测

1.碰撞产生的必要条件

(1)至少一个物体有刚体
(2)两个物体都必须有碰撞器

2.碰撞和触发

(1)碰撞会产生实际的物理效果

(2)触发看起来不会产生碰撞但是可以通过函数监听触发

3.使用场景

        碰撞检测主要用于实体物体之间产生物理效果时使用

二、什么是范围检测

1.使用场景

        游戏中瞬时的攻击范围判断一般会使用范围检测

2.常用游戏案例

(1)玩家在前方10m处释放一个魔法,在此处范围内的对象将受到魔法伤害

(2)玩家攻击,在前方1米圆形范围内对象都受到伤害等等

3.总结

        没有实体物体 只想要检测在指定某一范围是否让敌方受到伤害时 便可以使用范围判断。在指定位置进行范围判断,我们可以得到处于指定范围内的对象,目的是对对象进行处理,比如受伤 减血等等

三、如何进行范围检测

1.必备条件

        想要被范围检测到的对象,必须具备碰撞器

2.注意点

(1)范围检测相关API,只有当执行该句代码时,进行一次范围检测,它是瞬时的

(2)范围检测相关API,并不会真正产生一个碰撞器,只是碰撞判断计算而已

3.范围检测API

3.1盒状范围检测

参数一:立方体中心点
参数二:立方体三边大小
参数三:立方体角度
参数四:检测指定层级(不填检测所有层)
参数五:是否忽略触发器

        UseGlobal-使用全局设置

        Collide-检测触发器

        Ignore-忽略触发器

        不填默认使用UseGlobal
返回值:在该范围内的触发器(得到了对象触发器就可以得到对象的所有信息)

print(LayerMask.NameToLayer("UI"));
Collider[] colliders = Physics.OverlapBox( Vector3.zero, Vector3.one, Quaternion.AngleAxis(45, Vector3.up), 
                    1 << LayerMask.NameToLayer("UI") |
                    1 << LayerMask.NameToLayer("Default"), QueryTriggerInteraction.UseGlobal);

for (int i = 0; i < colliders.Length; i++)
{
    print(colliders[i].gameObject.name);
}

返回值:碰撞到的碰撞器数量

参数:传入一个数组进行存储

Physics.OverlapBoxNonAlloc()
if(Physics.OverlapBoxNonAlloc(Vector3.zero, Vector3.one, colliders) != 0)
{

}

3.2球形范围检测

参数一:中心点
参数二:球半径
参数三:检测指定层级(不填检测所有层)
参数四:是否忽略触发器

UseGlobal-使用全局设置

Collide-检测触发器

Ignore-忽略触发器

不填默认使用UseGlobal
返回值:在该范围内的触发器(得到了对象触发器就可以得到对象的所有信息)

colliders = Physics.OverlapSphere(Vector3.zero, 5, 1 << LayerMask.NameToLayer("Default"));

返回值:碰撞到的碰撞器数量

参数:传入一个数组进行存储        

Physics.OverlapSphereNonAlloc
if( Physics.OverlapSphereNonAlloc(Vector3.zero, 5, colliders) != 0 )
{

}

3.3胶囊范围检测

参数一:半圆一中心点
参数二:半圆二中心点
参数三:半圆半径
参数四:检测指定层级(不填检测所有层)
参数五:是否忽略触发器

UseGlobal-使用全局设置

Collide-检测触发器

Ignore-忽略触发器

不填默认使用UseGlobal
返回值:在该范围内的触发器(得到了对象触发器就可以得到对象的所有信息)

 colliders = Physics.OverlapCapsule(Vector3.zero, Vector3.up, 1, 1 << LayerMask.NameToLayer("UI"), QueryTriggerInteraction.UseGlobal);

返回值:碰撞到的碰撞器数量

参数:传入一个数组进行存储

Physics.OverlapCapsuleNonAlloc
if ( Physics.OverlapCapsuleNonAlloc(Vector3.zero, Vector3.up, 1, colliders ) != 0 )
{

}

4.层级以及层级编号知识点补充

通过名字得到层级编号

LayerMask.NameToLayer

        通过编号左移构建二进制数,这样每一个编号的层级 都是 对应位为1的2进制数,我们通过 位运算 可以选择想要检测层级,好处 一个int 就可以表示所有想要检测的层级信息。

        层级编号是 0~31 刚好32位,是一个int数,每一个编号 代表的 都是二进制的一位


 

四、练习题

1.题目

        世界坐标原点有一个立方体,键盘WASD键可以控制其前后移动和旋转
        1.按J键在立方体面朝向前方1米处进行立方体范围检测
        2.按K键在立方体前面5米范围内进行胶囊范围检测
        3.按L键以立方体脚下为原点,半径10米内进行球形范围检测

2.代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson22_Exercises : MonoBehaviour
{
    //移动速度
    public float moveSpeed;
    //旋转速度
    public float roundSpeed;

    void Update()
    {
        //位移
        this.transform.Translate(Vector3.forward * Time.deltaTime * moveSpeed * Input.GetAxis("Vertical"));
        //旋转
        this.transform.Rotate(Vector3.up, Input.GetAxis("Horizontal") * roundSpeed * Time.deltaTime);

        if( Input.GetKeyDown(KeyCode.J) )
        {
            Collider[] colliders = Physics.OverlapBox( this.transform.position + this.transform.forward, 
                                                       Vector3.one*0.5f, //长宽高的一半
                                                       this.transform.rotation, 
                                                       1 << LayerMask.NameToLayer("Monster"));
            for (int i = 0; i < colliders.Length; i++)
            {
                print("物体受伤" + colliders[i].gameObject.name);
            }
        }

        if(Input.GetKeyDown(KeyCode.K))
        {
            Collider[] colliders = Physics.OverlapCapsule(this.transform.position,
                                                         this.transform.position + this.transform.forward * 5,
                                                         0.5f,
                                                         1 << LayerMask.NameToLayer("Monster"));
            for (int i = 0; i < colliders.Length; i++)
            {
                print("物体受伤" + colliders[i].gameObject.name);
            }
        }

        if(Input.GetKeyDown(KeyCode.L))
        {
            Collider[] colliders = Physics.OverlapSphere(this.transform.position, 10, 1 << LayerMask.NameToLayer("Monster"));
            for (int i = 0; i < colliders.Length; i++)
            {
                print("物体受伤" + colliders[i].gameObject.name);
            }
        }
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值