Physics Simulation 之 SCNPhysicsBody
此系列为官方文档翻译,用于学习
SceneKit
概述
当SceneKit
准备渲染新帧时,会对场景中附加在节点上的物理体执行物理计算。 这些计算包括重力、摩擦和与其他物体的碰撞。 您还可以将自己的力和冲量应用于物体。 在SceneKit
完成这些计算之后,它会在渲染帧之前更新节点对象的位置和方向。
要向节点添加物理,创建和配置SCNPhysicsBody
对象,然后将其分配给SCNNode
对象的physicsBody
属性。 在您应用力或冲量之前,必须将物理体与节点对象关联。
一个物体的物理特性
当场景模拟物体时,SCNPhysicsBody
类定义物体的物理特性。对于物理模拟,有三个属性最重要:
type
属性,它确定物体如何与模拟中的力和其他物体交互。 静态物体不受力和碰撞影响且无法移动。动态物体受到力和与其他类型物体的碰撞的影响。 运动物体不受力或碰撞影响,但可以直接移动它们,从而可能会影响动态物体发生碰撞。physicsShape
属性,它定义物体的三维形状以进行碰撞检测。 使用简单形状而不是节点可见几何的详细信息,物理模拟运行得更快。 通常,您将一个物体的物理形状设置为大致匹配节点可见内容的边界框、球体或基本形状。 有关创建物理形状的详细信息,请参阅SCNPhysicsShape
。kinematic()
属性。 对动态物体施加力或扭矩会导致其加速度(或角加速度)与其质量成比例。
场景中的所有值在SceneKit
的物理模拟中使用国际单位制(SI),mass
(质量)单位为千克;force
(力)、impulse
(冲量)和torque
(扭矩)的单位是牛顿、牛顿秒和牛顿米;节点位置和大小的距离单位是米。 请注意,您不必尝试为物理量提供逼真的值 - 使用产生您所需行为或游戏玩法的任何值即可。
对于动态物体,您可以控制物体受力或碰撞的影响方式。 请参阅定义力如何影响物理体。
定义物体的类别和碰撞
当您设计使用物理的游戏时,定义在场景中出现的不同物理对象的各种类别。 为您的应用程序的行为定义不同类别的物理体。 一个物体可以分配给您想要的这些类别中的任意数量。 除了声明自己的类别之外,物理体还声明了它与哪些物体类别交互。
使用categoryBitMask
和collisionBitMask
属性定义对象的碰撞行为。 SCNPhysicsCollisionCategory
中列出的常量为这些属性提供了默认值。 此外,使用 contactTestBitMask
属性,您可以定义一对物体生成接触消息(请参见 SCNPhysicsContactDelegate
协议),而不受到碰撞影响的交互。
相关物理类
物理场创建影响区域内所有物体的力,例如涡旋和引力。 有关详细信息和可用字段类型的列表,请参阅 SCNPhysicsField
。
您可以添加更高级别的行为,以控制多个物体之间的交互,例如关节和车辆。 有关详细信息和可用行为的列表,请参阅 SCNPhysicsBehavior
。
场景的 physicsWorld
属性持有一个管理影响整个场景的物理特性的 SCNPhysicsWorld
对象。
物理和渲染循环
SceneKit
将其物理模拟作为 SCNSceneRendererDelegate
中描述的渲染循环的一部分进行评估。在通过此循环的每个步骤中,SceneKit 确定具有附加物理体的所有节点的状态,并为一个时间步长模拟物理对这些物体的影响。例如,通过根据其速度和角速度更新物体的位置或旋转来模拟物理。在模拟物理之后,SceneKit
将物理模拟的结果应用于场景以供显示。
因为您不仅可以通过物理,而且可以通过动作和隐式和显式定义的动画动画 SceneKit
内容,所以 SceneKit
将物理模拟的结果不应用于场景中 SCNNode
对象,而应用于每个节点的呈现对象,表示其当前显示状态。 因此,更改受物理影响的节点的属性需要特别考虑。
如果更改受物理影响的节点的变换值或变换的任何其他属性,如位置和旋转之一,SceneKit
将重置该节点的物理模拟。如果您只想更改变换的一个组件,同时将其他组件保留为其物理模拟值,请在更改前复制呈现节点的变换,如下所示:
1 | //将演示节点的变换复制到模型节点。 |
相关API
创建物理体
1 | init(type: SCNPhysicsBodyType, shape: SCNPhysicsShape?) |
使用指定的类型和形状创建物理体。
1 | class func `static` () -> Self |
创建一个不受力或碰撞影响且不能移动的物理体。
1 | class func dynamic() -> Self |
创建一个可以受力和碰撞影响的物理体。
1 | class func kinematic() -> Self |
创建一个不受力或碰撞影响,但在移动时可以引起影响其他物体的碰撞的物理体。
定义力如何影响物理体
1 | var physicsShape: SCNPhysicsShape? |
定义用于碰撞检测的物理体的实体体积。
1 | var type: SCNPhysicsBodyType |
一个常量,用于确定物理体如何响应力和碰撞。
1 | enum SCNPhysicsBodyType |
常量,用于确定物理体如何与力和其他物体交互,用于类型属性和创建物理体时。
1 | var velocityFactor: SCNVector3 |
一个乘数,影响SceneKit
将物理模拟计算的平移应用于包含物理体的节点。
1 | var angularVelocityFactor: SCNVector3 |
一个乘数,影响SceneKit
将物理模拟计算的旋转应用于包含物理体的节点。
1 | var isAffectedByGravity: Bool |
一个布尔值,用于确定场景中的恒定重力是否加速物体。
定义物体的物理属性
1 | var mass: CGFloat |
物体的质量,以千克为单位。
1 | var charge: CGFloat |
物体的电荷,以库仑为单位。
1 | var friction: CGFloat |
物体的滑动运动阻力。
1 | var rollingFriction: CGFloat |
物体的滚动运动阻力。
1 | var restitution: CGFloat |
确定物体在碰撞中损失或获得多少动能的因子。
1 | var damping: CGFloat |
减少物体的线性速度的因子。
1 | var angularDamping: CGFloat |
减少物体的角速度的因子。
1 | var momentOfInertia: SCNVector3 |
物体的惯性矩,以包含物体的节点的本地坐标系表示。
1 | var usesDefaultMomentOfInertia: Bool |
一个布尔值,用于确定SceneKit
是否自动计算物体的惯性矩,或允许设置自定义值。
1 | var centerOfMassOffset: SCNVector3 |
物体质心相对于其本地坐标原点的位置。
处理接触和碰撞
1 | var categoryBitMask: Int |
定义该物理体属于的哪些类别的掩码。
1 | var contactTestBitMask: Int |
定义哪些类别的物体与此物理体发生交集通知。
1 | var collisionBitMask: Int |
定义哪些类别的物理体可以与此物理体碰撞。
1 | struct SCNPhysicsCollisionCategory |
用于物理体的categoryBitMask
和collisionBitMask
属性的默认值。
1 | var continuousCollisionDetectionThreshold: CGFloat |
物体必须移动的最小距离,这样SceneKit
才能应用更精确(但更昂贵)的算法来检测与其他物体的接触。
应用力、冲量和扭矩
1 | func applyForce(SCNVector3, asImpulse: Bool) |
将力或冲量应用于物体的质心。
1 | func applyForce(SCNVector3, at: SCNVector3, asImpulse: Bool) |
将力或冲量应用于物体的特定点。
1 | func applyTorque(SCNVector4, asImpulse: Bool) |
将净扭矩或角动量变化应用于物体。
1 | func clearAllForces() |
取消当前模拟步骤中作用于物理体上的所有连续力和扭矩。
在运动的物体中交互
1 | var velocity: SCNVector3 |
描述物理体当前速度(以米/秒为单位)和运动方向的向量。
1 | var angularVelocity: SCNVector4 |
描述物理体当前旋转轴和旋转速度(以弧度/秒为单位)的向量。
定义何时可以移动物体
1 | var isResting: Bool |
一个布尔值,指示物理体是否静止。
1 | var allowsResting: Bool |
一个布尔值,指定是否可以自动将物理体标记为静止。
1 | func setResting(Bool) |
告诉SceneKit是否将物体视为当前正在运动。
将物理体与其节点同步
1 | func resetTransform() |
更新物体在物理模拟中的位置和方向,以匹配其附加的节点。
实例属性
1 | var angularRestingThreshold: CGFloat |
扩展
详细内容请看:SCNPhysicsBody