创建SCNPhysicsBody
+ (instancetype)staticBody;
staticBody
是一个不受外力或碰撞影响的物体,不能移动。比如地板、墙壁等。
必须把它附加到SCNNode
的physicsBody
属性上。附加到节点上后,会自动为节点创建物理形状。
对于包含自定义几何的节点,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;
物体的类型,枚举类型,就是上文中的staticBody
、dynamicBody
、kinematicBody
。
@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。staticBody
和kinematicBody
的默认质量为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会根据物体的形状和质量自动确定惯性矩阵。如果要自定义,需要设置usesDefaultMomentOfInertia
为NO
。
@property(nonatomic) BOOL usesDefaultMomentOfInertia;
是否自动计算物体的惯性矩矩形。
YES为自动计算,NO为自定义设置。
分类
@property(nonatomic) NSUInteger categoryBitMask;
物体的分类。
每个分类都是位掩码的一个位。我们可以通过位运算给物体设置一个或多个类别。
与physicsshape
和contacttestbitmask
一起使用可以定义物体间的相互作用。
dynamicBody
和kinematicBody
的默认类别是SCNPhysicsCollisionCategoryDefault
。staticBody
的默认类别为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。