swiftscenekitscnnode

In scene kit, SCNPhysicsField.noiseField seems to just terminate, end, after a few seconds


Have an SCNNode, add a physics body,

physicsBody = SCNPhysicsBody(type: .dynamic, shape: ..)
physicsBody?.isAffectedByGravity = false

Now add a physics field, for example

physicsField = SCNPhysicsField.noiseField(smoothness: 0.2, animationSpeed: 0.01)
physicsField?.strength = 0.05

It works perfectly. In this case, .noise , the object will jiggle around.

However after a few seconds (often 7 seconds, sometimes a different length of time), the object will simply stop moving.

(The three values, smoothness speed and strength, make no difference if you change them - it will still end after a few seconds.)

What's the solution to this mystery?


Solution

  • Just to be clear, I never used a SCNPhysicsField.noiseField, but I used one of type SCNPhysicsField.linearGravity and another of type SCNPhysicsField.customField and both of them are working correctly and do not stop unexpected as you describe.

    here are my examples:

    let attractionField = SCNPhysicsField.linearGravity()
    attractionField.halfExtent = SCNVector3(250.0, 35.0, 60.0)
    attractionField.direction = SCNVector3(-1.0, 0.0, 0.0)
    attractionField.strength = 0.2 // 0.15
        
    attractionNode.physicsField = attractionField
    

    and the other one, (which I used to create a tornado):

    private func addCustomVortexField() {
        
        // Tornado Particles Field
        let worldOrigin = stormNode.presentation.worldPosition
        let worldAxis = simd_float3(0.0, 1.0, 0.0)
        
        let customVortexField = SCNPhysicsField.customField(evaluationBlock: { position, velocity, mass, charge, time in
            
            let l = simd_float3(worldOrigin.x - position.x, 1.0, worldOrigin.z - position.z)
            let t = simd_cross(worldAxis, l)
            let d2: Float = l.x * l.x + l.z * l.z
            let vs: Float = 27 / sqrt(d2) // diameter, the bigger the value the wider it becomes
            let fy: Float = 1.0 - Float((min(1.0, (position.y / 240.0)))) // rotations, a higher value means more turn arounds (more screwed)
            return SCNVector3Make(t.x * vs + l.x * 10 * fy, 0, t.z * vs + l.z * 10 * fy)
            
        })
        
        customVortexField.halfExtent = SCNVector3Make(100, 100, 100)
        stormNode.physicsField = customVortexField
        stormNode.physicsField?.categoryBitMask = BitMasks.BitmaskTornadoField
        
    }
    

    I hope this is gonna help you in some way. You can also provide me your project, and I will have a look at it.