簡體   English   中英

當存在具有物理主體的SkSpriteNode時,TouchesMoved()滯后非常不一致

[英]TouchesMoved() lagging very inconsistently when there is a SkSpriteNode with a physics body

我正在使用Swift 3.0,SpriteKit和Xcode 8.2.1,在運行iOS 10.2的iPhone 6上進行測試。

問題很簡單......表面上看。 基本上我的TouchesMoved()以非常不穩定的速率更新,並且正在破壞游戲中UI的基本部分。 有時候它完美地工作,一分鍾后它以一半的速率進行更新。

我已經解決了這個問題。 只是在具有物理體的場景中有一個SKSpriteNode會導致問題......這是我的GameScene代碼:

import SpriteKit
import Darwin
import Foundation

var spaceShip = SKTexture(imageNamed: "Spaceship")

class GameScene: SKScene{

    var square = SKSpriteNode(color: UIColor.black, size: CGSize(width: 100,height: 100))

    override func didMove(to view: SKView) {
        backgroundColor = SKColor.white
        self.addChild(square)
         //This is what causes the problem:
        var circleNode = SKSpriteNode(texture: spaceShip, color: UIColor.clear, size: CGSize(width: 100, height: 100))
        circleNode.physicsBody = SKPhysicsBody(circleOfRadius: circleNode.size.width/2)
        self.addChild(circleNode)
    }
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in touches{
            var positionInScreen = touch.location(in: self)
            square.position = positionInScreen

        }
    }
    }

這個問題並不總是會發生,所以有時你必須重啟應用程序5次,但最終你會發現,如果你慢慢地拖動方塊,那就非常遲了。 我也理解它有時很微妙,但是當擴大規模時,這是一個很大的問題。

我的主要問題:為什么我有一個帶有物理體的SKSpriteNode導致TouchesMoved()滯后而沒有其他任何延遲,我該如何防止這種情況?

請為了愛的代碼和我的理智,救我脫離這個深淵!

看起來這是因為操作系統太忙而無法響應觸摸事件。 我找到了兩種方法來重現這個:

  • 在設備上啟用飛行模式,然后禁用它。 在禁用飛行模式后約5-10秒,觸摸事件滯后。

  • 在Xcode中打開另一個項目,在方案編輯器中選擇“等待應用程序啟動”,然后按Build and Run將應用程序安裝到設備而不運行它。 在安裝應用程序時,觸摸事件滯后。


似乎沒有解決方法,但這是一個解決方法。 使用上次更新時的位置和時間,預測下次更新時的位置和時間,並將精靈設置為該位置的動畫。 它並不完美,但它的效果非常好。 請注意,如果用戶在屏幕上有多個手指,它會中斷。

class GameScene: SKScene{
    var lastTouchTime = Date.timeIntervalSinceReferenceDate
    var lastTouchPosition = CGPoint.zero

    var square = SKSpriteNode(color: UIColor.black, size: CGSize(width: 100,height: 100))

    override func didMove(to view: SKView) {
        backgroundColor = SKColor.white
        self.addChild(square)

    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        lastTouchTime = Date().timeIntervalSinceReferenceDate
        lastTouchPosition = touches.first?.location(in: self) ?? .zero
    }



    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        let currentTime = Date().timeIntervalSinceReferenceDate
        let timeDelta = currentTime - lastTouchTime


        for touch in touches{
            square.removeAction(forKey: "TouchPrediction")

            let oldPosition = lastTouchPosition
            let positionInScreen = touch.location(in: self)
            lastTouchPosition = positionInScreen

            square.position = positionInScreen


            //Calculate the difference between the sprite's last position and its current position,
            //and use it to predict the sprite's position next frame.
            let positionDelta = CGPoint(x: positionInScreen.x - oldPosition.x, y: positionInScreen.y - oldPosition.y)
            let predictedPosition = CGPoint(x: positionInScreen.x + positionDelta.x, y: positionInScreen.y + positionDelta.y)

            //Multiply the timeDelta by 1.5.  This helps to smooth out the lag, 
            //but making this number too high cause the animation to be ineffective.
            square.run(SKAction.move(to: predictedPosition, duration: timeDelta * 1.5), withKey: "TouchPrediction")
        }


        lastTouchTime = Date().timeIntervalSinceReferenceDate
    }
}

使用touchesMoved方法拖動圖像時遇到類似問題。 我之前只是根據觸摸的位置更新節點的位置,這使得移動看起來很滯后。 我這樣做得更好:

//in touchesMoved
let touchedPoint = touches.first!
let pointToMove = touchedPoint.location(in: self)
let moveAction = SKAction.move(to: pointToMove, duration: 0.01)// play with the duration to get a smooth movement

node.run(moveAction)

希望這可以幫助。

暫無
暫無

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

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