做一個(gè)VRAR的app,用Vuforia識(shí)別出模型之后通過(guò)點(diǎn)擊模型切換到GoogleCardboard 的界面,兩邊都有SDK,實(shí)現(xiàn)起來(lái)應(yīng)該不難,單純是兩個(gè)SDK的跳接,然而卻遇到黑屏的問(wèn)題。
詳情:
版本:Vuforia 5.5.9 UnitySDK; Cardboard 0.5.0 UnitySDK;Unity 5.3.5;
只要引用進(jìn)Cardboard就會(huì)出現(xiàn)Black camera,但是卻能識(shí)別出東西,就像這樣:
1. 我猜想應(yīng)該是cardboard的什么東西影響到了vuforia,但還沒(méi)跳轉(zhuǎn)到cardboard啊,只是識(shí)別而已。查看cardboard UnitySDK,發(fā)現(xiàn)CardboardAppController是繼承自UnityAppController的,還重寫(xiě)了兩個(gè)方法preStartUnity 和 CreateUnityView。
- (void)preStartUnity {
[super preStartUnity];
syncProfile();
}
- (UnityView *)createUnityView {
UnityView* unity_view = [super createUnityView];
createSettingsButton(self, (UIView *)unity_view);
return unity_view;
}
防止覆蓋父類(lèi)的方法,子類(lèi)方法都有調(diào)用父類(lèi)的方法,而且注釋掉之后無(wú)法解決black camera。
2.查找Vuforia方面的問(wèn)題,發(fā)現(xiàn)Vuforia有VRAR的demo:Integrating Cardboard to the AR/VR Sample
該demo實(shí)現(xiàn)的是用谷歌的cardboard雙屏模式打開(kāi)攝像頭進(jìn)行識(shí)別,識(shí)別完之后進(jìn)去模型,并沒(méi)有提到black camera的問(wèn)題。跳過(guò)~
3.再查找Cardboard在github上面的地址,googlevr/gvr-unity-sdk,在issue里面找到一個(gè)同道中人,地址grr-unity-idk的issue,他解釋說(shuō):
It was due to the way both Vuforia and Cardboard override the AppController. If you manually merge them together then it works correctly (Unity 5.3).
有道理,既然繼承UnityAppController會(huì)有問(wèn)題,那為何不直接寫(xiě)進(jìn)去,嘗試了把CardboardAppController的方法,寫(xiě)到UnityAppController里面,成功解決了。但此時(shí)還有疑問(wèn),為什么繼承就不行,重寫(xiě)的兩個(gè)方法都包含父類(lèi)方法的調(diào)用。
仔細(xì)看了一下所有代碼,發(fā)現(xiàn)還有一句很奇怪的東西:
#import "CardboardAppController.h"
extern "C" {
extern void readProfile();
extern void syncProfile();
extern void createSettingsButton(id app, UIView* view);
extern UIViewController* createSettingsDialog(id app);
extern UIViewController* createOnboardingDialog(id app);
bool isOpenGLAPI() {
#if UNITY_VERSION < 463
return true;
#else
CardboardAppController* app = (CardboardAppController *)GetAppController();
UnityRenderingAPI api = [app renderingAPI];
return api == apiOpenGLES2 || api == apiOpenGLES3;
#endif
}
void launchSettingsDialog() {
CardboardAppController* app = (CardboardAppController *)GetAppController();
[app launchSettingsDialog];
}
void launchOnboardingDialog() {
CardboardAppController* app = (CardboardAppController *)GetAppController();
[app startSettingsDialog:createOnboardingDialog(app)];
}
void endSettingsDialog() {
CardboardAppController* app = (CardboardAppController *)GetAppController();
[app stopSettingsDialog];
}
}? // extern "C"
@implementation CardboardAppController
- (void)preStartUnity {
[super preStartUnity];
syncProfile();
}
- (UnityView *)createUnityView {
UnityView* unity_view = [super createUnityView];
createSettingsButton(self, (UIView *)unity_view);
return unity_view;
}
- (void)launchSettingsDialog {
[self startSettingsDialog:createSettingsDialog(self)];
}
- (void)startSettingsDialog:(UIViewController*)dialog {
[self pause:YES];
[self.rootViewController presentViewController:dialog animated:NO completion:nil];
}
- (void)stopSettingsDialog {
[[self rootViewController] dismissViewControllerAnimated:NO completion:nil];
[self pause:NO];
}
- (void)pause:(bool)paused {
#if UNITY_VERSION < 462
UnityPause(paused);
#else
self.paused = paused;
#endif
}
@end
IMPL_APP_CONTROLLER_SUBCLASS(CardboardAppController)
最后一句的IMPL_APP_CONTROLLER_SUBCLASS(CardboardAppController)是宏定義,在UnityAppController.h文件里可以找到
#define IMPL_APP_CONTROLLER_SUBCLASS(ClassName) \
@interface ClassName(OverrideAppDelegate) \
{ \
} \
+(void)load; \
@end \
@implementation ClassName(OverrideAppDelegate) \
+(void)load \
{ \
extern const char* AppControllerClassName; \
AppControllerClassName = #ClassName; \
} \
@end \
貌似是用分類(lèi)的方法,幫子類(lèi)寫(xiě)了一個(gè)load方法,然而在VuforiaNativeRendererController.mm也有一句這樣的宏,VuforiaNativeRendererController.mm也是UnityAppController的子類(lèi)。
我嘗試把CardboardAppController里面的load方法宏注釋掉,black camera也能解決了。
到底是不是這個(gè)宏的影響,還在研究中。。。