必要条件

この記事に必要な予備知識

これまでにFlash Professionalを使用した経験があることを前提としています。

ユーザーレベル

すべて

原文 作成日: 2011/10/22

この記事では、Flash Professionalを使用して作成されたアプリケーションのパフォーマンスを最適化する戦略について説明します。最適化のプロセスでは、FLAプロジェクトファイルを編集して、パブリッシュされたアプリケーションで実現される(つまり実際の)フレームレートが、アニメーションを滑らかに再生するのに十分であることを確認します。

これまでにFlashプロジェクトを実行したことがあり、アニメーションの再生がぎこちない場合、このような動作を回避する必要があります。再生がぎこちないアニメーションを使ってテストを再現したい場合は、単純なアニメーションのプロジェクトを作成し、10未満のフレームレート(5など)を割り当てます。SWFファイルをパブリッシュしてムービーをテストするときに、再生がぎこちないアニメーションの例を示します。

Flashのパフォーマンスを決定する主な2つの構成要素として、CPU/GPUの使用率とメモリの使用率があります。これらの構成要素は互いに独立しているわけではありません。一方の要素に対して最適化の調整を行うと、もう一方には逆の影響を及ぼします。以下のセクションでは、その仕組みを説明し、CPU/GPUの負荷を減らすためにメモリの使用量を増やすなど、合理的な決定を行うための判断理由を示します。

モバイルデバイス用のFlashゲームを開発している場合、以下で説明するテクニックのいくつかを使用して、許容できるフレームレートを実現する必要があります。デスクトップ用のゲーム以外のアプリケーションを開発している場合は、この記事で説明するテクニックをほとんどまたはまったく知らなくても、許容範囲のフレームレートを達成することができます。

ゲームのパフォーマンスの判断と計測

Flashテスト環境でターゲットプラットフォームをエミュレートし、アプリケーションがターゲットプラットフォームでどのように実行されるかを判断することができれば理想的です。残念ながら、開発用プラットフォームがターゲットプラットフォームと同じである場合を除いて、現在、プロジェクトがテスト環境でどのように再生されるかを正確に評価することはできません。

代わりに、開発用プラットフォームでアプリケーションのパフォーマンスを計測した後、ターゲットプラットフォーム上でアプリケーションのパフォーマンスを監視することによって、ターゲットプラットフォーム上ですべてが順調であることを定期的に確認します。

ターゲットプラットフォームでプロジェクトをテストし、問題を発見した場合は、MTクラスを使用してアプリケーションをデバッグし、問題を解決することができます(用意されているサンプルファイルフォルダーで、MT/com/kglad/MT.asディレクトリにあるActionScriptクラスを開きます)。

メモリの追跡、メモリの使用およびパフォーマンスのテスト

MTクラスのコードは、Damian Connolly氏が自身のサイトdivillysausages.comで提供しているコードに手を加えたものです。MTクラスは、フレームレート、メモリ消費およびメモリに残っているオブジェクトのリストをレポートします。MTクラスを使用するには、以下の手順に従います。

  1. MTクラスをインポートします。
    import com.kglad.MT;
  2. ドキュメントクラスまたはプロジェクトのメインタイムラインから、次の行でMTクラスを初期化します。
    MT.init(this,reportFrequency);
    前の行で、thisキーワードはムービーのメインタイムラインを参照し、reportFrequencyは整数です。メインタイムラインの参照を使用して、実現されるフレームレートを計算します。reportFrequencyは、トレース出力でフレームレートとFlashアプリケーションで消費されるメモリの容量をレポートする頻度(秒単位)です。定期的にフレームレートとメモリのレポートデータを出力したくない場合は、0(または0未満の数値)を渡します。フレームレートを出力しないことを選択している場合でも、このクラスのメモリトラッカーの部分は使用できます。
  3. アプリケーションで作成したオブジェクトを追跡するには、次の行を追加します。
    MT.track(whatever_object,any_detail);
    このコード行で、最初のパラメーターは追跡する(メモリから削除されたかどうかを確認する)オブジェクトで、2番目のパラメーターはテストする対象を含むオプションの文字列です(開発者は通常、このパラメーターを使用して、何について、いつ、どこで特定のオブジェクトの追跡を開始したかという詳細情報を取得します)。
  4. 追跡されたオブジェクトがまだメモリ内に存在しているかどうかを示すレポートを作成するには、次の行を追加します。
    MT.report();

MTクラスを使用するために、MTクラスを理解している必要はありません。ただし、Dictionaryクラスを使用して、MT.track()に渡されるすべてのオブジェクトへの弱い参照を格納する方法を確認しておくことをお勧めします。このクラスには、その仕組みを説明する幅広いコメントが含まれています。

この記事の最初に示されているサンプルファイルのテストの多くでは、MTクラスを使用しています。MTクラスの使用について詳しくは、テストを見て、MTクラスがどのように使用されているかを確認してください。

物理学における観察者効果と同様に、フレームレートやメモリを計測し、メモリを追跡しているという事実だけでも、フレームレートやアプリケーションのメモリ使用量が変化します。ただし、計測による効果は、トレース出力の頻度を比較的少なくすることで最小化できます。さらに、絶対数は通常、重要ではありません。デバッグや最適化で重要なことは、フレームレートやメモリ使用量の時間による変化です。MTクラスは、このような種類の変化をレポートするのに適しています。

MTクラスでは、1秒間に1回以上のトレース出力は許可されないため、トレースメソッドの頻繁な使用によって、レポートされるフレームレートが見かけ上低くなる可能性が最小化されます(トレースメソッド自体がフレームレートを低下させる場合があります)。必要に応じて、トレース出力の代わりにテキストフィールドを使用することによって、フレームレート特定の交絡因子としてのトレース出力を常に除去できることに注目する必要があります。

MTクラスは、サンプルファイルのテストプロジェクトで、メモリ使用量を確認し、メモリの問題を特定するために使用されている唯一のツールです。また、(実行中のアプリケーションの実際のフレームレートを確認することによって)間接的にCPU/GPUの使用量を計測します。

最適化のテクニックの実装

以下のセクションでは、最初にメモリ管理のガイドラインについて、サブトピックのアルファベット順に説明します。次に、CPU/GPU管理に関する情報を、この目標に関連するサブトピックと共に示します。

これらのテクニックを2つのセクションに分けて紹介することが論理的に見えるかもしれません。しかし、この記事でこれまで説明してきたように、メモリ管理はCPU/GPUの使用率に影響するので、メモリ管理のセクションに示されている推奨事項は、CPU/GPUのセクションに示されているヒントと組み合わせることによって機能します。

ユーザーが使用できる具体的なベストプラクティスを説明する前に、どのテクニックの実装が最も容易で、どれが最も難しいかを理解できるように、テクニックに関する情報を含めておくと役に立つのではないかと思います。また、2番目のリストでは、最もメリットの大きいものから順にテクニックに優先順位を付けて示しています。

これらのリストは主観的であることに注意してください。この順序は、開発者の個人的な経験や技能、およびテストの状況やテスト環境によって異なります。

最適化のテクニック(実装が容易なものから順に)

  1. フィルターを使用しない。
  2. 常に逆forループを使用する。doループおよびwhileループを記述しない。
  3. ガベージコレクションの準備をするために、明示的にTimerを停止する。
  4. 弱いイベントリスナーを使用し、不要になったらリスナーを削除する。
  5. できる限り、変数を厳密に型指定する。
  6. マウス操作が不要である場合は、明示的にマウス操作を無効にする。
  7. できる限り、dispatchEventをコールバック関数に置き換える。
  8. SoundおよびSoundChannelのガベージコレクションを有効にするためにSoundを停止する。
  9. 各要素について、必要とされる最も基本的なDisplayObjectを使用する。
  10. AIRアプリケーション(モバイルデバイス)では常にcacheAsBitmapおよびcacheAsBitmapMatrixを使用する。
  11. できる限り、Objectを再利用する。
  12. Event.ENTER_FRAMEループ:異なるリスナーと異なるリスナー関数を使用して、できるだけ少ないDisplayObjectに割り当てる。
  13. Objectを作成およびガベージコレクションする代わりにObjectをプールする。
  14. 部分ブリットを使用する。
  15. ステージブリットを使用する。
  16. Stage3Dを使用する。

最適化のテクニック(メリットが多きものから順に)

  1. ステージブリットを使用する(システムメモリの容量が十分である場合)。
  2. Stage3Dを使用する。
  3. 部分ブリットを使用する。
  4. モバイルデバイスではcacheAsBitmapおよびcacheAsBitmapMatrixを使用する。
  5. マウス操作が不要である場合は、明示的にマウス操作を無効にする。
  6. フィルターを使用しない。
  7. 必要とされる最も基本的なDisplayObjectを使用する。
  8. できる限り、Objectを再利用する。
  9. Event.ENTER_FRAMEループ:異なるリスナーと異なるリスナー関数を使用して、できるだけ少ないDisplayObjectに割り当てる。
  10. 逆forループを使用する。doループおよびwhileループを記述しない。
  11. Objectを作成およびガベージコレクションする代わりにObjectをプールする。
  12. できる限り、変数を厳密に型指定する。
  13. 弱いイベントリスナーを使用し、リスナーを削除する。
  14. できる限り、dispatchEventをコールバック関数に置き換える。
  15. ガベージコレクションの準備をするために、明示的にTimerを停止する。
  16. SoundおよびSoundChannelのガベージコレクションを有効にするためにSoundを停止する。

この優先順位を念頭に置いて、次のセクションでは、メモリをより効率的に管理できるようにFlashプロジェクトを更新する方法を説明します。

メモリの管理

以下に示す推奨事項のリストはすべてを網羅しているわけではありませんが、Flashコンテンツのパフォーマンスを大幅に向上させる戦略が含まれています。 

コールバック関数とdispatchEventの使用の比較

イベントを送出するときには、各イベントを作成し、イベントにメモリを割り当てる必要があるため、メモリ使用量が増加します。イベントはオブジェクトであり、メモリを必要とするので、この動作は理にかなっています。

筆者が少数のイベントをテストしたところ、各イベントが40~128バイトを消費していることがわかりました。また、コールバック関数を使用する方が、イベントを使用する場合と比べて、メモリの使用量が少なくなり、効率的に実行できることもわかりました。(サンプルファイルフォルダーcallback_v_dispatchEventにあるテストファイルを参照してください)。

フィルターの適用

動的フィルターを適用すると、メモリ使用量が増加します。アドビのヘルプドキュメントによると、フィルターを使用するとメモリ使用量は2倍になります。Flash Professional CS6を使用した実際の環境でのテストでは、フィルターを使用すると確かにメモリ使用量は増加しますが、使用量は2倍にまではなりませんでした(このテストの例を確認するには、filtersフォルダーにあるサンプルファイルを参照してください)。

各要素に適切な型の表示オブジェクトの使用

Shape、SpriteおよびMovieClipオブジェクトは、それぞれメモリ使用量が異なります。Shapeオブジェクトでは236バイト、Spriteでは412バイト、MovieClipでは448バイトが必要です。

プロジェクト内で数千個のDisplayObjectを使用している場合、インタラクティブ機能が不要なときにはShapeを使用することで、メモリの消費を大幅に削減できます。また、タイムラインが不要な場合は、Spriteを使用してください。

オブジェクトのプール

アプリケーションの起動時に、アプリケーションを開いている間に必要になるすべてのオブジェクト参照を作成し、作成した参照を配列にプール(格納)します。オブジェクトが必要になったときには、常に、配列からオブジェクトを取得します。

オブジェクトが不要になったときには、常に、配列にオブジェクトを戻します。
同じ型のオブジェクトを格納するには、配列の代わりに、Vectorを使用するのが一般的です。Vectorを使用すると、配列を使用する場合と比べて処理速度は約2倍になりますが、数十万回の演算を実行するのでなければ、その違いに気付くことはありません。数千回の演算に限って言えば、どちらも高速であるからです(例については、array_v_vectorフォルダーにあるサンプルファイルを参照してください)。

オブジェクトプールを使用することにはパフォーマンスのメリットもありますが、主なメリットはメモリの管理が容易になることです。メモリ使用量が無制限に増加するという問題がある場合、オブジェクトプールによってこの問題を回避できます。これは、一般的にパフォーマンスを向上させ、メモリ使用量を削減するテクニックです。

各フレームでガベージコレクションとリサイクルが行われるオブジェクトが数多く含まれているSWFファイルをテストした結果、プールを使用すると、fps(フレーム/秒)は10%向上し、メモリ使用量は約半分に削減されました(pooling_v_gcフォルダーにあるサンプルファイルを確認してください)。

オブジェクトの再利用

ループ内でオブジェクトを作成するときには、常に、ループの外部でオブジェクトを1つ作成し、ループ内で繰り返し再利用するよう努力します。すべてのプロジェクトでいつも可能であるとは限りませんが、多くの状況でこのテクニックが役立ちます。

ブリットについて説明しているセクションには、多くのオブジェクトを再利用する例も含まれています。このテストファイルで、オブジェクトの再利用がどのように実現されているかを確認できます。

サウンドの操作

メモリ使用量に関連するサウンドの問題は、比較的小さな問題です。サウンドを再生しているときには、サウンドのガベージコレクションを実行できません(Flash Professional CS6を使用してファイルをテストした場合)。Soundが再生を終了するか、SoundChannelインスタンスを使用してサウンドのstop()が実行されると、Soundのガベージコレクションを実行できるようになります(詳しくは、sound_testフォルダーにあるサンプルテストファイルを参照してください)。

Timerの使用

Timerに関する問題はより重大です。Timerが停止していない場合(currentCountがrepeatCountよりも小さい場合や、stop()メソッドがTimerに適用されていない場合)、Timerのリスナーとすべてのnull参照を削除しても、Timerはガベージコレクションに応答しません。一度リスナーを削除すると、Timerのリスナー関数が再び呼び出されることはありませんが、Timerは引き続きメモリを消費します。

Timerが使用するメモリは72バイトのみなので、デスクトップやブラウザーのFlashゲームで顕著な問題になる可能性は低いと言えます。ただし、モバイルデバイス上で実行しているFlashゲームで、ゲームを再起動せずに、開く、プレイする、閉じる操作を繰り返した場合、顕著な問題となる可能性があります。

コードを確認するには、gc_timer_testフォルダーにあるファイルを開いてください。

弱いリスナーと強いリスナー

MTクラスを使用したテストの結果でもう1つ予想外であったことは、弱いリスナーを使用した場合と強いリスナーを使用した場合で差がなかったことです。筆者がFlash Professional CS6を使って行ったテストでは、これらはどちらも弱いリスナーのように処理されました(strong_v_weak_listenersフォルダーにあるテストファイルを参照してください)。

CPU/GPU使用率の管理

現在、これを直接計測する方法は、筆者の知る限りでは、オペレーティングシステムのツールを使用する方法しかありません。WindowsにはWindowsタスクマネージャー(「パフォーマンス」タブ)が含まれており、Mac OSにはアクティビティモニタが用意されています。どちらのツールでもCPU使用率を確認することはできますが、一般的に、Flashのパフォーマンスをテストする場合はそれほど役に立ちません。

その結果、アプリケーションの実際のフレームレートを確認することによって、間接的にCPU/GPU使用率を計測するしかありません。MTクラスによって、プロジェクトのフレームレートを確認すると共に、メモリ使用量のレポートやメモリの追跡を行うことができます。

cacheAsBitmapとcacheAsBitmapMatrixの使用

DisplayObjectのcacheAsBitmapプロパティを有効にすると、パフォーマンスが大幅に向上し(メモリ使用量も増加し)ます。ただし、これはDisplayObjectでビットマップを頻繁に更新する必要がある変更が頻繁には行われない場合に限ります。これは、基本的に、DisplayObjectのステージ上の位置が変更される場合を除き、DisplayObjectの外観が変更されないことを確認するという意味です。ビットマップが頻繁に更新される場合、パフォーマンスは低下します。

キャッシュされたビットマップをどれくらいの頻度で更新しても、パフォーマンス上のメリットがあるかは、いくつかの要因に依存します。最も重要な要因は、当然、ビットマップを更新する頻度です。

いずれの場合も、ビットマップの更新が必要なDisplayObjectのcacheAsBitmapを有効にした場合と有効にしない場合について、MTクラスを使用して特定のプロジェクトをテストします(ビットマップの更新を必要としないDisplayObjectについてcacheAsBitmapを使用するかどうかを決定するのは非常に簡単です。使用してください)。

DisplayObject(ムービークリップ)があり、そのcacheAsBitmapプロパティを有効にしたい場合は、次の行を追加します。

mc.cacheAsBitmap = true;

cacheAsBitmapを有効にすることは、モバイルデバイス用にパブリッシュするときにDisplayObjectの拡大・縮小、傾斜、アルファ、回転を変更する(ただし、ムービークリップのフレームは変更しない)場合でも、常にメリットがあります。

具体的には、モバイルデバイス用にプロジェクトをパブリッシュするときに、次のように、cacheAsBitmapを有効にして、DisplayObjectのcacheAsBitmapMatrixプロパティを割り当てることによって、大幅なパフォーマンスの向上を実現できます。

mc.cacheAsBitmap = true;
mc.cacheAsBitmapMatrix = new Matrix();

デフォルトのIDマトリックスを使用する必要はありません。ただし、デフォルト以外のマトリックスを使用する理由はほとんどありません。

ステージブリット

ステージブリット(ビットブロック転送)では、ビットマップを使用して最終的な表示をレンダリングします。DisplayObjectを表示リストに追加する代わりに、ピクセルはステージサイズのビットマップに描画され、そのビットマップがStageに追加されます。アニメーションを再生するために、ビットマップのピクセルはループで更新されます。通常、BitmapDataクラスのcopyPixel()メソッドを使用するEvent.ENTER_FRAMEループが、アニメーションループの外部で作成された他のbitmapDataオブジェクトを使用するステージサイズのビットマップのbitmapDataプロパティに適用されます。

このテクニックは、オブジェクトを直接表示リストに追加することよりも複雑になりますが、ずっと効率的になります。Flashアプリケーションで許容できないレベルのフレームレートと優れたフレームレートほどの差が生じることもあります。確かに、フレームレートを向上させる必要がない場合には、この戦略を使用する理由はまったくありません。

そこで、ムービークリップを使用してステージ全体に10,000個の正方形が移動および回転するSWFファイルを比較しました(blit_test/blit_test_mc.flaという名前のサンプルファイルを参照してください)。次に、同じSWFファイルをいくつかの基本的な最適化テクニックを使用して更新し(blit_test/blit_test_basic_optimizations.flaという名前のサンプルファイルを参照)、さらにステージブリットを使って更新しました(blit_test/blit_test2を参照)。

最初のSWFファイルは約15 fpsで実行されましたが、これは許容できないレベルです。ただし、ブリットなど、始めることがより難しいテクニックに進む前に、パフォーマンスを向上させるために簡単に適用できる基本的な手法がいくつかありました。

最初に、forループを逆にすることによってパフォーマンスが若干向上しました(後のループのセクションを参照)。さらに重要な点として、同じ値を繰り返し再計算する代わりに定数を使用しました。これらの変更によって、スピードが大幅に(~40%)向上し、ほぼ許容できるフレームレート(~21 fps)になりました。

ステージブリットを使用して同じ表示をエンコードすると、フレームレートは54 fpsになり、350%増と著しく向上しました。

ただし、前に述べたように、ブリットの処理はより複雑です。この手順には、次のような処理が含まれます。

  1. Stageの表示ビットマップアセット(Bitmapインスタンス、BitmapDataインスタンス、Rectangleインスタンス)を初期化します。これらのアセットには、表示されるすべてのピクセルが各Event.ENTER_FRAMEイベントループでコピーされます。
  2. データ配列で、表示を更新するために使用されるすべてのデータを設定します(これは常に必要であるとは限りません)。
  3. BitmapDataオブジェクトの配列を設定します。ムービークリップのタイムラインにアニメーションがある場合は、これが書くフレームのBitmapDataオブジェクトを格納する場所です(例えば、スプライトシートを使用するなどの方法があります)。サンプルテストファイルでは、ActionScriptを使用して四角形を回転できる各角度についてBitmapDataインスタンスを作成しました。
  4. Event.ENTER_FRAMEイベントループを作成します。
  5. Event.ENTER_FRAMEループでデータを更新し、手順3で作成した配列から適切なピクセルを、手順1で作成したBitmapDataインスタンスの適切な場所(手順2のデータ配列を使用して決定される)にコピーします。

詳しくは、blit_test/blit_test2にあるファイルを確認してください。このファイルには、数多くの様々なコメントが含まれています。

コーディングが難しいこと以外のステージブリットのマイナス面として、必要なビットマップを作成するときに大量のメモリが消費される可能性があることが挙げられます。これは、iPadのような高解像度(第1世代と第2世代のiPadでは1,024 x 768、第3世代のiPadでは2,048 x 1,536)で、メモリ(RAM)の容量が比較的小さい(第1世代、第2世代、第3世代でそれぞれ256MB、512MB、1GB)デバイス用のアプリケーションを作成するときに重要な要因となります。

一般的に、ゲームは使用可能なRAM容量の半分以上を消費します。これには、ビットマップだけではなく、ゲームでRAMを消費する要素がすべて含まれています。

部分ブリット

名前が示しているように、部分ブリットでは、Flashの表示リストの使用と、BitmapDataオブジェクトへのピクセルのコピーを組み合わせます。通常、ステージに表示される各オブジェクトは、表示リストに追加されたビットマップであり、ムービークリップなどの表示オブジェクトを使って操作できます。各オブジェクトのアニメーションはBitmapDataオブジェクトの配列にブリットされます。

例えば、前のステージ上で正方形が回転および移動する例を使用して、正方形とその様々な回転をブリットし、それらのBitmapDataオブジェクトを配列に格納して、ビットマップを表示リストに追加します。次に、Event.ENTER_FRAMEループで、ビットマップを他の表示オブジェクト(前に説明したムービークリップなど)と同様に操作します。最後に、ビットマップのbitmapDataプロパティを適切な配列要素に割り当てます(この仕組みを確認するには、blit_test/partial_blitting_test.flaファイルを参照してください)。

筆者のPCで行ったテストでは、部分ブリットの結果はステージブリットにはとうてい及びませんでした(24~26 fps)。ただし、状況によっては、部分ブリットの方がステージブリットよりも高速になる場合もあるので、先入観は抱かないようにしてください。さらに、部分ブリットはステージブリットよりもコーディングが容易であるため、部分ブリットで許容範囲のフレームレートを実現できる場合は、ステージブリットで必要になる追加の作業を省略できます。

Event.ENTER_FRAMEループの使用

複数のEvent.ENTER_FRAMEリスナーを作成し、複数のリスナー関数を呼び出す1つのインスタンスに適用した場合、1つのEvent.ENTER_FRAMEリスナーを作成して、1つの1つのリスナー関数を呼び出し、そこから他の関数を呼び出す場合よりも若干効率的になりました。

ただし、1つのオブジェクトが1つのEvent.ENTER_FRAMEリスナーを持つ場合と比べて、複数のオブジェクトがそれぞれ独自のEvent.ENTER_FRAMEリスナーを持つ場合、状況は異なります。1つのEvent.ENTER_FRAMEリスナーを持つ1つのオブジェクトを使用する場合、複数のオブジェクトがそれぞれ独自のEvent.ENTER_FRAMEリスナーを持つ場合と比較して、パフォーマンスは約2倍になります。(このテストを確認するには、enterframe_test_one_v_many_loops_with_different_movieclipsフォルダーにあるファイルを参照してください)。

forループ、whileループ、doループの違いについて

Flashでは、最も実行速度の速いループは逆forループです。ループで同じ型のオブジェクトが格納されたリストが必要な場合、Vectorを使用する逆forループで、オブジェクトのリストを参照するのが、最も速い方法です。

反復パラメーターとして、uintではなく、intを使用する場合、3つのループはすべて実行速度が速くなります。ループ変数をインクリメントするのではなく、デクリメントする場合、3つのループはすべて実行速度が速くなります(注意:ループ変数iをデクリメントし、最終状態としてi>=0を使用するときに、iがuintの場合、無限ループがトリガーされます)。

最終状態として、式やオブジェクトのプロパティではなく、変数や定数を使用する場合、3つのループはすべて実行速度が速くなります。初期状態を評価する必要があるのは1回だけである(各ループの反復処理では評価されない)ため、これらのいずれのループでも、初期状態として式やオブジェクトのプロパティを使用しても大きな違いは生じません。

ループの外側に移動しても、ループの結果に影響しないものはすべて移動してください。例えば、ループ外部でのオブジェクトの宣言があります(オブジェクトの再利用に関するセクションを参照)。ループ内でnewコンストラクターが使用されているときには、ループの外部に移動できる場合があります。また、ループの最終状態が式である場合は、ループの外部で評価してください。

これまで、配列を使用してオブジェクトを参照するよりも、それぞれが次のオブジェクトを参照するオブジェクトを使用する方が処理が速いという意見もありました。筆者のテストでは、このような見解は誤りであることがわかりました。

配列を使用する方が、初期化も使用も容易で、処理も速くなりました。もちろん、配列の代わりにVectorを使用する方がさらに高速になります(for_loop_v_sequential_loopフォルダーにあるサンプルテストファイルを参照してください)。

これらの推奨事項はどれも、多くの状況では大きな違いが生じることはありません。ただし、コーディングで少しでも効率性を高めたい場合や、プロジェクトで大量のループを反復処理する場合は、これらの調整を行ってみる価値があります。

マウス操作の無効化

ムービークリップやスプライトはマウスで操作できます。マウス操作を何もコーディングしないときでも、これらのオブジェクトが存在する場合、Flash Playerはマウス操作を確認します。マウス操作が不要なオブジェクトでマウス操作を無効にすることによって、CPUサイクルを削減することができます。

この戦略は、ステージ上でマウスを動かしたときにパフォーマンスの問題が発生する(またはコンピューターのファンの回転速度が上がる)状況で非常に役に立ちます。マウス操作を無効にすることによって、パフォーマンスが向上し、コンピューターのファンも静かになります。

テストでは、テストファイル内のすべてのムービークリップを無効にした場合、フレームレートは約2.5倍に向上しました。このサンプルテストコードは、mouse_interactivityフォルダーに保存されています。

イベントリスナーの削除

最近のバージョンのFlash Playerでは、オブジェクトのガベージコレクションが実行されるときにリスナーが削除されるようになり、強いリスナーでガベージコレクションの遅延が発生することがなくなったように見えますが、すべてのイベントリスナーをできるだけすみやかに明示的に削除してください。リスナーをすみやかに削除するほど、リスナーによって消費されるCPUサイクルは少なくなります。さらに、ユーザーがインストールしているFlash Playerのバージョンがわからない場合もあります。古いバージョンのFlash Playerでは、弱いリスナーを使用するオブジェクトであっても、オブジェクトのガベージコレクションが実行されません。Flash Playerの新しい機能に依存して、不十分なコーディングを最適化しないでください。

Stage3Dの使用

Stage3DはGPU対応の表示レンダリングモデルで、Flash Player 11のリリース以降、利用できるようになりました。このモデルは3Dレンダリングで特に便利ですが、Starlingなどのフレームワークを使用する2D表示で使用する場合にもメリットがあります。

表示のレンダリングは一般的にCPU(アプリケーションの実行に必要な他のすべての処理も実行する)によって処理されてきたので、レンダリングにGPUの機能を利用することで、CPUが解放され、他のすべての処理を実行できるようになります。これにより、対応するGPUを搭載したデバイスでパフォーマンスが大幅に向上します。

Stage3Dコンテンツを表示するには、Flash Playerバージョン11以上を使用する必要があります。Stage3D APIを使用するには、Flash Player 11またはそれ以降のリリースを使用するようにSWFファイルをパブリッシュする必要があります。Flash Professional CS6を使用している場合は、すべて設定済みです。Flash Professional CS5またはCS5.5を使用している場合は、Flashのインストールを更新して、Flash Player 11へのパブリッシュを有効にすることができます。詳しくは、Rich Galvan氏のブログの記事「Adding Flash Player 11 support to Flash Professional CS5 and CS5.5」(Flash Professional CS5およびCS5.5へのFlash Player 11のサポートの追加)を参照してください。

残念ながら、Stage3D APIを使用するのは難しいのですが、Stage3Dを使用するために必要な低レベルのコードを処理する無料のパブリックフレームワークがいくつか存在し、APIを簡単に使用できるようにしています。

このようなフレームワークの1つであるStarlingは、2Dゲームの開発用に設計されています。このフレームワークは使用方法が簡単で、Stage3Dの複雑な機能を効率的に抽象化できます。Starling APIは、Starling Framework Referenceサイトで入手できます。

ブリットや部分ブリットと比較するために、Starlingのテストを実行しました。状況によって、Starlingのパフォーマンスはどちらのブリットオプションよりも悪い場合がありました。実際、最適化していない10,000個の正方形のムービークリップよりもパフォーマンスが悪い結果となりました。

ただし、Starlingのテストでデバッグを許可するオプションの選択を解除すると、この単純な調整でフレームレートは2倍以上になり、結果のSWFファイルは最適化していない10,000個の正方形のムービークリップのテストに匹敵するものになりました。これでもまだ満足できる結果ではありません。しかし、この問題の一部は、デバッグバージョンのFlash Playerを使用してファイルをテストしていることであり、非デバッグバージョンのFlash Playerと比較すると、デバッグバージョンでは、Starlingのパフォーマンスは悪くなるようです。

さらに、10,000個の正方形のムービークリップのテストは、Starlingの最高の状態を示しているわけではありません。それぞれがアニメーションを伴うタイムラインを含むムービークリップを多数使用している場合、Starlingのパフォーマンスは、ほぼ確実に、単純な最適化を利用してビルドできるものよりも高くなります。

Stage3DとStarlingを使用するメリットをしのぐパフォーマンスを提供するのはブリットだけです。ただし、必要なビットマップを作成するのに必要なメモリを考慮すると、ブリットは現実的ではない場合があります。

このサンプルテストファイルは、starling_testフォルダーにあります。

Starlingフレームワークを使用するには、以下の手順に従います。

  1. starling.swcファイルをダウンロードします。
  2. 以下の手順に従って、このファイルをFlashプロジェクトのライブラリパスに追加します。
    1. File(ファイル)/Publish Settings(パブリッシュ設定)/ActionScript Settings(ActionScript 設定)を選択します。
    2. 「Library path(ライブラリパス)」タブをクリックし、「Browse to SWC file(SWC ファイルを参照)」アイコンをクリックします。
    3. 表示されたファイルを開くダイアログボックスで、デスクトップのstarling.swcファイルに移動して選択します。
    4. 「Open(開く)」をクリックしてstarling.swcをライブラリパスに追加します。
    5. 「OK」をクリックしてAdvanced ActionScript 3.0 Settings(ActionScript 3.0 の詳細設定)パネルを閉じ、「OK」をクリックしてパブリッシュ設定を閉じます。 
    6. FLAファイルを保存すると、Starlingを使用することができます。

Stage3Dを使用する(Stage3Dを使用するStarlingなどのフレームワークの使用を含む)モバイル用のAIRゲームをパブリッシュする場合は、「Render mode(レンダリングモード)」を「Direct(ダイレクト)」に設定します。埋め込みHTMLファイルをパブリッシュする場合は、パブリッシュ設定で「Window Mode(ウィンドウモード)」を「Direct(ダイレクト)」に設定します。

StarlingとStage3D APIについて詳しくは、Adobe Gamingサイトを参照してください。

次のステップ

これまでに説明した最適化のテクニックに加えて、Flashプロジェクトを開発する際に、再生パフォーマンスを向上させるためのベストプラクティスが2つあります。

  1. 宣言する各変数のクラス型を指定します。すべての変数の型を指定しておくとコードの実行が速くなり、エラーが発生したときに、コンパイラーでよりわかりやすく役に立つ情報が表示されます。サンプルファイルフォルダーvariables_typed_v_untypedにあるテストファイルを確認してください。
  2. 配列を使用してデータ情報を格納する代わりに、Vectorを使用します。この仕組みを確認するには、サンプルファイルフォルダーarray_v_vectorにあるテストファイルを参照してください。

この記事で説明した推奨事項が、Flash Professionalで作成するプロジェクトのパフォーマンス向上のお役に立てば幸いです。Flashでのアニメーション、アプリケーションおよびゲームの作成について詳しくは、Flashデベロッパーセンターを参照してください。