2016-09-16 14 views
3

私はSwiftとSpriteKitで最初のゲームを構築しています。私は最近、CPUの不具合がどこから来ているのかを判断するためにすべてを分けました(ゲームプレイの数分で80〜100%)。私は最近、最も高価な操作の1つがtouchesMovedメソッドにあることを発見しました。これは非常に頻繁に呼び出され、ユーザは主人公を制御するためにゲーム全体を指で押さえているので、これは驚くべきことではない。しかし、私は特に1つの行が問題を引き起こしていたことに驚きました。ここに私のコードは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つの別々のテストを、それぞれ別のラインで別々にテストしました。私は私の指がとてもtouchesMovedがまだ呼ばれていたdown--た間

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

せずに、私は〜5〜10%CPUでホバリングしていることが分かりました。しかし、if(controlBase.frame.contains(touchStartPoint)){のチェックを行うときには、ブラケットの中に何も置かずに、私は〜20-30%のCPUを打つだろう。ここで

は、セットアップは現在、iPhone上でどのように見えるかのスクリーンショットです: enter image description here

、ここでは私の楽器の絵でログインします。私の指が画面と高ポイントのときに私から持ち上げられるとき、低いポイントがされています指がコントローラーを動かしています。 enter image description here

この問題を解決する方法はありますか?私は、ユーザーの仮想ジョイスティックのハンドルがベースを離れることができないようにするために、このチェックを行っています。なぜこの1行が非常に高価なのか、これがこの検査に内在するのかどうか、同様の機能を実現する別の方法があるのか​​どうかはわかりません。ありがとう!

+0

私はこれについて心配しているかどうかは分かりません。あなたの機器ログに基づいて、あなたは多くのCPUを使用していません。レンダリングは最高の消費者であり、タッチ用のコードではありません。それを公開するためにダウをスクロールする必要がない限り。次回の実行時にXcodeでCPUダッシュボードを使用して、その数値がどのように運賃を支払うかを確認してください。あなたのFPSは何ですか? –

+0

本当ですか? Xcode上では、彼らはFPSに大きな影響がないと心配することはあまりないと言っていない限り、私は信じている20%私のFPSは、ゲームの後半まで安定して60分(40分)に低下します。この例では完全なゲームプレイは考慮されていませんが、コントローラ(これは別のプロジェクトでアプリを再構築しています) – Sam

+0

今度はSpaceshipsを実行して、CPU使用量を確認してください(数分後)。あなたのタッチコードが大量に消費されていた場合、それは高い位置のコールツリーに表示されます。私はあなたの他のものを進歩させ、再訪すると言うでしょう。 FPSをあなたのガイドにしましょう。最終的には、チックタックのようなものを作っていない限り、CPU使用率の高いゲームになる可能性が最も高いです。明らかにドロップオフは、他の課題が先行していることを示しています。 –

答えて

2

ああ、大丈夫、別のスレッドであなたのためにコメントを残した後、私はこれを見ました。あなたは、タッチイベントの頻度に関連してOSの慈悲に少しいます。これらの瞬間に費やされる帯域幅を制限して試してみるのはあなた次第です。

ここでの質問はノードツリーの大きさです。手動でツリーを歩いて物理的にノード数を数えるコードを一時的に追加すると便利です。また、スケールを適用し、ノードで回転し、階層を使用していますか?そうであれば、計算がさらに必要になるので注意してください。

これまでに説明した内容に基づいていますが、実際には帯域幅を食べていたら驚いています。

また、あなたが本当に望むのであれば、独自のものを作成することもできます。それは実際に私がやっていることですが、これは私のグラフィックをどう扱うかという特別なニーズがある副産物です。それは言われている、私は通過するオブジェクトの何百もあり、私は顕著な問題がありません。私はあなたのようにCPU使用率を精査していないことに注意してください。私はFPSだけに焦点を当てています。

この間、あなたのFPSは何ですか?また、デバイス上でこれを実行し、CPU/GPUの使用量がフレームに関連しているかどうかを確認する必要があります。 %CPUはまた、私があなたがロギングしているか、時には他の要因に基づいて感じる少し疑わしいかもしれません。

最後に、あなたのコードを宇宙船の例に移動し、宇宙船を追加するときの効果を確認してください。

追加詳細

だから私はもともと私はあなたが何をしていたに以下を考慮した質問に答えるたとき。私はまだあなたが過度に本当に私に何のより良いアイデアを与えた、しかしSKOOPの答えを見ていると面白いコードがある

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

特に、この時点では、ここでダウン最適化しようとすべきではないと信じています必要に応じてCPU使用量を絞り込む方法について説明します。ゲームコーディングと最適化の背後にある教義の1つは、怠惰です。 「どのようにして、あらかじめ計算をしたり、最小限の作業をすることができますか?

touchesBegintouchedEnd/touchesCancelledの調整が必要です。タッチ処理を行っている、あなたのクラス

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を正しい計算で置き換えて距離を計算することを前提としています。これは簡単なことです。また、あなたの距離は絶対に必要です。

もう1つ注意してください。 controllerBaseが静的​​であるため、あなたは、店舗の変数の実際の中心点(controllerBaseCenterと半径計算を事前にすることができる。これにより、無駄なサイクルが各時間touchesStartが実行される節約したがってノード上location又はcontainsを実行することからユーザーを保護し。

ここで

touchesEnd/touchesCancelled

必要な場合がnilアウトはそれがキャンセル/終了したタッチでcontrollerTouch場合、あなたにも、通知のための任意の他のロジックを行うことができます。その後に対処するための

本当の事は、我々は、私の延期のコメントを注意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 
     } 
    } 
} 

を介して活性コントローラを持っている場合、我々は既に知っている知っているので、ここで

touchesMovedです。元のコードでは、タッチがcontrollerBase.frameであったときに必要なときに、location割り当てを完了している必要があります。

今、私が省略した最後のもの。コントローラが動かすことができる半径方向の距離をどのように扱うかは、あなた次第です。たとえば、半径が64で、タッチが60の中心から離れて開始された場合、それはどのように扱われますか?そのオフセットを中心点として扱いますか?このような場合は、最初のタッチの位置を追跡して、数学を適切に調整する必要があります。

プレイヤーが正確である必要がないようにする必要があります。また、コントローラの領域を頻繁に見落としてチェックしないことも心に留めておいてください。

+0

私は漠然としていたように、ゲームのプレイは、ユーザーによって制御される宇宙船が1つしかなく、多くのオブジェクトが宇宙船(ユーザー)が撮影するエイリアンであるように構成されています。つまり、私はスクリーンに宇宙船を描くことさえない - ちょうど私が 'touchMoved'を呼んでいるのでゲームの価値を得ている。ノードの数は、仮想ゲームコントローラを構成するノードの3〜2つにする必要があります。ベースのSKSpriteNode(画面の隅にある灰色の長方形)、joyStickのSKSpriteNode、指(指がベースの内側にある場合) – Sam

+0

あなたの最後のコメントを意味するかどうかはわかりません。とにかく、 "ノードの数は..."。ここのキーワードはすべきです。場合によっては妥当性を検証することが常に求められます。見知らぬ事が起こった。あなたはバックグラウンドで何かをやっている、あるいはあなたのタッチを覚えていますか?もしあなたが本当に 'controlBase.frame'から降りてくる3つのノードしか持たないなら、それは高速でなければなりません。 –

+0

ああ、どのようにCPU使用量を測定していますか? CPUダッシュボードの使用?これを宇宙船で隔離してみてください。 –

1

これは、Apple Frameworksを扱う際の心配な側面の1つです。

いいえ、いいですか?

多くのゲームエンジンとフレームワークは、機能の小さな、適切な例を提供しています。時には数百ものものがあり、エンジンの機能のさまざまな側面を使用する方法を示しています。

これらは、エンジンの各反復のための単位のようなテストとして使用され、それに応じて更新されます。 AppleのSprite Kitデモコードの一部は、元の形式です。

コミュニティはほとんどありません。

残念ながら、AppleがSprite Kit用の「ベストプラクティス」のドキュメントさえないので、他の人がgithubで似たようなことをしているかどうかを調べるのが最良です。

ここにgithubのバーチャルジョイスティックの例があります。

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

あり、ここで興味深い質問です:Dpad for sprite kit

条件が触れたノードの名前についてであるが、むしろより.frameに

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

を検索することが考えられフレーム内の検索が高価であること。それは簡単な数学でなければならないので、私はなぜそうなるのか分かりませんが、SpriteKitとSceneKitには奇妙な問題がたくさんあります。

+0

より全体論的な観点からは、タッチを特定した後、宇宙船のすべての動きにワンタッチを使用しているだけなので、タッチされているものを確認するために条件付きが必要かどうかはわかりません。あなたは(おそらく)それが画面上にあると仮定することができ、あなたの船を制御するための各移動の相対的な位置を使用することができます。 – SKOOP

+0

「多くのゲームエンジン...」APPLは、32セントのヘッドフォンをロゴとTV広告を使用して200ドルにブランド化したものです[フル解析](http://www.huffingtonpost.in/entry/we-took-apart -some-beats-headphones_b_7639618) - 神々を祝福して、私はあなたにAPPL株を買うことを勧めます。ゲームエンジンで手を動かすAPPLのアイデアはかわいいです!悪いDears! (地図のことを覚えておいてください!) – Fattie

+0

「これは、Apple Frameworksを扱う際の心配な側面の1つです。一つだけ。唯一。多くがあります。私はそれらをリストすることができると確信しています。他の部分は、彼らの純粋な貪欲、過度のシニシズム、WWDCビデオペーシングとプレゼンテーション、全体としてのドキュメンテーションなどです。より良いゲームエンジンを提案してください、どうぞよろしくお願いします! – SKOOP

関連する問題