前言
SceneKit
使用SCNPhysicsWorld
来管理这种物理模拟,让物体的碰撞、连接、掉落等具有真实感。
SCNPhysicsBody
:想要一个SCNNode参与到物理模拟中,只需要给node.physicsBod
y赋值一个合适的值,SCNPhysicsBody
有三种类型
-
dynamic
: 动态的物体,受力的影响(applyForce)。 -
static
: 静态的物体,不受力的影响,且不能移动。适合场景中地面、墙体等。 -
kinematic
: 不受碰撞、力影响,在空间变换中,会对dynamic
的物体产生力的影响。
实践
override func viewDidLoad() {
super.viewDidLoad()
let sceneView = SCNView(frame: view.bounds)
sceneView.backgroundColor = UIColor.black
sceneView.scene = SCNScene()
sceneView.allowsCameraControl = true
sceneView.showsStatistics = true
//设置运动速度
sceneView.scene?.physicsWorld.speed = 5
view.addSubview(sceneView)
//添加照相机
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3(0, 10, 20)
// 因为要显示地板 多以要倾斜一点角度(绕X轴旋转,绕哪个轴旋转哪个轴的值就为1)
cameraNode.rotation = SCNVector4(1, 0, 0, -Double.pi * 0.1)
cameraNode.camera?.automaticallyAdjustsZRange = true
sceneView.scene?.rootNode.addChildNode(cameraNode)
//添加地板
let floorNode = SCNNode()
let floor = SCNFloor()
floor.firstMaterial?.diffuse.contents = "floor.jpg"
floorNode.geometry = floor
// 如果没有这一行代码,柱状物体会直接下沉到不见为止
floorNode.physicsBody = SCNPhysicsBody.static()
sceneView.scene?.rootNode.addChildNode(floorNode)
// 添加动态事物
for _ in 0..<10 {
let box = SCNBox(width: 0.5, height: 3, length: 1, chamferRadius: 0)
box.firstMaterial?.diffuse.contents = "1.PNG"
let node = SCNNode(geometry: box)
node.physicsBody = SCNPhysicsBody.dynamic()
node.position = SCNVector3(Float(arc4random_uniform(5)) - 2, 1.5, Float(arc4random_uniform(5)))
sceneView.scene?.rootNode.addChildNode(node)
}
// 继续添加动态事物
for _ in 0..<5 {
let node = SCNNode()
let sphere = SCNSphere(radius: 1)
sphere.firstMaterial?.diffuse.contents = "sun.jpg"
node.geometry = sphere
node.physicsBody = SCNPhysicsBody.dynamic()
node.position = SCNVector3(Float(arc4random_uniform(5)) - 2, 10, Float(arc4random_uniform(5)))
sceneView.scene?.rootNode.addChildNode(node)
}
}
-
效果图