缩放SCNNode时如何同步更新SCNPhysicsBody?求解决方案
这确实是SceneKit里一个容易踩的小坑——SCNPhysicsBody的物理形状并不会自动跟随节点的scale属性同步变化,因为物理形状是基于原始几何体的尺寸生成的,和节点的变换(缩放、旋转这类)是相互独立的。不过有几个很靠谱的解决办法,看你的需求来选:
1. 一次性缩放:创建物理形状时直接考虑缩放
如果你的节点缩放是固定的(像示例里那样只设置一次),可以在初始化SCNPhysicsShape的时候,通过optionScale选项把节点的缩放值传进去,这样物理形状会直接基于缩放后的尺寸生成:
let box = SCNBox(width: 0.2, height: 0.3, length: 0.4, chamferRadius: 0.1) box.firstMaterial?.diffuse.contents = UIColor.blue var boxNode = SCNNode(geometry: box) boxNode.scale = SCNVector3(0.5, 0.5, 0.5) boxNode.position.x += 0.5 // 关键:传入节点的缩放作为物理形状的创建参数 let physicsShape = SCNPhysicsShape(geometry: box, options: [ SCNPhysicsShape.optionScale: boxNode.scale ]) boxNode.physicsBody = SCNPhysicsBody(type: .static, shape: physicsShape) sceneView.scene.rootNode.addChildNode(boxNode)
或者更简单的方式,直接基于节点创建物理形状——SCNPhysicsShape(node:)会自动考虑节点当前的所有变换(包括缩放、旋转),生成匹配的物理形状:
// 先设置好节点的缩放,再用node创建物理形状 boxNode.scale = SCNVector3(0.5, 0.5, 0.5) boxNode.physicsBody = SCNPhysicsBody(type: .static, shape: SCNPhysicsShape(node: boxNode, options: nil))
2. 动态缩放:更新缩放后同步刷新物理形状
如果之后还会动态修改节点的缩放(比如用户交互调整大小),那每次修改scale后,需要重新生成物理形状并赋值给physicsBody:
// 假设之后要修改缩放 boxNode.scale = SCNVector3(0.8, 0.8, 0.8) // 重新创建匹配当前缩放的物理形状 let updatedShape = SCNPhysicsShape(geometry: box, options: [ SCNPhysicsShape.optionScale: boxNode.scale ]) boxNode.physicsBody?.physicsShape = updatedShape
要是想更自动化,还可以用KVO监听节点的scale属性变化,一旦缩放改变就自动更新物理体,避免手动调用的麻烦。
需要注意的是:如果用SCNPhysicsShape(node:)的方式,要是节点有子节点,会把所有子节点的形状合并成一个复合物理形状,所以如果只是单个节点的情况,这个方法最省心。
内容的提问来源于stack exchange,提问作者Magnus T
相关产品推荐
相关产品推荐

