簡體   English   中英

如何將SCNAction和沖力應用於SCNNode

[英]How to apply a SCNAction & An Impulse Force to a SCNNode

嘿,我有一個被施加力的球移動了。 我試圖使之完成的工作基本上是在重力通過空中移動到目的地時對其產生因果關系。 基本上,在執行“移至”動作時重力不會產生影響,因此,它不會緩慢地跌落至地面,而是移至其最終位置,然后在“移至”動作停止時直接掉下。 在現場做重力。

我想讓球拋成弧形並落在目標上嗎?

碼:

                   func CreateBall() {
    let BallScene = SCNScene(named: "art.scnassets/Footballs.dae")
    Ball = BallScene!.rootNode.childNodeWithName("Armature", recursively: true)! //the Amature/Bones
    Ballbody = BallScene!.rootNode.childNodeWithName("Ball", recursively: true)!

    let collisionCapsuleRadius3 = CGFloat(0.01) // Width of physicsBody
    let collisionCapsuleHeight3 = CGFloat(0.01) // Height of physicsBody
    Ball.position = SCNVector3Make(Guy.position.x, Guy.position.y, Guy.position.z)
    Ball.scale = SCNVector3Make(5, 5, 5)
    Ball.rotation = SCNVector4Make(0.0,0.0,0.0,0.0) // x,y,z,w

    Ball.physicsBody = SCNPhysicsBody(type: .Dynamic, shape:SCNPhysicsShape(geometry: SCNCapsule(capRadius: collisionCapsuleRadius3, height: collisionCapsuleHeight3), options:nil))
    Ball.physicsBody?.affectedByGravity = true
    Ball.physicsBody?.friction = 1 //
    Ball.physicsBody?.restitution = 0 //bounceness of the object. 1.0 will boounce forever
    Ball.physicsBody?.angularDamping = 1 // ability to rotate
    Ball.physicsBody?.mass = 1
    Ball.physicsBody?.rollingFriction = 1
    Ball.physicsBody!.categoryBitMask = BitmaskCollision4
    Ball.physicsBody?.contactTestBitMask = BitmaskCollision3 //| BitmaskCollision2
    Ballbody.physicsBody?.collisionBitMask = BitmaskCollision2 | BitmaskCollision3 | BitmaskCollision//| BitmaskCollision2

    scnView.scene!.rootNode.addChildNode(Ball)
    scnView.scene!.rootNode.addChildNode(Ballbody)


    }
    CreateBall()

現在這就是魔術發生的地方:

                   scnView.scene!.physicsWorld.gravity = SCNVector3(x: 0, y: -9.8, z: 0)

                    let location = SCNVector3(Guy2.presentationNode.position.x, 0.0, Guy2.presentationNode.position.z + Float(50) )
                    let moveAction = SCNAction.moveTo(location, duration: 2.0)
                    Ball.runAction(SCNAction.sequence([moveAction]))


                    let forceApplyed = SCNVector3(x: 0.0, y: 100.0 , z: 0.0)
                     Ball.physicsBody?.applyForce(forceApplyed, atPosition: Ball.presentationNode.position, impulse: true)

將SCNActions和物理學結合起來是行不通的,您需要使用其中之一。 使用物理學,您可以計算出將節點推進到目標所需的確切力。

我為這里找到的Unity改編了一個解決方案,並利用了SCNVector3擴展名 ,該擴展名使某些計算更加容易。

基本上你在傳遞SCNNode要扔,一個SCNVector3目標和angle ,你希望節點在被拋出(弧度)。 然后,該功能將計算出達到目標所需的力量。

func shootProjectile() {
    let velocity = ballisticVelocity(ball, target: target.position, angle: Float(0.4))
    ball.physicsBody?.applyForce(velocity, impulse: true)
}

func ballisticVelocity(projectile:SCNNode, target: SCNVector3, angle: Float) -> SCNVector3 {
        let origin = projectile.presentationNode.position
        var dir = target - origin       // get target direction
        let h = dir.y                   // get height difference
        dir.y = 0                       // retain only the horizontal direction
        var dist = dir.length()         // get horizontal distance
        dir.y = dist * tan(angle)       // set dir to the elevation angle
        dist += h / tan(angle)          // correct for small height differences
        // calculate the velocity magnitude
        let vel = sqrt(dist * -scene.physicsWorld.gravity.y / sin(2 * angle))
        return dir.normalized() * vel * Float(projectile.physicsBody!.mass)
}

將PhysicalBody的damping設置為0也很重要,否則它將受到空氣阻力的影響。

我不會假裝確切地知道它是如何工作的,但是Wikipedia上有文章解釋了它背后的所有數學原理。

UPDATE

由於使用了上面的代碼,我注意到它並不總是有效,尤其是當原點和目標的高度不同時。 在同一論壇上,此功能似乎更可靠。

func calculateBestThrowSpeed(origin: SCNVector3, target: SCNVector3, timeToTarget:Float) -> SCNVector3 {

    let gravity:SCNVector3 = sceneView.scene!.physicsWorld.gravity

    let toTarget = target - origin
    var toTargetXZ = toTarget
    toTargetXZ.y = 0

    let y = toTarget.y
    let xz = toTargetXZ.length()

    let t = timeToTarget
    let v0y = y / t + 0.5 * gravity.length() * t
    let v0xz = xz / t


    var result = toTargetXZ.normalized()
    result *= v0xz
    result.y = v0y

    return result
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM