Seasons.NET

ちょっとした技術ブログです

cocos2d performance tips(翻訳版)

cocos2dは、そりゃーもうゲームを作るにはとても素晴らしいフレームワークなのですが、
この原文を読んで取り組むとより一層ゲームの質が上がります。


●英語が苦手の方にも要点をまとめておくと。

  • Instrumentsを使ってプロファイルを取る事
    • CCDDirectorのmainloopの中を覗いて、CCNode visitが処理を食っていれば、描画
    • CCSchedulaer tickが処理を食っていれば、ゲームlogic
    • 処理のパフォーマンスチューニングすべき箇所は、上記処理パーセンテージで判断する
  • 異なるデバイスでテストする事
    • iPhone 3GSやtouch 3rd 32,64GBでテストしてそれで遅いという前に、、、他のデバイスでテストする事
      • iPhone/iPhone 3G/touch 1stが最も遅いデバイス
      • touch 2nd , touch 3rd( 8GB )が次に2番目に速いデバイス
      • iPhone 3GS / touch 3rd( 32,64GB )が最も速いデバイス
  • ローディング画面にtipsを載せる手法は、デバイスによって処理時間が異なる為、読めない時が出てくる
    • tap screenという文言を追加して、タップして次に進めるようにする事で回避出来る。
  • デバイスの違いによるメモリの容量にも注意
    • 128MBを積むもの、256MBを積むものがある為、メモリワーニングの頻度も変わってくる
  • テクスチャサイズは、1024x1024を超えないようにする。
    • GLES2.0では、2048x2048までいけるが、それは機種を限定させてしまう。
  • テクスチャを事前に読み込んでおく
    • テクスチャのロードは、遅いです。なので、テクスチャを使用したい時に読み込む方法は、フレームレートにばらつきが出てしまいます。
    • ばらつきを無くすためにもTextureCacheを利用するべきです。これは利用したい時にテクスチャの参照を返します。
  • テクスチャatlasを使う事。
    • テクスチャの読み込みに時間がかかっている場合は、テクスチャをまとめるようにすること。
    • テクスチャをまとめることでメモリ使用量も減り、描画パフォーマンスもアップ。さらにローディングが速くなる。
    • cocos2dでは、TextureCacheに読み込んだテクスチャから取り出して、使用する矩形を渡せばその矩形サイズのテクスチャを利用出来る。
    • 2の累乗に満たしていないテクスチャは、ロード時に余白をつけて補正して読み込んでくれるがこれが無駄。
      • 空いたスペースに入るテクスチャがあればなるべくまとめること。これだけでもロード回数を減らすことができ省メモリ!!
  • フリップを活用する
    • 左右、上下反転して使えるテクスチャがあればわざわざそのパターンを画像を持たないで、flipX,Yを利用しましょう!!
  • ピクセルフォーマット
    • pngデータを読み込むときに重要なのは、リソースのサイズではなく、ピクセルフォーマット
    • RGBA8888で読み込む時とRGBA4444で読み込むのとではメモリの使用量が半分違う。これはデカイ!!
    • ただし、RGBA8888は、グラデーション等が綺麗に見える為、綺麗に見せたい時はその方が良い。
    • cocos2dではピクセルフォーマットを簡単に変更する事が出来る。
      • [CCTexture2D setDefaultAlphaPixelFormat:kTexture2DPixelFormat_RGBA4444];のように渡すフォーマットで変更可能。
      • cocos2dのピクセルフォーマットについて書かれている
  • PVRTCを活用せよ
    • PVRTCフォーマットは、iPhone専用の素晴らしいフォーマットだ。メモリサイズ、描画コストが減り、高速に描画出来る。
    • 画質に違いがでる為、クオリティが気にならない所で利用するべき。Space Harvestでは、背景に使っているが分からないはずだ。
  • CCSpriteSheetを活用せよ
    • CCSpriteSheetは、パフォーマンス改善をアンロックするもう一つの手段。
      • CCSpriteSheetから作ったSpriteを別のスプライトシートに子供として追加する事ができます。これは何が便利かって?
      • 描画は、スプライトシート単位で行われる為、スプライトが異なっているとAPIコールを無駄に消費する
      • だったら、それに属するものを子供としてぶら下げてが一度に描画してしまおうっていう話です。
      • CCSpriteの描画コールでは、glXXXのメソッドが7回でてきます。
      • これを100個のスプライトで行う場合。7x100=700回APIコールを行う事になる。これは無駄!!1000ならなおさら!!
      • 例えば、別のCCSpriteSheetから生成されたスプライトでも関係するCCSpriteSheetの子供にして一度に描画してしまおう!!
  • CCSpriteSheetでデプスソートするには?
    • cocos2dの描画では、Painterのアルゴリズムを使ってます。親に対して子供の配列がぶら下がっている形。
      • 奥=背景から先に描画し、その上に重なるオブジェクトを順番に表示する。
      • スプライトシートはそれぞれの相対Zで描画する為、スプライトシートをまたいだZ設定はできない。
      • どうしても細かいZ制御が必要なら、CCNodeのvertexZプロパティを使えば、Zバッファを使うことになるので、奥行き設定は想いのままである。
      • Appleのアドバイスに、半透明画像は最後に描画すべきという内容がある為、これらは、親の子供配列よりもさらに上に設定する必要がある。
      • Space Harvestでは、vertexZは用いなかった。いくつかの副作用等を見つけたからだ。だが、CCSpriteSheetは、それがなくとも使う価値は十分ある。
  • プリレンダされた画像を使うと良い
    • CoreGraphicsでeffect生成していたが、どうしてもパフォーマンスがでず困っていた。
    • だが、プリレンダした画像に出力して、それをテクスチャアトラスとして利用するようにしたら10程ロード時間を短縮できた。
  • アトミックなアクセスは避ける
    • ゲームはシングルスレッドで動いているのでアトミックなアクセスはなるべく避けること。


合わせて、cocos2dパフォーマンスチューングの記事
読んでおきたい。