Unity - 范围检测

369 阅读3分钟

什么是范围检测

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

例如:

  1. 玩家在前方5m处释放一个魔法,在此范围内的对象将收到伤害;

  2. 玩家攻击,在前方1m圆形范围内对象都会受到伤害,等等。

类似这种并没有实体物体,只想在检测的一瞬间在某一指定范围内是否让敌人受到伤害时,便可以使用范围判断。简而言之,在指定的位置进行范围判断,我们可以得到处于指定范围内的对象,目的是对对象进行处理,比如受伤,减血等。

如何进行范围检测

必备条件:想要范围检测到的对象,必须具备碰撞器!

注意:

  1. 范围检测相关API只有当执行该代码时进行一次范围检测,他是瞬时的
  2. 范围检测相关API并不会真的产生一个碰撞器,只是碰撞判断计算而已

范围检测API

盒状范围检测
  1. 参数1:立方体中心的
  2. 参数2:立方体三边大小
  3. 参数3:立方体角度
  4. 参数4:检测指定层级(不填检测所有层)
  5. 参数5:是否忽略触发器。UseGlobal- 使用全局设置  Collide-检测触发器 Ignore-忽略触发器 不填默认UseGlobal
  6. 返回值:在该范围内的触发器(得到了对象触发器就可以得到对象的所有信息)

//只检测Default层
Collider[] colliders = Physics.OverlapBox(Vector3.zero, Vector3.one, Quaternion.AngleAxis(45, Vector3.up),
            1 << LayerMask.GetMask("Default"), QueryTriggerInteraction.UseGlobal);
foreach (var collider in colliders)
{
    print(collider.gameObject.name);
}

关于层级的运算:

如果不填指定层级,那么默认是所有层;如果想只检测对应某几个层级,可以使用或运算;如果不想检测某几层可以先或后非。

Unity内部逻辑是 1<<(0-31) 然后与传入的值做与运算,如果不为0则表示这个层级需要检测。

另外可以通过名字得到层级编号:LayerMask.NameToLayer("Default"); 我们需要通过左移构建二进制,这样每个编号的层级都对应位为1的2进制数,我们通过位运算可以选中想要检测的层级。好处是一个int就可以表示所有想要检测的层级信息。

例如:(层级编号是0-31,刚好32位)

每个编号都是int数,都代表的二进制的一位

  • //0 --------- 1<<0 ======== 0000 0000 0000 0000 0000 0000 0000 00001 =1
  • //1 --------- 1<<1 ======== 0000 0000 0000 0000 0000 0000 0000 00010 =2
  • //2 --------- 1<<2 ======== 0000 0000 0000 0000 0000 0000 0000 00100 =4
  • …….
另一个盒状范围检测API
  1. 返回值:碰撞到的碰撞器数量
  2. 参数:传入一个数组进行存储
Collider[] colliders1 = new Collider[] { };
if (Physics.OverlapBoxNonAlloc(Vector3.zero, Vector3.one, colliders1) != 0)
{

}
球形范围检测
  1. 参数1:中心点
  2. 参数2:球半径
  3. 参数3:检测指定层级(不填检测所有层)
  4. 参数4:是否忽略触发器。 UseGlobal- 使用全局设置  Collide-检测触发器 Ignore-忽略触发器 不填默认UseGlobal
  5. 返回值:在该范围内的触发器
Collider[] colliders2 = Physics.OverlapSphere(Vector3.zero, 5, 1 << LayerMask.GetMask("Default"));
另一个球形范围检测
  1. 返回值:碰撞到的碰撞器数量
  2. 参数:传入一个数组进行存储
Collider[] colliders3 = new Collider[] { };
if (Physics.OverlapSphereNonAlloc(Vector3.zero, 5, colliders3) != 0)
{

}
胶囊范围检测
  1. 参数1:半圆一中心点
  2. 参数2:半圆二中心点
  3. 参数3:半圆半径
  4. 参数4:检测指定层级(不填检测所有层)
  5. 参数5:是否忽略触发器。 UseGlobal- 使用全局设置  Collide-检测触发器 Ignore-忽略触发器 不填默认UseGlobal
  6. 返回值:在该范围内的触发器
//胶囊是两个半圆加上中间的圆柱体构成。通过参数1和2,可以确定胶囊圆柱体的高以及胶囊的角度
Collider[] colliders4 = Physics.OverlapCapsule(Vector3.zero, Vector3.up, 1); 
另一个胶囊范围检测
  1. 返回值:碰撞到的碰撞器数量
  2. 参数:传入一个数组进行存储
if(Physics.OverlapCapsuleNonAlloc(Vector3.zero, Vector3.up, 1, colliders5) != 0)
{

}