ほとんどの Unity API やプロジェクト構造はすべてのサポートするプラットフォームで同一であり、ケースによってはプロジェクトは単にリビルドすることで異なるデバイスで実行できます。しかしハードウェアやデプロイ方法の基本的な違いによってプロジェクトの一部は変更なしではポートできません。よくあるクロスプラットフォームでの課題と解決するための提案の詳細を、以下にまとめています。
プラットフォーム間での異なる動作のもっとも明らかな例はハードウェアにより提供される入力方法です。
Input.GetAxis 関数はデスクトッププラットフォームにてキーボードやジョイパッドからの入力を統合するのに便利な方法です。しかし、この関数はタッチ入力に依存するモバイルプラットフォームでは意味がありません。同様に標準のデスクトップキーボード入力はタイプされたテキスト以外ではうまくポートできません。将来他のプラットフォームへのポートを考えるのであれぱ入力のコードには抽象化レイヤーを追加するのは意味があります。簡単な例としてカーレースのゲームを作成する場合、自身の入力クラスを作成して Unity API コールを自身の関数でラップする場合があるかもしれません。
// Returns values in the range -1.0 .. +1.0 (== left .. right).
function Steering() {
return Input.GetAxis("Horizontal");
}
// Returns values in the range -1.0 .. +1.0 (== accel .. brake).
function Acceleration() {
return Input.GetAxis("Vertical");
}
var currentGear: int;
// Returns an integer corresponding to the selected gear.
function Gears() {
if (Input.GetKeyDown("p"))
currentGear++;
else if (Input.GetKeyDown("l"))
currentGear--;
return currentGear;
}
API コールをラップするメリットはこのようなクラスが、ひとつのソースファイルに集約されて、結果的に簡単に見つけられて置き換えできることです。しかし入力関数をゲームにおける論理的な意味に沿って作ることはより重要なことです。これによってゲームのコードを特定プラットフォームの特殊な入力手法から切り離すことができます。例えば、前述の Gears()関数を修正して実際の入力がモバイルデバイスの画面タッチから受けるように修正できます。整数を使用してギアを選択するのはあらゆるプラットフォームで十分に機能しますが、プラットフォーム固有の API コード残りのコードと混ぜることは問題の種です。プラットフォーム固有のコンパイルによって、同じソースファイルにある入力関数のさまざまな実装を組み合わせ、手動による置き換えを回避することは便利かもしれません。
Input.GetMouseButtonXXX 関数はモバイルデバイスでは実際に “マウス” がないにも関わらず、理屈に合った明白な解釈がなされるように設計されています。画面でのシングルタッチは左クリックとして返され、Input.mousePosition プロパティは指が画面をタッチしている間はタッチの位置を返します。これはつまり簡単なマウス操作はデスクトップとモバイルプラットフォーム間でしばしば相互的に可能だということです。当然、実際の変換はもう少し分かりづらいものです。デスクトップのゲームはひとつ以上のマウスボタンを活用できて、モバイルゲームは画面上の同時マルチタッチを検知できます。
API コールと同様、この問題は入力を論理的な値で表現することによって一部は管理ができます。例えば、ピンチジェスチャーによってモバイルデバイスでのズームはデスクトップで+/-キーで置き換えできます。入力関数は単にズームに関する float 値を返すことができます。同様にしてモバイルデバイスのダブルタップをデスクトップの右クリックを置き換えることができます。しかし、もし入力デバイスのプロパティがゲームに統合されたものであると別のプラットフォームで再度モデル化することはできないかもしれません。すなわちそのゲームは完全にポートすることができないか、入力またはゲームプレイの大幅修正が必要となることを意味します。
これらの入力はハンドヘルドデバイスのポータビリティに由来するものであり、デスクトップでは意味ある代替手段はないかもしれません。しかしいくつかのケースでは単に標準的なゲーム制御を踏襲しているのみであり、この場合にポートすることはとても容易です。例えばカーレースではステアリング制御をモバイルデバイスの画面の傾き(加速度センサーにより判断)で実装するかもしれません。このようなケースでは入力 API コールは比較的置き換えが容易であり加速度センサーの入力はキー入力などで置き換えます。しかし入力を再度キャリブレーションしたり、異なる入力方法によってゲーム難易度を変更することが必要かもしれません。デバイスを傾けるのはより遅く全体的にキー入力より骨が折れる作業となり、画面に集中することが難しくなったりします。結果としてモバイルデバイス上のほうがマスターすることが難しく、ゲームプレイをもう少しゆっくりにするか、レベルで許容するラップタイムを緩めるなどした方が適切かもしれません。このためにはこれらの要素の調整が容易にできるようなゲームコードの設計が必要となります。
モバイルデバイスは必然的にメモリ、ストレージ、CPU パフォーマンスがデスクトップマシンより劣り、パフォーマンスが十分でないために、ゲームをポートすることができない場合があります。いくつかのケースではリソースの問題は管理できますが、もしデスクトップマシンで性能限界まで引き出そうとしている場合はモバイルプラットフォームにポートする候補として不向きです。
現在、モバイルデバイスは動画再生をするときはハードウェアサポートに強く依存しています。実際には再生オプションが限定されていて、MovieTexture アセットがデスクトッププラットフォームで提供する柔軟性は与えられていません。動画はモバイルでフルスクリーン再生できますが、ゲームのオブジェクトのテクスチャとして使用することはスコープ外の仕様です(例えばゲーム内のテレビ画面に動画を映すことはできません)。ポータビリティの観点では、動画を導入部、シーンのカット、説明や短いプレゼンの中で使用するのは問題ありません。しかし、ムービーがゲーム世界と同居して表示する必要がある場合はモバイルの再生オプションの適切な考慮が必要です。
動画、音声、さらにはテクスチャは多くのストレージ容量を使用するかもしれず、ゲームをポートするときはこれを意識する必要があります。ストレージ容量(多くの場合ダウンロード時間とも関連する)は典型的にはデスクトップマシンでは問題となりませんが、モバイルでは状況が異なります。さらにモバイルの App Store は提出した製品に容量制限を加えることがあります。これらの懸念を解消するにはゲームの開発時のプランニングが必要かもしれません。例えば容量カットしたモバイル版のアセットを用意して容量の節約をする必要があります。
“死んだ” オブジェクトからの未使用メモリ回復は Unity により自動的にハンドリングされていて、デスクトップマシンで気付かないうちに行われます。しかしメモリや CPU 処理能力の低いモバイルデバイスではガベージコレクションはより頻繁に行われ、パフォーマンスにより甚大な影響を及ぼすこと(ゲームプレイの中で不要な待機の要因となる、など)があります。たとえゲームが利用可能なメモリの範囲で実行されても、それでもコードを最適化してガベージコレクションによる待機を避ける必要がある場合があります。詳細については 自動メモリ管理を理解する を参照してください。
デスクトップマシンでスムーズに動作するゲームがモバイルデバイスで十分なフレームレートが出ない理由として、モバイル CPU がゲームの複雑さに耐えられない場合があります。モバイルプラットフォームへポートするときは効率的なコードにすることに注意してください。いくつかの簡単なステップにより効率をあげる方法はマニュアルの iOS のパフォーマンスの最適化 で要点をあげています。