Category Archives: Unity3d

Blank Game View in Unity3D Editor

Since a recent Unity update (pretty sure it’s the one that added the ability to scale the gameview) I’ve been seeing an intermittent issue where the game view will just go blank.  This happens in both Edit & Play mode, but only on my Mac.  Initially, I had to quit and reload Unity to resolve it, but discovered, reselecting my window layout from the ‘Layout’ drop down restored the game view.  So it became annoying and not as aggravating :D.

I’ve been following a thread on the Unity forums where this is being discussed:

http://forum.unity3d.com/threads/blank-game-view.421817/#post-2772116

I tried the suggested start-up flag and the problem went away, though I noticed a performance drop in the editor, but nothing serious.  I used the following command line from a terminal window to start Unity with the flag set.  (Note, I have my copy of Unity in a folder that includes the version name, you might need to change that):

/Applications/Unity5.4.0/Unity.app/Contents/MacOS/Unity -force-gfx-direct

I hope they find & fix this one soon.

NGUI EventDelegate

I have a button whose function changes depending on which panel is currently being displayed.  When switching panels, this button stays on screen (think a NavBar).  I ran into this unexpected behavior today, that slowed me down.

If you change the contents of an EventDelegate list during a method called from that  EventDelegate list then its probable that your new method will get called right way when control is passed back to the Execute method of EventDelegate.  This looked like the OnClick method of a UIButton was not waiting for a release, so I went down that rabbit hole for a bit.

I ended up adding a short delay to the code that switches the current OnClick action to the new OnClick action, which solved the problem.

	button.onClick.Clear();
	//delay this by a frame, so it happens outside the EventDelegate processing
	callAfterDelay(0.01f,()=>{
		button.onClick.Add(action);
	});

Accessing a Struct as a SerializedProperty

I’m working on a custom editor extension that will support a palatalized color system for Unity3D UI elements (both NGUI and new Unity UI).  As part of this process I’m learning how to create custom Inspectors and PropertyDrawers.

I added a struct to one of my objects that replaced a simple Int, and I needed to be able to access the struct from an inspector.  Normally, to access the Int you’d create a SerializedProperty that would point to the public serialized int and then access the value with the .intValue property.

Once I updated the class to use a custom struct, the inspector no longer worked (obviously) and I needed to pull values from this struct instead of a primitive type.

The struct is defined as:

    [Serializable]
    public struct PBMapperIndex
    {
        public int intValue;
        public string indexName;
    }

It contains a string and an int, and most importantly, it’s marked as serializable. This means Unity will keep the struct as a serializable object.

To access it in the custom inspector, I used the following:

    SerializedProperty tintProp = serializedObject.FindProperty(tintIndex);

Where tinitIndex is declared as a public PBMapperIndex in my class.

Then to drill down and get the intValue for this property I used:

        SerializedProperty ixProp = tintProp.FindPropertyRelative(intValue);
        int  index = ixProp.intValue;

Two keys, mark the original struct as [Serializable] and then used FindPropertyRelative to pull out the ‘child’ property.

Apple WatchKit 2.2 – NATIVE apps what are they good for?

We have a workout app that supports the Apple Watch, and it was something that I’d hacked into the original project when the watch first shipped.  It’s a Unity3D based project and back then, adding the Watch target was a real pain, but I managed to get it done and even got it working as best as I could.

One of the major complaints was that the watch didn’t always notify users when a workout ended and a new one would start.  With the original WatchKit there was no way to access the haptic feedback system or even make the watch go ‘bing’. I’d used local notifications to make this happen as best as possible, but iOS decides if it’s going to forward a notification to the watch or not, and there was no way to ensure such forwarding – very haphazard…

Enter WatchKit 2 and NATIVE watch apps.  I was quite excited about this, I’d be able to update the code and fix the biggest complaint the app received from our users.  I’d be able to make the watch buzz and bing on command!

I started this update a few weeks back, and migrated the code to the new WatchKit2 system and had the code run on the watch.  In the simulator, things were working really well, however I was having difficulties in getting the app to actually run on my watch.  Turns out all was not well with my XCode project and the watch wouldn’t validate the binary and run it.  Of course, there was no error popups or feedback to XCode, just silence.

After numerous reboots of everything involved, a pairing of the watch to another test phone, I decided to try a new XCode project just to see where the problem actually was.  That new project built & ran just fine, and when I copied my code & storyboards across from the old project (one file at a time) that also worked as expected.  Huzzah, I had my code running on my watch.  I retired the old XCode project and continued with the new one.

At this point, I was able to run my code on an actual watch.  This was after a frustrating few days of trying everything else to resolve the problems.  So my frustration level was then enhanced when I discovered that an App running on the actual watch is suspended when the watch sleeps, or the user taps the crown to return to the clock display.  This didn’t happen on the simulator!  Some simulation!

It turns out all my previous work was pretty useless.  The App I’d moved to run independently of the attached iPhone does not work as expected.  If I setup an NSTimer to alert the user when it’s time to switch an activity, unless the user keeps the watch alive by tapping the screen, that NSTimer is suspended when the watch sleeps.  The timer never expires, the user is never alerted, and the App fails.

Even if I put all the code back on the iPhone, I can’t even make the watch vibrate and bing when the NSTimer expires, unless the watch happens to be awake when that happens and the user happens to have my App in the foreground.  So I’m back to the unreliable notification system with all the same problems as before.  There really is no point in building an update at this point.

I was pretty excited by WatchKit2, I really thought it would solve the issues I had with the original WatchKit, but it seems that once again, Apple have dropped the ball and not provided a cure.  I know the battery drain is the biggest concern, but seriously, couldn’t you spare enough juice to run one special background timer and let us notify the user when it expires…

Grrrrr.

More Java issues

I’ve upgraded some of the projects I’ve been working on to Unity 5 and at the same time, I upgraded the Google Play Unity plugin to the latest version.

The GP plugin now uses AAR files (a android library file) instead of JARs (a standard java library file).  Unity 5 prefers AAR’s so that makes sense.  However, I ran into a headscratcher when my plugins (JAR files) started giving me the ‘java.lang.NoSuchMethodError’ errors again.

I verified I had all the libraries I needed in my Plugin folder so I couldn’t see what the problem was.  As I was messing with various debug additions I noticed the the standard GooglePlay folder was being deleted by something in Unity from my Plugin folder, and that this was the root of the problem.

A little more digging and I discovered that the new version of the GPlay plugin will remove that folder from Plugin/Android and then includes the ‘referenced’ parts of the library when you compile it for your android build.  As their plugin didn’t use the advertising or analytic’s part of the GPlay libraries, it was not including it in the final APK, and my plugins would then fail as I use both of those.

They have a mechanism to create a c# class that their code will pull in and let you add additional dependencies, which in turn enables those sections to be included in the APK.  I wasn’t able to figure that out, and in frustration (I’d already spent several hours tracking this down) I just modified a file in their plugin to include the dependencies I wanted.

I modified the static constructor by adding two lines to PlayServicesResolver.cs

        static PlayServicesResolver()
        {
            svcSupport = PlayServicesSupport.CreateInstance(
                PlayServicesResolver,
                EditorPrefs.GetString(AndroidSdkRoot),
                ProjectSettings);
            //CG  added the following two lines
            svcSupport.DependOn(com.google.android.gms, playservicesads, GooglePlayGames.PluginVersion.PlayServicesVersionConstraint);
            svcSupport.DependOn(com.google.android.gms, playservicesanalytics, GooglePlayGames.PluginVersion.PlayServicesVersionConstraint);

        }

These two lines keep the analytics and AdMob modules in the final APK and most importantly, let my plugins function as expected.  When I have time, I’ll figure out the correct way to do this.