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.

AndroidJavaException: java.lang.NoSuchMethodError: no static method

I’ve been working on updating my Unity3D Android plugins, and decided to make a new project to test them in.  On and off for the past few days I’ve been trying to nail down the reason for the following error:

AndroidJavaException: java.lang.NoSuchMethodError: no static method “Lcom/purplebuttons/unity/PBAndroidUtils;.PBInitAndroidUtils(Lcom.unity3d.player.UnityPlayerNativeActivity;Z)V”

I get this error when the plugin is initialized, and it looks like Unity can’t find my static method.  I checked my parameters, verified that the method name was correct, checked that the JAR was in my plugins/android folder.  Everything checked out, but I was still getting the error.

I rolled the plugin back to a version from another project I knew worked as intended.  No difference, same error.  Lots of google searching and still nothing obvious.  The most common cause is either the parameters not matching, an incorrect java class path, or a misspelled method name.  I had none of those.

So I duplicated a working project that called the plugin without any errors, and started stripping it back.  Removed lots of scripts, objects, images & sounds. Finally I started pairing down the plugins/android directory, and that’s when it happened – I found the error.

Turns out I needed to include the ‘google-play-services_lib’ in my plugins/android folder.  The plugin jar used various bits & bobs from this lib and without it included in the APK, the plugin would fail to load when called, and return the error above, which didn’t really explain what was going on.

When I created the test project, I didn’t think to copy that forward, and hence my wasted time…

Extending the Unity3D Color struct

I’m working on a convenience class that will allow me to specify the color used by an NGUI item by the SVG/HTML named color list (http://www.december.com/html/spec/colorsvg.html).

I was hoping I could extend the standard Unity3D Color class by adding a static method that could be used to update the color values, however as Color is a struct and not a class, you can’t update the value in an extension method as a copy is passed.

    public static void ColorWithName(this Color color,
     PBColor.ColorNames name)
    {
        color = PBColor.FromName(name);
    }

This will not work as expected.  The var color points to a copy of the calling color struct and not the actual struct, so any changes are discarded 🙁

I ended up with this:

    public static void ColorWithName(this UIWidget widget,
     PBColor.ColorNames name)
    {
        widget.color = PBColor.FromName(name);
    }

Not as convenient as I wanted, but it gets the job done as below:

    widget.ColorWithName(ColorNames.GoldenRod);

where widget is an NGUI.UIWidget object.

Unity 3D c# and lack of Tuple

Unfortunately the compiler used for Unity 3D does not support Tuples.  Tuples are a convenient way to lump a couple of types together into one object without creating a class.

So, if like me you needed a list to contain a string and a float for one entry, you could do so like this:

    public List<Tuple<string,float>> things;

Then you could access the parts of the item, add both parts at the same time, etc.

There are a bunch of class definitions available that will let you use something very similar to Tuple in Unity.  I didn’t want to go to that effort, so I ended up with using an ArrayList.  This will hold multiple objects of different types in a nice ordered array.

    public List<ArrayList> things;

Now each item in the list is an array and I can get at the contents using normal array syntax.

     ArrayList thing = things[0];
     label.text = thing[0as string;
     duration = (float)thing[1];

There’s no error checking here, but you get the basic idea.

Renaming c# classes and Unity…

As far as I know, there is no ‘correct’ way to rename a class that you’ve built inside a Unity C# file with ease and 0 pain…  but there is certainly a wrong way to do it:

Approach it in this order:

Rename the ????.cs file using the Unity Editor.  Click on the file in the project explorer and use what ever method you’d like to rename it to the new class name.  This means that Unity will keep a reference to the newly named file and any instances of that class file attached to objects in the scene will get updated.

Now, open the file in your text editor (Mono, VS, whatever) and use ‘Refactor or Rename’ on the actual class name and let the editor change all references in the project.  Save all the changed files and you should be able to build just fine.

Go back to Unity and the project should build and run without any errors.

If you do what I did – rename the class first in your text editor, then you’ll end up replacing every ‘missing script’ error by hand – not so much fun — you’ve been warned!