前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >物理引擎的碰撞分组,适用2D和3D

物理引擎的碰撞分组,适用2D和3D

作者头像
Layabox Charley
发布2021-01-12 14:46:39
1.1K0
发布2021-01-12 14:46:39
举报
文章被收录于专栏:Layabox

我们在运用物理碰撞的业务逻辑时,尤其是复杂的碰撞需求时,就需要设置碰撞组,以及指定碰撞组可以与哪些碰撞组进行碰撞。而这些,需要用到位运算的知识,有一些开发者对此不太理解。为了降低开发者上手的门槛,今天就来讲一讲,如何通过位运算来理解碰撞组的碰撞关系。

设置碰撞组

2D物理的碰撞组是设置刚体的category(碰撞类别)属性。

3D物理的碰撞组是设置碰撞器的collisionGroup(所属碰撞组)属性。

无论是2D还是3D,设置碰撞组的共同规则就是采用2的N次幂作为碰撞分组的值。

所以,设置碰撞组,比较容易理解,只要是2的N次幂值,都可以用于设置碰撞组,成为区分不同碰撞组的ID。

指定可碰撞的组

2D物理通过设置刚体的mask(掩码)属性来指定可与哪些组进行碰撞。

3D物理通过设置碰撞器的canCollideWith(能碰撞的组)属性来指定可与哪些组进行碰撞。

指定碰撞组,通常有三种情况:指定单个要碰撞的组,指定多个要碰撞的组,指定不可碰撞的组。

所以,我们设置指定碰撞组的值,从这三种情况分别介绍如何进行设置。

指定单个要碰撞的组

指定单个要碰撞的组最容易理解,就是你想和哪个组碰撞,就指定哪个组的ID。

例如你的组ID是2,想与碰撞组值为8的碰撞,那mask(2D)或canCollideWith(3D)的值设置为8即可。

这样,碰撞组2就只会与碰撞组8发生物理碰撞。

指定多个要碰撞的组

如果我们想与多个碰撞组发生碰撞,那就需要运用到 按位或的运算。

3D物理处理起来比较简单,由于通常是在代码里设置值,所以,我们可以直接使用 按位或的运算表达式即可。

例如,我想与8、32、128这几个碰撞组发生碰撞。

那么,直接在代码里用 8|32|128 表示即可。如下面的代码示例所示:

  1. //指定xxx碰撞器可以与其发生碰撞的碰撞组
  2. xxx.canCollideWith = 8 | 32 | 128;

而2D物理,开发者需要直接在IDE的刚体mask属性里填写按位或运算结果,比如刚才的8|32|128的 按位或运算结果是168。mask属性值里要输入168,才会与8、32、128这几个碰撞组发生碰撞。

所以,我们可以借助第三方工具来进行按位或运算,例如Chrome的调试工具,下图就是在Chrome中进行按位或运算。

为了便于直观计算,mask值可以理解为要碰撞的类别category十进制数值的求和。 但要理解,实质是二进制的按位或位运算。

既然讲到按位或运算,这里再啰嗦几句,展开说一下按位或运算的基础。位运算底子扎实可跳过此处,阅读下个部分。

按位或运算是二进制的按位相或运算,我们填写的十进制数值,需要先转换为二进制,然后对每一位进行相或运算。

即两个二进制值相或的时候,只要对应的二进制位中有1,那结果位就为1,否则结果位为0。

如果说两个十进制转成两个二进制后,位数不一样怎么相或?补0即可。

例如十进制的1与2进行相或的位运算,十进制的2转换为二进制是10,十进制的1转换为二进制是1,那么1补为01即可。为了让大家更直观的理解,可以参考下图进行理解。

通过上图的示意说明,我们可以看到,对应起来按位或运算得到的值是11,二进制11的十进制值为3。

所以2D刚体的mask属性值为3的时候,是1与2的按位或运算结果,也就mask为3可以与1和2的碰撞分组进行碰撞。

需要了解的是,

按位或运算虽然可以计算出碰撞多个组的对应值,但物理引擎中真正决定能不能进行碰撞的,其实是按位与运算。了解完按位与的物理碰撞原理,我们就可以进一步掌握除了按位或以外的碰撞指定技巧。

下面,我们再聊聊碰撞关系的形成,

物理引擎会用碰撞组的值与指定的可碰撞组的值进行按位与运算,按位与的计算结果非0,就可以碰撞;为0,就不可以碰撞。

刚才我们将刚体的mask值设置为3,现在我们用按位与来验证一下,指定为3能否与碰撞组2发生碰撞。

首先我们将十进制的3转换成二进的11,十进制的2转换为二进制的10。当我们每一位进行相与计算时,只有当两个计算位都为1的时候,结果位才为1,否则结果位为0。我们继续用参考图辅助理解。

通过上图的示意说明,我们可以看到,11与10的二进制按位与运算结果为10,而10的十进制对应的值是2,上文讲过,非0就可以碰撞。所以,当mask值为3,category值为2的时候,就可以发生碰撞。

举一反三,如下图所示,当按位与运算结果为0的时候,就不可以碰撞。

指定不可碰撞的组

通过上文,我们了解到按位与运算才是决定碰撞的判断条件。那么我们只要通过位运算,达成这个条件,是不是就可以指定与谁碰撞了。顺着这个思路,我们尝试一下二进制异或运算。

首先,我们需要了解,-1与任何2的N次幂值按位与运算,都是幂值本身,是非0的,可以碰撞的。也就是说-1可以与所有组(2的N次幂值)进行碰撞。

那么我们用-1去异或运算任何2的N次幂值,得到的结果再与该幂值进行按位与运算,一定是为0,也就是不可以碰撞的。验证测试的过程,如下图所示。

转换为二进制的异或运算过程就不截图了,过程与之前按位与和按位或一样,只是异或运算的规则为:参与运算的两个数,对应位为“异”(值不同),则该位结果为1,否则为 0。

通过上图的验证流程,我们可以看到,通过-1去异或运算我们想排除的组,那该结果值就可以指定不想去碰撞的组。除了这些指定的组(例如上图的8和16组),其它组都是可碰撞的,如下图所示。

在项目使用的时候,3D物理,和指定多个可碰撞组一样,指定不可碰撞组,也是直接使用位运算表达式即可。例如直接在代码里用 -1^8^16 表示。如下面的代码示例所示:

  1. //指定xxx碰撞器不可以与其发生碰撞的碰撞组,本例为8和16
  2. xxx.canCollideWith = -1 ^ 8 ^ 16;

2D物理,还是要直接在LayaAir IDE中,为刚体mask属性输入结果。为了便于直观计算,mask值可以理解为不想碰撞的类别category十进制数值求和+1,再取负。但要理解,实质是二进制的异或位运算。

写在最后

关于物理的文档,无论是2D还是3D,官网上全都有,也比较全面,建议大家学习引擎前先通读一下官网文档。考虑到有开发者提问,最近几天会集中在公众号上推一下物理相关的文章,各位开发者也可以直接在官网文档(ldc2.layabox.com)中查看。

END

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Layabox 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
图像处理
图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档