Commit a0fd194e cgx

解决Unity在静音模式下无法播放bug

1 个父辈 28bd1061
......@@ -14,6 +14,7 @@
#pragma mark - Unity
@property (nonatomic, strong) NSDictionary * appLaunchOpts;
@property (nonatomic, strong) UnityFramework* ufw;
/// 显示unity
- (void)showUnityView;
@end
......
......@@ -64,7 +64,7 @@
[[IQKeyboardManager sharedManager] setEnable:YES];
[[IQKeyboardManager sharedManager] setEnableAutoToolbar:YES];
[[IQKeyboardManager sharedManager] setShouldResignOnTouchOutside:YES];
return YES;
}
......@@ -162,13 +162,10 @@
UnityFramework* UnityFrameworkLoad(void) {
NSString* bundlePath = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/Frameworks/UnityFramework.framework"];
NSBundle* bundle = [NSBundle bundleWithPath:bundlePath];
if ([bundle isLoaded] == false) [bundle load];
if ([bundle isLoaded] == false) { [bundle load]; }
UnityFramework* ufw = [bundle.principalClass getInstance];
if (![ufw appController])
{
[ufw setExecuteHeader: &_mh_execute_header];
}
UnityFramework *ufw = [bundle.principalClass getInstance];
if (![ufw appController]) { [ufw setExecuteHeader:&_mh_execute_header]; }
return ufw;
}
......@@ -180,17 +177,16 @@ extern int gArgc;
extern char** gArgv;
- (void)initUnity {
if([self unityIsInitialized]) {
[DSProgressHUD showDetailInfo:@"Unload Unity first"];
// unity如果初始化了,首先需要卸载unity
if ([self unityIsInitialized]) {
[DSProgressHUD showDetailInfo:@"Unity already initialized,please unload unity first"];
return;
}
[self setUfw: UnityFrameworkLoad()];
[self setUfw:UnityFrameworkLoad()];
[[self ufw] setDataBundleId:"com.unity3d.framework"];
[[self ufw] registerFrameworkListener:self];
[[self ufw] runEmbeddedWithArgc:gArgc argv:gArgv appLaunchOpts:self.appLaunchOpts];
[[[self ufw] appController] rootView];
}
- (void)showUnityView {
......@@ -201,15 +197,16 @@ extern char** gArgv;
#pragma mark - UnityFrameworkListener
- (void)unityDidUnload:(NSNotification*)notification {
DSLog(@"unityDidUnloaded called");
DSLog(@"unityDidUnload");
[self.window makeKeyAndVisible];
[[self ufw] unregisterFrameworkListener:self];
[self setUfw: nil];
[self.window makeKeyAndVisible];
}
- (void)unityDidQuit:(NSNotification *)notification {
DSLog(@"========== %s ============", __func__);
}
- (void)applicationWillResignActive:(UIApplication *)application { [[[self ufw] appController] applicationWillResignActive: application]; }
- (void)applicationDidEnterBackground:(UIApplication *)application { [[[self ufw] appController] applicationDidEnterBackground: application]; }
- (void)applicationWillEnterForeground:(UIApplication *)application { [[[self ufw] appController] applicationWillEnterForeground: application]; }
- (void)applicationDidBecomeActive:(UIApplication *)application { [[[self ufw] appController] applicationDidBecomeActive: application]; }
- (void)applicationWillTerminate:(UIApplication *)application { [[[self ufw] appController] applicationWillTerminate: application]; }
@end
......@@ -36,6 +36,7 @@ __attribute__ ((visibility("default")))
id<RenderPluginDelegate> _renderDelegate;
}
@property (strong, nonatomic) UIViewController *vc;
// override it to add your render plugin delegate
- (void)shouldAttachRenderDelegate;
......
......@@ -94,14 +94,14 @@ NSInteger _forceInterfaceOrientationMask = 0;
// we will simply assert if deprecated methods are present
// NB: methods table is initied at load (before this call), so it is ok to check for override
NSAssert(![self respondsToSelector: @selector(createUnityViewImpl)],
@"createUnityViewImpl is deprecated and will not be called. Override createUnityView"
);
@"createUnityViewImpl is deprecated and will not be called. Override createUnityView"
);
NSAssert(![self respondsToSelector: @selector(createViewHierarchyImpl)],
@"createViewHierarchyImpl is deprecated and will not be called. Override willStartWithViewController"
);
@"createViewHierarchyImpl is deprecated and will not be called. Override willStartWithViewController"
);
NSAssert(![self respondsToSelector: @selector(createViewHierarchy)],
@"createViewHierarchy is deprecated and will not be implemented. Use createUI"
);
@"createViewHierarchy is deprecated and will not be implemented. Use createUI"
);
}
return self;
}
......@@ -117,28 +117,29 @@ NSInteger _forceInterfaceOrientationMask = 0;
- (void)startUnity:(UIApplication*)application
{
NSAssert(_unityAppReady == NO, @"[UnityAppController startUnity:] called after Unity has been initialized");
UnityInitApplicationGraphics();
// we make sure that first level gets correct display list and orientation
[[DisplayManager Instance] updateDisplayListCacheInUnity];
UnityLoadApplication();
Profiler_InitProfiler();
[self showGameUI];
[self createDisplayLink];
UnitySetPlayerFocus(1);
AVAudioSession* audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
[audioSession setActive: YES error: nil];
[audioSession addObserver: self forKeyPath: @"outputVolume" options: 0 context: nil];
UnityUpdateMuteState([audioSession outputVolume] < 0.01f ? 1 : 0);
#if UNITY_REPLAY_KIT_AVAILABLE
void InitUnityReplayKit(); // Classes/Unity/UnityReplayKit.mm
InitUnityReplayKit();
#endif
}
......@@ -164,21 +165,21 @@ extern "C" void UnityCleanupTrampoline()
// We need to ensure that these objects will not receive any callbacks from system during that time.
[_UnityAppController window].rootViewController = nil;
[[_UnityAppController unityView] removeFromSuperview];
// Prevent multiple cleanups
if (_UnityAppController == nil)
return;
[KeyboardDelegate Destroy];
SensorsCleanup();
Profiler_UninitProfiler();
[DisplayManager Destroy];
UnityDestroyDisplayLink();
_UnityAppController = nil;
}
......@@ -189,12 +190,12 @@ extern "C" void UnityCleanupTrampoline()
// No rootViewController is set because we are switching from one view controller to another, all orientations should be enabled
if ([window rootViewController] == nil)
return UIInterfaceOrientationMaskAll;
// During splash screen show phase no forced orientations should be allowed.
// This will prevent unwanted rotation while splash screen is on and application is not yet ready to present (Ex. Fogbugz cases: 1190428, 1269547).
if (!_unityAppReady)
return [_rootController supportedInterfaceOrientations];
// Some presentation controllers (e.g. UIImagePickerController) require portrait orientation and will throw exception if it is not supported.
// At the same time enabling all orientations by returning UIInterfaceOrientationMaskAll might cause unwanted orientation change
// (e.g. when using UIActivityViewController to "share to" another application, iOS will use supportedInterfaceOrientations to possibly reorient).
......@@ -260,7 +261,7 @@ extern "C" void UnityCleanupTrampoline()
- (BOOL)application:(UIApplication*)app openURL:(NSURL*)url options:(NSDictionary<NSString*, id>*)options
{
id sourceApplication = options[UIApplicationOpenURLOptionsSourceApplicationKey], annotation = options[UIApplicationOpenURLOptionsAnnotationKey];
NSMutableDictionary<NSString*, id>* notifData = [NSMutableDictionary dictionaryWithCapacity: 3];
if (url)
{
......@@ -269,16 +270,16 @@ extern "C" void UnityCleanupTrampoline()
}
if (sourceApplication) notifData[@"sourceApplication"] = sourceApplication;
if (annotation) notifData[@"annotation"] = annotation;
AppController_SendNotificationWithArg(kUnityOnOpenURL, notifData);
return YES;
}
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity
#if defined(__IPHONE_12_0) || defined(__TVOS_12_0)
restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring> > * _Nullable restorableObjects))restorationHandler
restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring> > * _Nullable restorableObjects))restorationHandler
#else
restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler
restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler
#endif
{
NSURL* url = userActivity.webpageURL;
......@@ -296,34 +297,34 @@ extern "C" void UnityCleanupTrampoline()
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
::printf("-> applicationDidFinishLaunching()\n");
// send notfications
#if !PLATFORM_TVOS
if (UILocalNotification* notification = [launchOptions objectForKey: UIApplicationLaunchOptionsLocalNotificationKey])
UnitySendLocalNotification(notification);
if ([UIDevice currentDevice].generatesDeviceOrientationNotifications == NO)
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
#endif
UnityInitApplicationNoGraphics(UnityDataBundleDir());
[self selectRenderingAPI];
[UnityRenderingView InitializeForAPI: self.renderingAPI];
_window = [[UIWindow alloc] initWithFrame: [UIScreen mainScreen].bounds];
_unityView = [self createUnityView];
[DisplayManager Initialize];
_mainDisplay = [DisplayManager Instance].mainDisplay;
[_mainDisplay createWithWindow: _window andView: _unityView];
[self createUI];
[self preStartUnity];
// if you wont use keyboard you may comment it out at save some memory
[KeyboardDelegate Initialize];
return YES;
}
......@@ -343,7 +344,7 @@ extern "C" void UnityCleanupTrampoline()
- (void)applicationWillEnterForeground:(UIApplication*)application
{
::printf("-> applicationWillEnterForeground()\n");
// applicationWillEnterForeground: might sometimes arrive *before* actually initing unity (e.g. locking on startup)
if (_unityAppReady)
{
......@@ -355,9 +356,9 @@ extern "C" void UnityCleanupTrampoline()
- (void)applicationDidBecomeActive:(UIApplication*)application
{
::printf("-> applicationDidBecomeActive()\n");
[self removeSnapshotViewController];
if (_unityAppReady)
{
if (UnityIsPaused() && _wasPausedExternal == false)
......@@ -378,11 +379,67 @@ extern "C" void UnityCleanupTrampoline()
{
_startUnityScheduled = true;
[self performSelector: @selector(startUnity:) withObject: application afterDelay: 0];
// 替换startUnity:为startSelfIOSView
// [self performSelector: @selector(startSelfIOSView) withObject: application afterDelay: 0];
}
_didResignActive = false;
}
// 创建原生页面和控件,自己控制唤起Unity时机
- (void)startSelfIOSView
{
UIViewController *vc = [[UIViewController alloc] init];
vc.view.frame = [UIScreen mainScreen].bounds;
vc.view.backgroundColor = [UIColor blackColor];
UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(100, 100, 200, 50)];
btn.backgroundColor = [UIColor blueColor];
[btn setTitle:@"跳转到Unity界面" forState:UIControlStateNormal];
// 按钮被点击时唤起Unity项目
[btn addTarget:self action:@selector(startUnity:) forControlEvents:UIControlEventTouchUpInside];
[vc.view addSubview:btn];
self.vc = vc;
[_window addSubview:vc.view];
[self addGLViewButton];
}
// 在UnityGetGLView上添加按钮
- (void)addGLViewButton
{
// 添加右旋按钮
UIButton *rightBtn = [[UIButton alloc] initWithFrame:CGRectMake(10, 150, 100, 30)];
rightBtn.backgroundColor = [UIColor whiteColor];
[rightBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[rightBtn setTitle:@"向右旋转" forState:UIControlStateNormal];
[rightBtn addTarget:self action:@selector(turnRight) forControlEvents:UIControlEventTouchUpInside];
// 添加左旋按钮
UIButton *leftBtn = [[UIButton alloc] initWithFrame:CGRectMake(10, 200, 100, 30)];
leftBtn.backgroundColor = [UIColor whiteColor];
[leftBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[leftBtn setTitle:@"向左旋转" forState:UIControlStateNormal];
[leftBtn addTarget:self action:@selector(turnLeft) forControlEvents:UIControlEventTouchUpInside];
// 在Unity界面添加按钮
[UnityGetGLViewController().view addSubview:rightBtn];
[UnityGetGLViewController().view addSubview:leftBtn];
}
// 左旋按钮响应事件
- (void)turnRight
{
const char* str = [[NSString stringWithFormat:@"向右"] UTF8String];
UnitySendMessage("_bridgeManager", "turnRight", str);
}
// 右旋按钮响应事件
- (void)turnLeft
{
const char* str = [[NSString stringWithFormat:@"向左"] UTF8String];
UnitySendMessage("_bridgeManager", "turnLeft", str);
}
- (void)updateUnityAudioOutput
{
UnityUpdateAudioOutputState();
......@@ -402,15 +459,15 @@ extern "C" void UnityCleanupTrampoline()
{
return;
}
UIView* snapshotView = [self createSnapshotView];
if (snapshotView != nil)
{
_snapshotViewController = [[UIViewController alloc] init];
_snapshotViewController.modalPresentationStyle = UIModalPresentationFullScreen;
_snapshotViewController.view = snapshotView;
[_rootController presentViewController: _snapshotViewController animated: false completion: nil];
}
});
......@@ -429,10 +486,10 @@ extern "C" void UnityCleanupTrampoline()
[self performSelector: @selector(removeSnapshotViewController) withObject: nil afterDelay: 0.05];
return;
}
[_snapshotViewController dismissViewControllerAnimated: NO completion: nil];
_snapshotViewController = nil;
// Make sure that the keyboard input field regains focus after the application becomes active.
[[KeyboardDelegate Instance] becomeFirstResponder];
}
......@@ -442,15 +499,15 @@ extern "C" void UnityCleanupTrampoline()
- (void)applicationWillResignActive:(UIApplication*)application
{
::printf("-> applicationWillResignActive()\n");
if (_unityAppReady)
{
UnitySetPlayerFocus(0);
// signal unity that the frame rendering have ended
// as we will not get the callback from the display link current frame
UnityDisplayLinkCallback(0);
_wasPausedExternal = UnityIsPaused();
if (_wasPausedExternal == false)
{
......@@ -464,12 +521,12 @@ extern "C" void UnityCleanupTrampoline()
UnityWillPause();
[self repaint];
UnityPause(1);
[self addSnapshotViewController];
}
}
}
_didResignActive = true;
}
......@@ -482,7 +539,7 @@ extern "C" void UnityCleanupTrampoline()
- (void)applicationWillTerminate:(UIApplication*)application
{
::printf("-> applicationWillTerminate()\n");
// Only clean up if Unity has finished initializing, else the clean up process will crash,
// this happens if the app is force closed immediately after opening it.
if (_unityAppReady)
......@@ -551,35 +608,35 @@ static bool isDebuggerAttachedToConsole(void)
int mib[4];
struct kinfo_proc info;
size_t size;
// Initialize the flags so that, if sysctl fails for some bizarre
// reason, we get a predictable result.
info.kp_proc.p_flag = 0;
// Initialize mib, which tells sysctl the info we want, in this case
// we're looking for information about a specific process ID.
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = getpid();
// Call sysctl.
size = sizeof(info);
junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
assert(junk == 0);
// We're being debugged if the P_TRACED flag is set.
return ((info.kp_proc.p_flag & P_TRACED) != 0);
}
void UnityInitTrampoline()
{
InitCrashHandling();
NSString* version = [[UIDevice currentDevice] systemVersion];
#define CHECK_VER(s) [version compare: s options: NSNumericSearch] != NSOrderedAscending
_ios81orNewer = CHECK_VER(@"8.1"), _ios82orNewer = CHECK_VER(@"8.2"), _ios83orNewer = CHECK_VER(@"8.3");
......@@ -588,9 +645,9 @@ void UnityInitTrampoline()
_ios110orNewer = CHECK_VER(@"11.0"), _ios111orNewer = CHECK_VER(@"11.1"), _ios112orNewer = CHECK_VER(@"11.2");
_ios130orNewer = CHECK_VER(@"13.0");
#undef CHECK_VER
AddNewAPIImplIfNeeded();
#if !TARGET_IPHONE_SIMULATOR
// Use NSLog logging if a debugger is not attached, otherwise we write to stdout.
if (!isDebuggerAttachedToConsole())
......@@ -622,7 +679,7 @@ static void AddNewAPIImplIfNeeded()
});
class_replaceMethod([UIScreen class], @selector(maximumFramesPerSecond), UIScreen_MaximumFramesPerSecond_IMP, UIScreen_maximumFramesPerSecond_Enc);
}
if (![[UIView class] instancesRespondToSelector: @selector(safeAreaInsets)])
{
IMP UIView_SafeAreaInsets_IMP = imp_implementationWithBlock(^UIEdgeInsets(id _self) {
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!