Friday 23 February 2018

How to overlay a firework show before your 2D GUI in Unity3D

You may want to have a firework show in your 2D game when your user wins. It is pretty easy with Unity3D.

Just add a new camera to your existing scene. Set "Clear Flags" to "Don't clear", and set "Depth" to a greater value than that of your 2D GUI's camera. Then what ever this camera sees will be displayed over your 2D GUI.

Then add your firework prefab as child of your new camera, and adjust its position so that it looks good in your camera. And that's it.

Wednesday 14 February 2018

NullReferenceException with unity3d on iOS

To debug NullReferenceException on iOS, write lots of Debug.Log for objects, and in build settings enable development build and script debugging.

This could happen if GameObject.FindGameObjectWithTag is used in Awake or Start because the object may not be created when Awake or Start is executed. The issue may not show up in editor since in editor the objects may already be there but they may not be created when running the app on iOS. One workaround is to do it at point of usage when the object has been created.

Saturday 13 January 2018

uncaught exception [FIRApp configure]

erminating app due to uncaught exception 'com.firebase.core', reason: '`[FIRApp configure];` (`FirebaseApp.configure()` in Swift) could not find a valid GoogleService-Info.plist in your project. Please download one from https://console.firebase.google.com/.'
*** First throw call stack:
(
0   CoreFoundation                      0x000000011718e12b __exceptionPreprocess + 171
1   libobjc.A.dylib                     0x00000001162ddf41 objc_exception_throw + 48
2   CoreFoundation                      0x0000000117203245 +[NSException raise:format:] + 197
3   SimplePeriod                        0x000000010e1a212a +[FIRApp configure] + 352
4   SimplePeriod                        0x000000010e1397cd myinit + 61
5   SimplePeriod                        0x000000010e108cff -[ICAppDelegate applicationDidFinishLaunching:] + 351
6   UIKit                               0x0000000113587c0c -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 365
7   UIKit                               0x00000001135896bd -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4230
8   UIKit                               0x000000011358eaeb -[UIApplication _runWithMainScene:transitionContext:completion:] + 1720
9   UIKit                               0x00000001139586f8 __111-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:]_block_invoke + 924
10  UIKit                               0x0000000113d2e4c8 +[_UICanvas _enqueuePostSettingUpdateTransactionBlock:] + 153
11  UIKit                               0x00000001139582f1 -[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:] + 249
12  UIKit                               0x0000000113958b6b -[__UICanvasLifecycleMonitor_Compatability activateEventsOnly:withContext:completion:] + 696
13  UIKit                               0x00000001142d6a69 __82-[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:]_block_invoke + 262
14  UIKit                               0x00000001142d6922 -[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:] + 444
15  UIKit                               0x0000000113fb39c8 __125-[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:]_block_invoke + 221
16  UIKit                               0x00000001141b2b06 _performActionsWithDelayForTransitionContext + 100
17  UIKit                               0x0000000113fb388b -[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:] + 231
18  UIKit                               0x0000000113d2db25 -[_UICanvas scene:didUpdateWithDiff:transitionContext:completion:] + 392
19  UIKit                               0x000000011358d36a -[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 523
20  UIKit                               0x0000000113b68605 -[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 369
21  FrontBoardServices                  0x000000011c498cc0 -[FBSSceneImpl _didCreateWithTransitionContext:completion:] + 338
22  FrontBoardServices                  0x000000011c4a17b5 __56-[FBSWorkspace client:handleCreateScene:withCompletion:]_block_invoke_2 + 235
23  libdispatch.dylib                   0x000000011585933d _dispatch_client_callout + 8
24  libdispatch.dylib                   0x000000011585e9f3 _dispatch_block_invoke_direct + 592
25  FrontBoardServices                  0x000000011c4cd498 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 24
26  FrontBoardServices                  0x000000011c4cd14e -[FBSSerialQueue _performNext] + 464
27  FrontBoardServices                  0x000000011c4cd6bd -[FBSSerialQueue _performNextFromRunLoopSource] + 45
28  CoreFoundation                      0x0000000117131101 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
29  CoreFoundation                      0x00000001171d0f71 __CFRunLoopDoSource0 + 81
30  CoreFoundation                      0x0000000117115a19 __CFRunLoopDoSources0 + 185
31  CoreFoundation                      0x0000000117114fff __CFRunLoopRun + 1279
32  CoreFoundation                      0x0000000117114889 CFRunLoopRunSpecific + 409
33  GraphicsServices                    0x0000000118d479c6 GSEventRunModal + 62
34  UIKit                               0x00000001135905d6 UIApplicationMain + 159
35  SimplePeriod                        0x000000010e10b50f main + 111

36  libdyld.dylib                       0x00000001158d5d81 start + 1

The issue is due to FireBase not configured.
The fix is set up FireBase for the target and download and add GoogleService-Info.plist to the target.

Sunday 29 September 2013

iOS 7 UINavigationController layout issue and workaround

Before iOS 7, UINavigationController layouts navigation bar above the view to be displayed. In iOS 7, the navigation bar is overlapping with the view to be displayed. This causes display issue for certain views. One workaround is through UINavigationControllerDelegate.

// Workaround for iOS7 UINavigationController layout issue.
// In iOS7, navigation bar is overlapping with the displayed view.
// Needs to shift it down by navigation bar height and shrink its height.
// But do not do this for table view.
- (void)navigationController:(UINavigationController *)navigationController
  didShowViewController:(UIViewController *)vc
animated:(BOOL)animated {
    if(!IOS7_OR_UP)
        return;
    if ([vc.view isKindOfClass:NSClassFromString(@"UITableView")])
        return;
    
    static int barH = 0;
    if (barH == 0) {
        UIView* bar = findViewOfClass(vc.view.superview.superview.superview, NSClassFromString(@"UINavigationBar"));
        barH = bar.frame.size.height;
    }
    
    CGRect frame = vc.view.frame;
    frame.size.height -= barH;
    frame.origin.y = barH;
    vc.view.frame = frame;

}

iOS 7 UITabBarController layout issue and workaround

Before iOS 7, UITabBarController layout the tab bar below the view to be displayed. However, in iOS 7, the tab bar is overlapping with the view to be displayed. This causes some display issues for some views drawn by user.

One workaround is to shrink the size of the view to be displayed by the UITabBarController by subclass UITabBarController.

@interface MyTabBarController : UITabBarController

@end

@implementation MyTabBarController

// Workaround for iOS UITabBarController layout issue.
// In iOS7, the tab bar overlaps with the view to be displayed.
// The height of the view to be displayed with a UITabBarController needs
// to be shrinked by the height of the tab bar.
-(void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    
    if (!IOS7_OR_UP)
        return;
    
    static int barHeight = 0;
    if (barHeight == 0) {
        UIView* bar = findViewOfClass(self.view, NSClassFromString(@"UITabBar"));
        barHeight = bar.frame.size.height;
    }
    UIView* CV = (UIView*)self.view.subviews.firstObject;
    CV.autoresizesSubviews = YES;
    UIView* GCV = (UIView*) CV.subviews.firstObject;
    UIView* GGCV = (UIView*) GCV.subviews.firstObject;
    CGRect frame = CV.frame;
    frame.size.height = self.view.frame.size.height - barHeight;
    CV.frame = frame;
    GCV.frame = frame;
    GGCV.frame = frame;
    
}

@end

Friday 26 July 2013

OpenGL ES: How to rotate around a specific point instead of origin?

If you want to rotate around a point (x0, y0, z0), assuming

matrix-vector multiplication order is vector * matrix,

your current modelview matrix is M1,

the rotation matrix is MR,

translation matrix from (0, 0, 0) to (x0, y0, z0) is T(x0, y0, z0),

After rotation, the modelview matrix should be

M1*T(-x0, -y0, -z0) * MR * T(x0, y0, z0)

Note if (x0, y0, z0) is in world coordinates, it needs to be first transformed to eye coordinates by

(x0, y0, z0) * M1


OpenGL ES: Is modelview matrix column major or row major?

Modelview matrix is column major. In memory, it is like

M00, M10, M20, M30, M01, M11, M21, M31, M02, M12, M22, M32, M03, M13, M23, M33

A translation of (x, y, z) is

1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1

In GLSL, matrix vector multiplication is defined as matrix * vector.

In host program, depending on how you define your matrix vector multiplication operator, it can be either matrix * vector or vector * matrix.

For a series of transformations M1, M2, M3,

if you define matrix-vector multiplication as matrix * vector,  the total transformation is

M3 * M2 * M1

If you define it as vector * matrix, the total transformation is

M1 * M2 * M3