'SceneKit how to move a character on terrain with different height

I am working on a scene with a character and a platform with a stairs. Character must move up and down of the stairs and jump from the platform: enter image description here

I move character by virtual d-pad. I am looking for a correct way to move a character. Now I have two ways, each has its advantages and disadvantages:

First way: ray test. This way works perfect: I can move character up and down of the stairs, but if I have a lot of objects near the pad, and I want to jump I need to do a lot of ray tests.

Second way: move physics body of the character. Using this way I couldn't understand how to move character down of the stairs. Each time it looks like a jump over the stairs.

So what is the correct way to move a character over terrain with different height?



Solution 1:[1]

To move a character over a terrain with different heights you should use collisions. To find out more about it, watch a part on collision meshes in Enhancements to SceneKit at WWDC 2015 (time 17:30) and also look at a code in Fox 2 game's sample.

Here's a code's snippet how to use collisions:

private func loadCharacter() {
    let scene = SCNScene( named: "Art.scnassets/character/max.scn")!
    model = scene.rootNode.childNode( withName: "Max_rootNode", recursively: true)
    model.simdPosition = Character.modelOffset

    characterNode = SCNNode()
    characterNode.name = "character"
    characterNode.simdPosition = Character.initialPosition

    characterOrientation = SCNNode()
    characterNode.addChildNode(characterOrientation)
    characterOrientation.addChildNode(model)

    let collider = model.childNode(withName: "collider", recursively: true)!
    collider.physicsBody?.collisionBitMask = Int(([ .enemy, .trigger, .collectable ] as Bitmask).rawValue)

    let (min, max) = model.boundingBox
    let collisionCapsuleRadius = CGFloat(max.x - min.x) * CGFloat(0.4)
    let collisionCapsuleHeight = CGFloat(max.y - min.y)

    let collisionGeometry = SCNCapsule(capRadius: collisionCapsuleRadius, height: collisionCapsuleHeight)
    characterCollisionShape = SCNPhysicsShape(geometry: collisionGeometry, options:[.collisionMargin: Character.collisionMargin])
    collisionShapeOffsetFromModel = float3(0, Float(collisionCapsuleHeight) * 0.51, 0.0)
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1