- Unity Web Player - ParticleTest (http://abagames.sakura.ne.jp/unity/ParticleTest/ParticleTest.html)
FlashやXNAやSilverlightとかでもやってたようなパーティクルテストをUnityでもやってみた。ゲーム内のオブジェクトをどんくらいのオーダーの数まで扱えるかが知りたい、ってのが主な目的。
結果は、なかなかパフォーマンス的には厳しいかも。Core i7 2.7GHzくらいのマシンなら60フレで850個くらい出せるんだけど、Core 2の1.8GHzだと250個くらい。これノーパソとかだと多分壊滅的だよね、まあGPUにも依存するだろうから一概には言えないけど。
ただまだUnityでの最適化手法が全然分からんので全く最適化してないってのと、Unityには組み込みのパーティクルシステムがあるので、本当のパーティクルはそっちを使えという逃げ道はある。
パーティクルの動作を扱うスクリプトはすごく簡単に書けた。Unityはコルーチンがあるので、yieldを使えばフレームごとに呼び出されるUpdate関数を使わなくてもオブジェクトの動作がかける。これは便利。
import Util; private var START_SPEED = 3.0; private var vel:Vector3; function Start () { vel.x = RandZeroCenter(START_SPEED); vel.y = (0.3 + Random.value) * START_SPEED; vel.z = RandZeroCenter(START_SPEED); while (transform.localScale.sqrMagnitude > 0.001) { transform.position += vel * Time.deltaTime; vel.y -= 5.0 * Time.deltaTime; if (transform.position.y < 0) { transform.position.y = 0; vel.y *= -0.9; } transform.localScale *= (1 - 1.0 * Time.deltaTime); numberOfObjects++; yield; } Destroy(gameObject); }
ただUnityではFPSは一定でないことを想定して、フレームごとの経過時間を表すTime.deltaTimeを使うのが通常のやり方らしい。これはちょっと面倒。
というわけで、現状Unityで大量のオブジェクトを扱うのは簡単そうではなさげ。ちょっと最適化手法とか、別の逃げ道とかを探してみようかと思う。
(12/23追記) Unity組み込みのパーティクルシステムの方も試してみた。シーンの真ん中にParticleのEmitter、Animator、Renderer付きのGameObject置いただけ。
- BuiltinParticleTest(http://abagames.sakura.ne.jp/unity/BuiltinParticleTest/BuiltinParticleTest.html)
こっちはパフォーマンス優秀だなあ。Core i7 2.7GHzマシンなら相当数のパーティクル出してもぬるぬる動く。
あとパフォーマンス関係でいろいろ試してみた結果としては、
- オブジェクトプーリングはあんまりパフォーマンス向上には役に立たなさそう。そもそもUnityには高機能なオブジェクト管理機能があるので、それとは別の管理機能を自前で作るのはあまり筋がよくない
- Cubeの代わりに50枚くらいの三角形ペラポリゴンのMeshを書いた場合でもパフォーマンスは同じくらい
- ペラポリゴン1枚にしてもパフォーマンスが劇的に良くなったりはしない
- レンダリングしないで単にパーティクルのGameObjectを生成、制御するだけなら3.5倍くらいのパーティクルが出せる
なのでUnityでパフォーマンス稼ぐ戦略としては、GameObjectの数は絞ってMeshをレンダリングする回数を減らし、パーティクルは組み込みのものを使う、という感じになりそう。