2016-09-16 207 views
3

我正在用Swift和SpriteKit構建我的第一款遊戲,最近我將整個事情分開以確定我的CPU來自哪裏(在遊戲玩幾分鐘內〜80-100%)。我最近發現最昂貴的操作之一是位於touchesMoved方法中。這並不令人意外,因爲它被稱爲非常頻繁,並且用戶在整個遊戲中控制主角。但是,我驚奇地發現,特別是一條線導致了麻煩。這是我的代碼:CPU-Expensive(frame.contains)是否有解決方法?

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { 
    for touch : AnyObject in touches { 
     let location = touch.location(in: self) 

     let touchStartPoint:CGPoint = startingTouches[touch as! UITouch]! 

     if(controlBase.frame.contains(touchStartPoint)){ 
      controlStick.position = location 
     } 
    } 

} 

我跑了4個單獨的測試儀器與另一行。我發現,沒有

if(controlBase.frame.contains(touchStartPoint)){ 
     controlStick.position = location 
    } 

我徘徊在5-10〜%的CPU,而我的手指被down--所以touchesMoved仍然被調用。但是,當檢查if(controlBase.frame.contains(touchStartPoint)){時,即使在括號內沒有任何內容,我也會達到〜20-30%的CPU。

這裏是什麼樣的設置目前看起來像iPhone截圖: enter image description here

,這裏是我的儀器的圖片日誌:低點時,我的手指從屏幕和高點的時候偷了我手指正在移動控制器。 enter image description here

有沒有辦法解決這個問題?我正在執行此檢查以確保用戶虛擬手柄上的手柄無法離開其基座。我只是不確定爲什麼這一行會是如此昂貴,如果這是檢查固有的,如果有另一種方式來實現類似的功能。謝謝!

+0

我不確定我是否會擔心這一點。根據你的儀器日誌,你沒有使用大量的CPU。你會注意到渲染是你的最高消費者,而不是你的觸摸代碼。除非您需要更多地滾動以暴露它。嘗試在您的下一次運行中使用Xcode中的CPU儀表板,並查看這些數字如何運行。另外你的FPS是什麼? –

+0

真的嗎?在Xcode上,他們建議我相信20%,除非你說如果FPS沒有受到很大影響,那麼不需要擔心什麼?我的FPS穩定60,直到遊戲後期(幾分鐘),當它降低到40秒 - 也沒有考慮到完整的遊戲玩法,只有控制器(這是一個單獨的項目,我正在重建應用程序) – Sam

+0

現在嘗試運行Spaceships並查看它的CPU使用情況(減去幾分鐘後)。如果你的觸摸代碼消耗了很多,你會看到它顯示在呼叫樹中的更高位置,事實並非如此。我會說你的其他東西取得進展,並重新審視。讓FPS成爲你的指南。最後,你很可能會得到一個高CPU佔用率的遊戲,除非你正在做類似tic tac的腳趾;)。很顯然,下降意味着你面臨其他挑戰。 –

回答

2

啊,好吧,我剛剛在另一個線程中留下了一些對你的評論後纔看到這個。關於您所獲得的觸摸事件的頻率,您有點兒處於操作系統的擺佈之中。您需要嘗試限制這些時間段內佔用的帶寬。

這裏的問題是你的節點樹有多大?臨時添加一些代碼,以便通過手動走下樹來物理計算節點數量可能會很有用。你是否也在節點上應用縮放和旋轉並使用層次結構?如果是這樣,你也應該注意到,因爲它需要更多的計算。

仍然基於您之前描述的內容,如果真的耗盡了您的帶寬(假設您說有20個對象),我會感到驚訝。

或者,如果你真的想要你可以創建自己的包含。這實際上就是我所做的,但是這部分是我處理圖形的特殊需求的副產品。這就是說,我有數百個物體,而且我沒有明顯的問題。請注意,我並不像您一樣仔細檢查CPU使用情況。我只專注於FPS。

這段時間你的FPS是什麼?你也應該在設備上運行它,看看你的CPU/GPU使用情況是相對於幀的。 %CPU也可能有點懷疑我覺得基於其他因素,如果你正在記錄甚至有時,操作系統還在發生什麼。

最後嘗試將代碼移至太空船示例,並在添加更多太空船時注意效果。

添加詳細

所以,當我最初回答我予少取帳戶的問題變成,你在做什麼。我仍然認爲,你不應該過分試圖在此時此地優化了下來,但是看着SKOOP的回答,特別是

https://github.com/MitrophD/Swift-SpriteKit-Analog-Stick

這是有趣的代碼,給了我什麼,你一個更好的主意真想要做什麼以及如何根據需要擠出CPU使用量。遊戲編碼和優化背後的原則之一就是懶惰。 「我如何預先計算或做最少量的工作?」

這裏您需要對touchesBegintouchedEnd/進行一些調整。在你的類是做觸摸處理添加一個名爲

var controllerTouch : UITouch?

注意,這是可選的,表示當前的接觸,是在控制器中的成員屬性。另外請注意,如果您正在進行多點觸控,則您將此定義爲一個規則:控制器內的第一次觸摸是控制觸摸。

這提出了另一個關鍵點,這是規則。你需要定義規則。在這裏,我要說的是,觸動一個主動控制器超出controllerBase的範圍(這將像是最大化控制桿)並且控制器實際上應該是一個圓圈。最後,我將假設controllerBase是靜態的。

現在,我可以採取一些方法來儘量減少所需的工作。

touchesBegin

由於這是靜態的,我應該通過觸摸的位置從controllerBase中心比較的距離使用這個簡單的數學。我可以這樣做,因爲我們說這是一個圓圈。所以我應該知道半徑。因此,我的檢查將是這樣的:

let distance = computeDistance(pt0: controllerBaseCenter, pt1: location) 

// We only care about doing this if we are not currently actively tracking 
if controllerTouch == nil { 
    if distance < controllerBaseRadius { 
     // Where touch is the current touch 
     controllerTouch = touch 
    } 
} 

注意代碼沒有測試,編譯或如果它的工作原理,而它是做什麼的例子,假設需要你會解決它。我假設你將用正確的數學來代替computeDistance來計算距離,這是一件微不足道的事情。你的距離也需要絕對的。

還有一件事要記住。由於controllerBase是靜態的,你可以預先計算和存儲在變量的實際中心點(controllerBaseCenter和半徑,這樣可以保護你不必做的節點上locationcontains,從而節省了等待的週期,每次touchesStart運行。

touchesEnd/touchesCancelled

在這裏你會零出controllerTouch如果它是結束/取消觸摸。如果有必要,你可以做任何其他通知邏輯。

處理,然後將真實的東西是

touchesMoved

所以在這裏,我們知道我們已經知道,如果我們通過controllerTouch

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { 
    for touch : AnyObject in touches { 

     if touch == controllerTouch { 
      // Only get location when needed (ie defer until you really need this) 
      let location = touch.location(in: self) 
      controlStick.position = location // You will need to adjust, see notes below to compensate for controllerBaseCenter if needed 
     } 
    } 
} 

有一個活躍的控制器注意我的延遲評論。在您的原始代碼中,您只需在需要時完成location作業,即當觸摸位於controllerBase.frame時。

現在,我已經省略了最後一件事。這將取決於您如何處理控制器可以移動的徑向距離。例如,如果半徑是64,並且我的觸摸距離60的中心有一段距離,那麼如何處理?你把這個偏移量作爲中心點嗎?如果是這種情況,則需要跟蹤第一次觸摸的位置以正確調整數學。

請記住,您需要讓玩家不必精確。另外請記住,他們不會經常低頭看管控制器區域來檢查事情。

+0

只是爲了澄清,因爲我很模糊 - 遊戲的結構使得只有一個用戶控制的飛船,許多物體是飛船(用戶)射擊的外星人。也就是說,我甚至沒有畫太空船,只是在遊戲中獲得價值,因爲我已經調用了'touchMoved'。節點的數量應該在構成虛擬遊戲控制器的節點的三分之一左右 - 基礎的SKSpriteNode(屏幕角落中只是一個灰色的矩形),joyStick的SKSpriteNode - 只是一個紅點手指(如果手指在基座內) – Sam

+0

我不太清楚你的意思是你最後的評論。無論如何,「節點的數量應該......」。這裏的關鍵詞是應該的。爲了以防萬一,它總是支付驗證。奇怪的事情發生了。你是否正在做任何事情在背景中,或者你記錄你的觸摸?如果你真的只有3個節點從'controlBase.frame'下降,它應該很快。 –

+0

哦,你如何測量CPU使用率?使用CPU儀表板?嘗試用宇宙飛船隔離這個。 –

1

這是處理Apple框架的思維彎曲方面之一。

沒有好的微示例!

許多遊戲引擎和框架提供了一些小的,功能性的,相關的例子,有時數百個,展示瞭如何使用引擎功能的各個方面。

然後這些(也)用作單位樣測試,用於引擎的每次迭代,並相應地更新。 Apple的一些Sprite Kit演示代碼以其原始形式出現。

而且社區很少。

因此,您最好檢查其他人是如何在github上完成類似的事情的,因爲甚至連Apple的Sprite Kit都沒有「最佳實踐」文檔。

這是github上的一個虛擬手柄示例。

https://github.com/MitrophD/Swift-SpriteKit-Analog-Stick

有一個有趣的問題在這裏:Dpad for sprite kit

其中條件是關於節點的感動,而不是在.frame搜索

//if control pad touched 
    if ([node.name isEqualToString:@"controlPadNode"]) { 
     .... 
    } 

這可能是名在.frame內的搜索是昂貴的。它(應該是)簡單的數學,所以我不知道爲什麼會這樣,但是隨着SpriteKit和SceneKit的出現,有很多奇怪的細節。

+0

從更全面的角度來看,一旦你確定了觸摸,並且由於你只用一鍵觸摸了你的太空飛船的所有移動,我不確定你需要一個條件來檢查被觸摸的東西。你可能(可能)只是假設它在屏幕上,並在每次移動中使用它的相對位置來控制你的船。 – SKOOP

+0

「許多遊戲引擎......」APPL是一款使用標誌和電視廣告將32美分耳機品牌標記爲200美元的股票[完整分析](http://www.huffingtonpost.in/entry/we-took-apart -some-beats-headphones_b_7639618) - 上帝保佑他們,我鼓勵你購買APPL股票。 APPL嘗試在遊戲引擎上的想法是 - 可愛!可憐的Dears! (請記住「地圖」的東西,嘿!) – Fattie

+0

「這是處理蘋果框架的思想彎曲方面之一。」只有一個。只有一個。有很多。我相信你可以列出他們。其他部分是他們純粹的貪婪,猖獗的玩世不恭,WWDC視頻節奏和演示,他們的文檔整體等等等等。建議更好的遊戲引擎,請親愛的! – SKOOP

相關問題