SCNPhysicsBody学习

创建SCNPhysicsBody

+ (instancetype)staticBody;

staticBody是一个不受外力或碰撞影响的物体,不能移动。比如地板、墙壁等。
必须把它附加到SCNNodephysicsBody属性上。附加到节点上后,会自动为节点创建物理形状。
对于包含自定义几何的节点,SceneKit出于对准确性和性能的折衷,创建的只是一个近似的物理形状。基于基本几何类(SCNBox, SCNSphere, SCNPyramid, SCNCone, SCNCylinder, 或者 SCNCapsule)的节点体验效果最好。
如果想手动创建物理形状,使用SCNPhysicsShape类方法。

+ (instancetype)dynamicBody;

dynamicBody是一个可以受力和碰撞影响的物体。
其余同staticBody

+ (instancetype)kinematicBody;

kinematicBody是一个不受外力或碰撞影响的物理实体,但它会在移动时造成碰撞影响其他物体。
其余同staticBody

举一个简单的例子:桌球游戏中,球桌是staticBody,球是dynamicBody,球杆是kinematicBody

+ (instancetype)bodyWithType:(SCNPhysicsBodyType)type shape:(nullable SCNPhysicsShape *)shape;

根据指定类型和形状创建一个物理实体。
如果将nil传递给shape,在将它附加到节点上时,会自动根据节点创建物理性状。
其余同staticBody

定义力如何影响物体

@property(nonatomic, retain) SCNPhysicsShape *physicsShape;

在碰撞检测中物体的形状。
在碰撞检测时往往没必要用真实的几何形状,用简单的形状可以得到更好的性能。通常我们把physicsShape设置为一个简单的形状,把真实的几何形状放里面。
当然对于精准的碰撞测试,我们需要使用更详细的几何图形。
创建物理图形的细节参见SCNPhysicsShape类。

@property(nonatomic) SCNPhysicsBodyType type;

typedef enum SCNPhysicsBodyType : NSInteger {
    SCNPhysicsBodyTypeStatic,
    SCNPhysicsBodyTypeDynamic,
    SCNPhysicsBodyTypeKinematic
} SCNPhysicsBodyType;

物体的类型,枚举类型,就是上文中的staticBodydynamicBodykinematicBody

@property(nonatomic) SCNVector3 velocityFactor;

移动因子
例如,可以通过将其速度因子设置为{1.0,1.0,0.0},从而使物体只能在在两个维度中移动。

@property(nonatomic) SCNVector3 angularVelocityFactor;

旋转因子
例如,可以通过将其旋转因子设置为{0.0,1.0,0.0},从而使物体只能在一个轴上旋转。

@property(nonatomic, getter=isAffectedByGravity) BOOL affectedByGravity;

是否受重力影响
这个属性默认是YES

定义物体的属性

@property(nonatomic) CGFloat mass;

质量,以千克为单位。
质量会影响物体对力的反应。dynamicBody的默认质量是1。staticBodykinematicBody的默认质量为0,但它们不受质量影响。
物理模拟的影响取决于不同物体的相对质量,而不是绝对值。所以你不需要对应用程序中的物体进行实际测量。

@property(nonatomic) CGFloat charge;

电荷,以库仑为单位。
当受到电场或磁场影响时,带有正电荷或负电荷的物体的行为会不同。三种类型的物体的默认电荷均为0,即不会受电场和磁场的影响。
同样不需要去做实际测量。

@property(nonatomic) CGFloat friction;

滑动摩擦力。
当两个物体接触并滑动时,摩擦力决定它们对运动的阻力。如果两个物体的摩擦力都是0,它们会自由地滑动。如果都是1,就不会滑动。默认值为0.5。

@property(nonatomic) CGFloat rollingFriction;

滚动摩擦力。
圆型物体在滚动时的阻力。如果是0,将持续滚动而不减速,除非另有动作。如果是1,将无法滚动。默认值为0。

@property(nonatomic) CGFloat restitution;

可以理解成弹性。
决定了物体在碰撞过程中会保留多少动能。比如一个球掉在地面,如果是0,就不会反弹。如果是1,就会弹回原处。如果大于1,它会弹得比原来更高。默认值是0.5。

@property(nonatomic) CGFloat damping;

移动阻尼。
类似空气摩擦或水摩擦,就是在移动中的阻力。与其他的力独立并共存。如果是0,表示没有阻力,不会造成速度损失。如果是1,就会阻止物体移动。默认值是0.1。

@property(nonatomic) CGFloat angularDamping;

旋转阻尼。
同上,影响物体在旋转中的阻力。默认值是0.1。

@property(nonatomic) SCNVector3 momentOfInertia;

惯性矩阵。
比如x<y时,表示物体在x轴上旋转时的惯性更小,就能够更加自由旋转。
默认情况下,SceneKit会根据物体的形状和质量自动确定惯性矩阵。如果要自定义,需要设置usesDefaultMomentOfInertiaNO

@property(nonatomic) BOOL usesDefaultMomentOfInertia;

是否自动计算物体的惯性矩矩形。
YES为自动计算,NO为自定义设置。

分类

@property(nonatomic) NSUInteger categoryBitMask;

物体的分类。
每个分类都是位掩码的一个位。我们可以通过位运算给物体设置一个或多个类别。
physicsshapecontacttestbitmask一起使用可以定义物体间的相互作用。
dynamicBodykinematicBody的默认类别是SCNPhysicsCollisionCategoryDefaultstaticBody的默认类别为SCNPhysicsCollisionCategoryStatic

@property(nonatomic) NSUInteger contactTestBitMask;

定义哪些类别的物体与这个物体接触时会收到通知。
当物体A与物体B接触时,SceneKit会比较A.contactTestBitMask&&B.categoryBitMask,如果结果是一个非零的值,会创建一个SCNPhysicsContact对象,我们可以通过contactDelegate来处理我们需要自定义的一些操作。通常为了获得最好的性能,只需为我们感兴趣的交互中的物体设置contactTestBitMask
iOS8或者OS X v10.10的环境下,当且仅当碰撞发生了,SceneKit才会触发delegate。iOS9或者OS X v10.11以后的版本,这个值默认是0,且不管是碰撞,还是穿过彼此,都会触发delegate.

@property(nonatomic) NSUInteger collisionBitMask;

定义哪些分类的物体可以和这个物体发生碰撞。
当物体A与物体B接触时,可能会发生碰撞。SceneKit会比较A.collisionBitMask&&B.categoryBitMask。如果结果是一个非零值,那么物体会发生碰撞。每个物体可以单独选择想发生碰撞的物体。
默认值是SCNPhysicsCollisionCategoryAll,将于所有的类别发生碰撞。

用力

- (void)applyForce:(SCNVector3)direction impulse:(BOOL)impulse;

给物体的质心施加一个力或冲量。
direction:力的大小和方向
impulse:YES,施加的是冲量;NO,施加的是力
物体线性加速度与质量成正比。
impulse参数决定了这个方法如何进行物理模拟。(复习力学知识)
如果设置为YES,会把direction参数作为一个冲量。单位是牛秒(kgm/s 或 N·s = Huygens Hy),并立即加速物体。比如发射炮弹等。
如果设置为NO,会把direction参数作为一个力。单位是牛顿(N),SceneKit会在每一帧的最后,将所有的力都应用到物体上,从而得到一个加速度。
impulse参数改变了量值的单位,如果是冲量,将在每一帧上连续产生一定的加速度,如果紧在一帧里应用,那么加速度将大大降低。
同样不需要去做实际测量。

- (void)applyForce:(SCNVector3)direction atPosition:(SCNVector3)position impulse:(BOOL)impulse;

给物体的某个位置施加一个力或冲量。
position:物体所在的SCNNode的自身坐标系中,施加力或冲量的点。
其余参数同上
在物体的质心以外的位置上施加一个力或冲量,可以是线性加速度或角加速度,这取决于物体在物理世界中的位置,以及作用于它的其他力。

- (void)applyTorque:(SCNVector4)torque impulse:(BOOL)impulse;

给物体施加一个扭矩(旋转的力)或角动量(旋转的冲量)。
torque :方向和大小的扭矩(牛·米)或角动量的变化(在newton-meter-seconds),相对于场景的世界坐标空间。
impulse :YES,施加的是角动量;NO,施加的是扭矩
施加扭矩或角动量到物体上,其角速度与物体的质量、形状有关,此外这并不会影响到物体的线性加速度。

- (void)clearAllForces;

取消所有持续的力或扭矩。

管理物体运动

@property(nonatomic) SCNVector3 velocity;

物体当前运动速度(米/秒)和方向。
在SCNSceneRendererDelegate协议中的任何方法中调用,返回的是物理模拟的当前结果,设置属性会立即应用更改。
在其他时间调用,返回的是最后一次设置的值,设置属性会在下一次渲染循环的过程时生效。

@property(nonatomic) SCNVector4 angularVelocity;

物体当前的旋转轴和旋转速度(弧度/秒)。
从旋转轴指定的方向看,正值代表逆时针旋转。
其余同上。

@property(nonatomic, readonly) BOOL isResting;

表示物体是否出于静止状态。
默认是NO。但是物体没有动,并且没有收到任何力。SceneKit会自动将值变成YES。

@property(nonatomic) BOOL allowsResting;

是否自动将物体设置为“静止”
物理模拟的物体越少,可以提升模拟的性能。
设为YES,将提高模拟性能。
设为NO,将提高准确性。


这里涉及到了很多编程以外的物理知识,需要彻底搞懂的话需要恶补物理先。笑cry。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 首先要熟悉一些基本的力学名词及相关公式 刚体(Rigidbody):刚体是指在运动中和受到力的作用后,形状和大小不...
    FLY旳影子阅读 11,680评论 0 11
  • 简介 增强现实技术(Augmented Reality,简称 AR),是一种实时地计算摄影机影像的位置及角度并加上...
    牛奈奈阅读 1,338评论 1 3
  • 111. [动画系统]如何将其他类型的动画转换成关键帧动画? 动画->点缓存->关键帧 112. [动画]Unit...
    胤醚貔貅阅读 13,248评论 3 89
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,067评论 19 139
  • 实践100天走来第44天,养成从早起到跑步再到早睡,3个好习惯,真是个神奇的体验。 最大的收获是爱非坚持的理念体会...
    方锦扬阅读 302评论 0 0