iPhoneでの性能調査のため、とあるシーン(3000ポリゴン程度、物理演算を使用)のフレームレートを測ってみた。
| iPhone3GS (fog有) | 60 fps |
| iPhone4 (fog有、retina) | 38 fps |
| iPhone4 (fog無、retina) | 48 fps |
| iPhone4S (fog有、retina) | 60 fps |
| iPad (fog有) | 33 fps |
| iPad (fog有) | 42 fps |
| iPad2 (fog有、AAx2) | 60 fps |
| new iPad (fog有、retina) | 60 fps |
iPhone4とiPadがやけに遅い。iPadはともかく、iPhone4は何とか60fpsを実現したい。
一番手っ取り早い方法はレンダリング解像度を320x480に下げること。
まずは、Unityの標準クラス Screen のメソッドを使ってみた。
Screen.SetResolution (320, 480, true);
これは表示がおかしくなってうまくいかなかった。
次に iOS PlayerSetting の Target Resolution の設定。
・Native(Default Device Resolution)
・Standard(Medium or Low Resolution)
・HD(Highest available resolution)
"Standard"にすると解像度が下がるが、iPhone4やnew iPadも影響を受けるようだ。
ネットで調べるとやっと解決策が見つかった。
Unityから生成されるiOSコードを以下のような感じで変更すれば、端末ごとにRetinaかSDの制御が可能になるようだ。さらに、scaleFactor を 0.5 とかに設定することでもっと解像度を下げることも可能なので、iPadの高速化も見込めそうだ。
AppController.mm
bool CreateSurface(EAGLView *view, EAGLSurfaceDesc* surface)
{
CAEAGLLayer* eaglLayer = (CAEAGLLayer*)surface->eaglLayer;
assert(eaglLayer == [view layer]);
CGSize newSize = [eaglLayer bounds].size;
newSize.width = roundf(newSize.width);
newSize.height = roundf(newSize.height);
#ifdef __IPHONE_4_0
int resolution = UnityGetTargetResolution();
if ( (resolution == kTargetResolutionNative || resolution == kTargetResolutionHD)
&& [view respondsToSelector:@selector(setContentScaleFactor:)]
&& [[UIScreen mainScreen] respondsToSelector:@selector(scale)]
)
{
CGFloat scaleFactor = [UIScreen mainScreen].scale;
struct utsname u;
uname(&u);
NSString* machine = [[[NSString alloc] initWithUTF8String:u.machine] autorelease];
if ([machine isEqualToString:@"iPhone3,1"] ||
[machine isEqualToString:@"iPod4,1"]) {
scaleFactor = 1.0f;
}
[view setContentScaleFactor:scaleFactor];
newSize.width = roundf(newSize.width * scaleFactor);
newSize.height = roundf(newSize.height * scaleFactor);
UnitySetInputScaleFactor(scaleFactor);
}
#endif
surface->w = newSize.width;
surface->h = newSize.height;
UNITY_DBG_LOG ("CreateWindowSurface: FBO¥n");
CreateSurfaceGLES(surface);
GLES_CHK( glBindRenderbufferOES(GL_RENDERBUFFER_OES, surface->renderbuffer) );
return true;
}
結果として、iPhone4でも 60fps を実現することが出来た。
| iPhone4 (fog有、AAx2) | 60 fps |
Retina表示より質は劣るが、AAをかけても高いfpsを維持できるので、アプリの方向性によっては十分良い方法だと思う。