前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >碰撞以及如何检测碰撞详解

碰撞以及如何检测碰撞详解

作者头像
酷走天涯
发布2022-05-13 15:36:21
1.2K0
发布2022-05-13 15:36:21
举报
文章被收录于专栏:每日一篇技术文章
本节的学习目标
  • 如何设置两个物理之间碰撞,有如何让两个物体不能进行碰撞
  • 怎么能检测到两个物体进行了接触(注意是接触不是碰撞)

解析

让学习成为一种习惯

首先确定一个问题: 是要用A去碰撞B 呢? 还是B 去碰撞A?

我用A去碰撞B 来讲解这个问题

能够实现物理碰撞的前提条件是什么?

两个物体都要有物理身体,我们知道游戏中物理身体有三种dynimic,static,kinematic

  • 第一个学习目标-怎么设置两个物体是否进行碰撞

节点A 和节点B 都设置了物理身体(SCNPhysicsBody),那么如图所示,SCNPhysicsBody 有三个属性如下

  1. categoryBitMask (分类掩码)
  2. collisionBitMask (碰撞掩码)
  3. contactTestBitMask (接触检测掩码)

解释一下前两个属性的作用

categoryBitMask (分类掩码)表示的物理身体的类别,如果是游戏的话,加入这个节点属于飞机 我们可以给飞机设置一个类别掩码 0b001 (最大值为15位)

collisionBitMask(碰撞掩码) 表示节点的物体身体允许被那些分类的物理身体碰撞 0b101

A 要去碰撞B, 如果要产生碰撞效果应该怎么设置呢?

代码语言:javascript
复制
ANode.physicsBody.categoryBitMask = 0b001;
BNode.physicsBody.collisionBitMask = 0b011;  // b允许那些分类与自己碰撞

如果两个掩码进行按位与运算 结果为一个非零的数字 就会产生碰撞

如果是下面的设置将不会产生碰撞

代码语言:javascript
复制
 ANode.physicsBody.categoryBitMask = 0b001;
 BNode.physicsBody.collisionBitMask = 0b110;

提示:

注意千万不要将两者的顺序搞混了,有点绕

  • 第二个学习目标-如何实现接触检测

注意一个词语'接触检测'不是碰撞检测哦!就是说两个物体是否碰撞与能否检测到接触没有关系

先来看一个代理,这个代理是物理世界的一个属性

代码语言:javascript
复制
scnView.scene?.physicsWorld.contactDelegate = self

代理SCNPhysicsContactDelegate 有三个方法

代码语言:javascript
复制
 // 开始接触
optional public func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact)
// 接触中
optional public func physicsWorld(_ world: SCNPhysicsWorld, didUpdate contact: SCNPhysicsContact)
// 接触结束
optional public func physicsWorld(_ world: SCNPhysicsWorld, didEnd contact: SCNPhysicsContact)

如果两个物体满足接触条件就会触发这个代理事件

怎么才能让其满足这个接触条件呢?

1.首先要设置物理身体(同上面一样)

如果要想A去接触B,并且要触发代理事件

代码语言:javascript
复制
 ANode.physicsBody.categoryBitMask = 0b001;
 BNode.physicsBody.contactTestBitMask = 0b101;// 允许分类掩码的对象和自己发生接触时触发回调函数

这样A 在受到力的时候,去接触B 就会去触发代理事件

完整的示例演示

第一步 创建工程(略)

运行结果如下

Scenekit_15.gif

为什么没碰撞呢?

代码语言:javascript
复制
sphereNode.physicsBody?.categoryBitMask = 1;
boxNode.physicsBody!.collisionBitMask = 0b010;

分析

1|0b10 = 0 所以不产生效果

如果改为下面的设置就会产生碰撞效果

代码语言:javascript
复制
sphereNode.physicsBody?.categoryBitMask = 0b10;

Scenekit_15.gif

  • 如何设置接触检测呢?

设置正方体的允许那些物理身体接触自己发生代理事件

代码语言:javascript
复制
boxNode.physicsBody!.collisionBitMask = 0x01;

设置球体的属性掩码

代码语言:javascript
复制
sphereNode.physicsBody?.categoryBitMask=0x01;

命令行输出如下

代码语言:javascript
复制
 '<SCNNode: 0x6080003c1a40 pos(0.000000 5.000000 -20.000000) | geometry=<SCNBox: 0x60800018ea00 | width=10.000 height=10.000 length=10.000 chamferRadius=0.000> | no child>' '<SCNNode: 0x6080003c1b30 pos(0.000000 20.000000 -20.000000) | geometry=<SCNSphere: 0x6000001448e0 | radius=1.000> | no child>' point(0.000000 9.949695 -20.000000) normal(0.000000 -1.000000 0.000000) impulse(0.000000) distance:0.050305>
  • SCNPhysicsContact 对象

属性如下

代码语言:javascript
复制
// 被碰撞的节点
open var nodeA: SCNNode { get }
// 主动碰撞的物体 这里指的是上面例子的球体
open var nodeB: SCNNode { get }
// 碰撞点的世界坐标
open var contactPoint: SCNVector3 { get }
// 碰撞点的法线
open var contactNormal: SCNVector3 { get }
// 碰撞的力度
open var collisionImpulse: CGFloat { get } // the collision impulse on nodeA
// 离世界坐标点的距离
open var penetrationDistance: CGFloat { get }

物理世界的碰撞检测就这些内容了

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 本节的学习目标
  • 解析
  • 完整的示例演示
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档