Unity: Networking Does Not Work in the Editor

This is an embarrassing post. Some days are there to simply remind you that you don’t really know what you are doing. I spent two days trying to track down why my networking scripts were not working when I ran them in the editor. Turns out that the editor makes it’s own internal network stack when running a project which does not connect to the normal ethernet ports on your machine.

Top Tip ! Build you project and run it natively if you are using TCP/IP connections ! Don’t try and run it in the editor (not even for quick checks or small simple projects) it simply won’t work.

The really nice thing is after I got it all working I built a touch screen controller for Android phones that can be used as input in a Unity game.

The code is in the repo: https://github.com/zuluonezero/AndroidTouchController

Unity: How to Create a Cut-Scene with Cinemachine and Unity Recorder

Hi Xander here,

For Endless Elevator we wanted to do an Introduction Scene for the game. The gameplay, as the name suggests, consists of climbing endless elevators and escalators. The player navigates floor after floor in the bad guys luxury hotel and tries to climb as high as possible while defeating the bad guys. It’s a 2.5D top down scroll mechanism and clipped into the limits of the building. Just dumping the player into the start of the game in the levels of the building felt a little weird as there was no context to where you were in the story. Hence the need for an opening shot to set the scene and to literally drop the player into the game.

Our hero flies into the enemies’ oasis headquarters in a helicopter and storms into the foyer of their luxury hotel. We mocked up a scene and a helicopter in Blender and imported the assets into the main foyer scene of the game. I hadn’t used Unity’s Cinemachine before but wanted to try it out. Previously, in other projects, we had captured gameplay for cut-scenes using external software and video editing suites which was OK but the experience with Cinemachine and Unity Recorder was way smoother. It was much easier to work with and much better quality avi files. Plus we didn’t have to do custom scripts for switching cameras and panning. It was so easy it kind of made me excited about movie making with Unity but you know I don’t need another distraction.

To start working with Cinemachine and Unity Recorder you can download them using the Package Manager. Unity Recorder has only recently been added (it’s still also on the Asset Store) so you need to enable the “Preview Packages” selection from the Advanced menu in the Package Manager.

Cinemachine in the Package Manager

Have a look at the Unity Manual and tutorials for more info about Cinemachine and Unity Recorder.

Below is a screen shot of my scene in Unity. You can see the main building in green and the surrounding buildings and water in the bad guys oasis HQ. The helicopter is just visible down where the camera sight lines join and on the left in the Hierarchy you can see my Timeline component and my two vcams (Virtual Cameras).

The Timeline is where all the magic happens and was very easy to set up.

First we did a few animations on the helicopter to fly it in to the building and make the rotor spin. Then we added an animation to move the character from the helicopter into the building (which looks terrible but remember this is a quick mock up)

The Helicopter Animation

We dragged this animation into a new Animation track on the Timeline object (right click and Add Animation Track). Then we created two Virtual Cameras in the scene. One Camera (vCam1) was set using the properties in the Inspector to automatically Loot At and Follow the helicopter. This means that where ever we flew the Helicopter the camera would follow it round from behind at a set distance and keep it in the frame automatically. This was really fun when we had it under manual control for testing and worked well when under the control of the Animator. We used a preset for a bit of camera jitter and shake to mimic a real camera man in a second helicopter.

The second Camera (vCam2) was stationary at the building site but set to Follow (ie. Look At) the Main Character. We timed the cut from one camera to the other so that once the helicopter landed it would pass control to the second camera and seamlessly start focusing on the Player. This was so easy it was ridiculous. The Camera objects were added to the Timeline and the split where we cut from one camera to the next is clearly visible in the screenshot below (two triangles). The first time I ran it and that view cut automatically from one vcam to the other gave me an enormous sense of satisfaction like I’d just been named a modern day Hitchcock.

The Timeline Editor Window

To record what we had done as an AVI we opened the Recorder Window:

Opening the Recorder Window.

We used the default settings and triggered the Start of the Recording with the start of the animation by having it in the Timeline. The Capture target was the Game View (you can also get the other elements of the Editor if you need it). The Output Resolution is interesting as you can use the Size of the Editor Game window on your screen or set it to standard default movie formats.

The Recorder Window

That’s about it. We hit Play in the Editor and the Timeline starts the Recording of the AVI and synchronises the Animations and the Camera movement automatically. Once we are done we are left with a good quality moving image of our game screen that we will use as the cut-scene to drop the player into the start of our game. Obviously what we got here is just a “screen test” but I was really happy with what we could achieve in just a few hours and with so little complexity.

Xander out…

The Coin Flip

Ah the coin flip! Simple easy and fun. The mechanism is a platformer mainstay. You run over a spinning coin (it glitters, it calls you) it pops into the air, and it’s yours!

The Endless Elevator Coin Flip !

This is how we do it…

There is a Rigidbody and Collider on both the coin and the player character. You can clearly see the spinning frame of the coin collider in the .gif above.

The collider acts as a trigger which is being listened for by our script which executes the “pop”.

The coin has a spinning script (and also a magnetic feature as a bonus for later).

The player has a couple of behaviours that handles the trigger and action.

The coin scripts – note the use of the slider to get the spinning speed just right.

Here we have the coin’s Rigidbody and Collider settings:

The Rigidbody isKinematic and the Collider is a Trigger

This is the script we use for spinning:

public class spinCoin : MonoBehaviour {

    [Range(0.0F, 500.0F)]
    public float speed;
	
	// Update is called once per frame
	void Update () {
        transform.Rotate(Vector3.up * speed * Time.deltaTime);
    }
}

Simple and sweet.

This is the function that that handles the collision and the pop into the air! (It’s part of our character behaviours).

    void OnTriggerEnter(Collider otherObj)
    {
        if (otherObj.name == "Coin(Clone)")
        {
            coins++;
            var coin_txt = coins.ToString();
            coinsText.text = "Coins: " + coin_txt;
            Rigidbody riji = otherObj.GetComponentInParent<Rigidbody>();
            riji.useGravity = true;
            riji.isKinematic = false;
            riji.AddForce(Vector3.up * 40f,  ForceMode.Impulse);
            Destroy(otherObj.gameObject, 0.4f);
        }
     }

First of all we are incrementing our coin total variables and screen display.

The mesh for the coin is part of a child component so we need to call the Rigidbody attached to the parent object.

We set gravity to true so that it falls back down after adding the force and set isKinematic to false so we can use it’s mass to fall.

After a very short flight we destroy it (0.4 seconds).

As an added bonus here is the other coin behaviour for when a magnet power up is used in the game.

    private void OnTriggerEnter(Collider col)
    {
        colName = col.gameObject.name;
        float step = speed * Time.deltaTime; // calculate distance to move

        if (colName == "chr_spy2Paintedv2")
        {
            transform.position = Vector3.MoveTowards(transform.position, col.gameObject.transform.position, step);
        }
    }

This is when we make the collider really big on the coin. If the player gets in range of the collider then the coin moves like a magnet towards him. Which is kinda fun when there is lots of coins around and you feel like a millionaire just by standing around.

Demo Text Adventure Game Released on Google Play

Hi Harmony here….

We released the demo game for our Text Adventure framework on the Google Play Store this week.

https://play.google.com/store/apps/details?id=com.ZuluOneZero.AdventureText


The Code for the Project is available on GITHUB:

https://github.com/zuluonezero/AdventureText

Quick Start Instructions for building a 2D Unity project are available on the README.

More detailed information is available in the ZuluOneZero – DevBlog.

See our posts about the development of this game and more information on how to configure the project: 

I hope you enjoy playing with it.

If you have any questions or need support you can email us at zuluonezero.z10@gmail.com.

Harmony out…

Getting a Foot in the Door of Game Design

First of all – sorry about the misleading title – this post is about getting the doors working in the Endless Elevator game that we are currently developing. I thought it was a good pun and that as this post is all about our development process that it wasn’t too bad. The only career advice I got is just to start making games…any games.

You’d think making a door that opens and closes would be a pretty simple thing to do but surprisingly it wasn’t.

I designed and built some 3D models of building components in MagicaVoxel and exported them as .obj files. I use MagicaVoxel because it’s free and really quick and simple to use. When I model components I can be sure that they are all exactly the same scale and that all the different bits (no matter when I made them) are going to fit together without any hassle. But the models are not optimised for game engines as they have a reasonably high poly count due to the modelling process within the program. Most of the models come out with heaps of unnecessary triangles that need to be managed first. In most cases I will import the object into Blender and use the “decimate” modifier on the planes (with an angle of about 20 if you are interested). In the case of the door object it was pretty simple, it is just a door after all, and I didn’t need to optimise it.

Here is what the door looks like in MagicaVoxel:

Notice that the door object is sitting just forward of the enclosing frame and that when exporting the object the center is at the middle bottom plane of that frame. The door is off center because it’s modelled to fit exactly in a doorway that sits exactly in that position within the frame. This saves me a huge amount of time lining everything up when it gets to Unity as the position of the door (or any other object for that matter) is already in the right spot. The problem is that the point of origin for the door is in the wrong spot. It exports a few units behind the door and on the floor! This becomes important when you try and rotate that object (like you would when opening and closing a door) and the pivot point is not where the hinges should be.

To fix this I had to import the .obj file into Blender and reposition the point of origin for the model.

This is what it looks like in Blender when I did this:

To do it I selected the edge that I wanted the door to pivot on when opened.

Then in Edit Mode:
Mesh -> Snap -> Curser to Selected

In Object Mode:
Object -> Transform -> Origin to 3D Curser

So that puts the curser onto the correct position in the middle of that edge where the hinges would be and resets the point of origin (which is where it will pivot when rotated in Unity) to the right spot.

Once we were all imported into Unity and looking good I set up a prefab for the “Doorway” object with the door as a child object. The doorway object has a bunch of colliders to stop the player walking through the walls and a big sphere collider where the door would be to trigger the open / close function when the player walks into it.

This is what the doorway looks like in Unity:

Next I scripted up a few options for opening the door. I’ll post the script at the end of this article but basically there were three options of opening the door that I wanted to test. (Actually I tried it about six ways but whittled it down to the most simple methods – and just as an aside there is an actual “hinge” object type in Unity if you ever need it).

This is how the script looks in the editor:

Notice the slider at the bottom to control how far I want the door to open. It’s really handy to have this when playing in the editor and getting your settings right. If you want to know more about using it see this post

The three tick boxes are for testing the three different ways of opening the door.

Snappy was a quick simple transform of the position from open to closed with no “in betweening”. It looks a bit unnatural as the door magically goes from closed to open but it’s not too bad and most people are pretty used to similar behaviour in video games.

The active line in the code is:
the_door.transform.Rotate(-Vector3.up * 90 * Time.deltaTime);

The next method works more like a door should. In that it swings open and closed the whole way in a steady fashion. But the big problem with this method was that it was OK when the character was going into the doorway and with the swing of the door but when it was time to come back out of the doorway the door was in the way. There was not enough room to trigger the door opening from the other side without being hit by the door as it opened. Plus if the player enters the collider from the wrong trajectory the character gets pushed through a wall by the swinging door which is sub-optimal. I called this method InTheWay!

The active line here is:
the_door.transform.rotation = Quaternion.Euler(targetPositionOpen);

In an effort to combat this I chose to do a hybrid method that opened the door to a point that wouldn’t hit the player and then do the magic transform to get all the way open. I call this one aBitBoth. It looks a little weird too. Like there is an angry fairy pulling the door closed with a snap after the character enters.

Here are all three to compare.

Snappy

In The Way

A Bit of Both

I’m not too sure which one I’m going to use at this stage as the Snappy method works best for now but I like the In The Way method better. I looks more normal and I like that you have to wait just a few milliseconds for the door to swing (adds tension when you are in a hurry to escape a bullet in the back). I could do something like halt the player movement from the rear of the door when it triggers to open from the closed side or maybe play around with the radius of the sphere. Neither solutions seem like great ideas to me right now but something like that will need to be done if I’m going to use that method. Maybe I could just have the door swing both ways and open to the outside when he is behind it but that’s probably a bit weird for a hotel door.

Here is that script that I was testing with:

using UnityEngine;

public class OpenDoor : MonoBehaviour {

    public bool openMe;
    public GameObject the_door;
    public bool snappy;
    public bool inTheWay;
    public bool aBitBoth;
    public Vector3 targetPositionOpen;
    public Vector3 targetPositionClosed;

    [Range(0F, 180F)]
    public float turningOpen;

    void Start ()
    {
        targetPositionClosed = new Vector3(0f, 180f, 0f);
        targetPositionOpen = new Vector3(0f, turningOpen, 0f);
    }

    void Update()
    {

        if (openMe)
        {
            OpenMe();
        }
        else
        {
            CloseMe();
        }

    }

    private void OpenMe()
    {

        if (inTheWay)
        {
            if (the_door.transform.rotation.eulerAngles.y > turningOpen)
            {
                the_door.transform.Rotate(-Vector3.up * 90 * Time.deltaTime);
            }
        }

        if (snappy)
        {
            the_door.transform.rotation = Quaternion.Euler(targetPositionOpen);
        }

        if (aBitBoth)
        {
            if (the_door.transform.rotation.eulerAngles.y > turningOpen)  // 144f
            {
                the_door.transform.Rotate(-Vector3.up * 90 * Time.deltaTime);
            }
            else
            {
                the_door.transform.rotation = Quaternion.Euler(targetPositionOpen);
            }

        }

    }

    private void CloseMe()
    {
        if (inTheWay)
        {
            if (the_door.transform.rotation.eulerAngles.y <= 180)
            {
                the_door.transform.Rotate(Vector3.up * 90 * Time.deltaTime);
            }
        }

        if (snappy)
        {
            the_door.transform.rotation = Quaternion.Euler(targetPositionClosed);
        }

        if (aBitBoth)
        {
            if (the_door.transform.rotation.eulerAngles.y <= turningOpen)  // 144f
            {
                the_door.transform.Rotate(Vector3.up * 90 * Time.deltaTime);
            }
            else
            {
                the_door.transform.rotation = Quaternion.Euler(targetPositionClosed);
            }
        }
    }

        void OnTriggerEnter(Collider col)
    {
        string colName = col.gameObject.name;
        Debug.Log("Triggered OpenDoor!!! : " + colName);

        if (col.gameObject.name == "chr_spy2Paintedv2" || col.gameObject.name == "BadSpy_Package(Clone)") 
        {
            openMe = true;
        }
    }

    void OnTriggerExit(Collider col)
    {
        if (col.gameObject.name == "chr_spy2Paintedv2" || col.gameObject.name == "BadSpy_Package(Clone)") 
        {
            openMe = false;
        }
    }

}

The Dog Run is in Production on the Google Play Store

This week we moved our latest game The Dog Run into Production on the Google Play Store.

The Dog Run is an Endless Runner for Android that supports animal welfare!

It’s a free game. There is the option to watch ads but instead of in game rewards all profits from the advertising goes to support animal welfare and animal hospitals.

The game is about taking your fun lovin’ pooch for a run. But watch out! There is a bunch of obstacles in your path. It’s a good thing your dog is a natural jumper and can run all day in all sorts of weather.

Read the review from Daikon Media here.

They say, “… it’s not only the style, that I like, it’s also the unique sense of humor…the game is even fun and original.”

Feedback can be posted on the Google Play Store,  on this website in the comments,  or directly by email.

ZuluOneZero Game Design
http://www.zuluonezero.net/
zuluonezero.z10@gmail.com

Image File Size in Unity and their Impact on Start Up Time on Android

Xander here…

We have been Beta Testing our soon to be released game The Dog Run and it’s been mostly OK but we had a number of issues with memory on smaller or older devices.  We made some gains with modifying our audio files (See this post) but were still running into niggling crashes on start up and longer than normal load times.

We were getting feedback like:

“Hey, I installed the game and couldn’t run it. When I started it there was a black screen for about 15s and then it went back to the launcher. Then each time I went back to the game there was unity and game logo fading out and again the app crashed/hanged and I was sent back to the launcher.”

(Thanks slomoian and the_blanker for all your help testing)

Obviously feedback like this is a little disheartening and far from ideal.  The game was running fine on every device and emulator I had access to but it’s only when you send something into the wild that you realise the full breadth of the spectrum that is the Android platform.  I guess this is another lesson in the importance of proper Beta testing.  One we hadn’t learned last time we released an app (see this old post on the perils and difficulty of finding Beta Testers).

We were using adb logcat to monitor our start up problems but not finding a “smoking gun” that solved every case. It seemed to be a memory problem and often with the graphics cache so again we went back to the Unity Editor build log to investigate our image files.  The game uses multiple large files to ensure that our animated sprites were always in the right spot. The game is dependent on the titular Dog hitting the ground line accurately on every frame to achieve the look we wanted when he runs and the paw breaks the ground line and appears as a gap.  We used a “flip-book” old fashioned style of animation where each frame sits exactly on top of the old frame and everything lines up on a transparency like in classic animated movies.

By using this schema we had to keep to a certain scale that fit within the constraints of a typical Android device format. This meant that when the images were imported the POT was not going to be something we could play with easily to get performance gains.  (Image files that have a width and breadth that is a power of 2 are faster and easier for the compression functions to work with – so 2, 4, 8, 16, 32, 64, 128, etc).  If I had the chance to do this again this is something I would probably start doing right from the beginning of development. When going through the Editor Logs we did find something interesting (get to the Editor Logs by right clicking on the arrow or tab near the Console and selecting it).

We found that some of our image files were 10 MB and a few were 2 MB.  Which was a little weird as they were all exported as layers from the same Gimp file so I must have done something in the import settings or the editor to change them.

This is a comparison of two files of the same dimensions and basically the same content but with two very different file sizes:

10.6 mb 0.8% Assets/artwork/RunOnSpot6.png

2.0 mb 0.1% Assets/artwork/DogSitHeadWag.png

The difference that I found was MIP Maps.  I’d selected to use MIP Maps fairly early on as it made the art work look smoother in the Editor.  MIP Maps are generated in the engine to make smaller more compressed versions of your artwork that can be used at longer distances from the camera where the detail is less visible. My game is 2D and has everything running at pretty much the same distance from the screen so really MIP Maps should not be required.  My art did look a bit better in the editor with them turned on but on a smaller device like a phone I couldn’t really tell the difference.  See below the difference in a file with MIP Maps selected and a file without.

With MIP Maps turned on (see the file size at the bottom and that the type is RGBA 32 bit):

The same file with MIP Maps removed (down to 2 MB and using ECT2 compression):

This is the difference that generating those MIP Maps makes. Your file is converted from the Android default compression to a larger (harder to process) 32 bit compression format.

So by turning off MIP Maps across the three hundred plus image files in my game reduced my application start up time to under a few seconds and reduced the APK file size by over one thousand MB.

This is the Build Report from the Editor Logs that shows the larger texture sizes and final build size:

Uncompressed usage by category:
Textures 1292.3 mb 94.6%

Complete size 1365.9 mb 100.0%

Compare this later Build Report with MIP Maps turn off to the original one above:

Textures 284.5 mb 82.6%

Complete size 344.6 mb 100.0%

It’s a considerable difference with little or no quality loss on most devices.  When I say most devices there were a few cases where the running dog did look a little tatty.  On very small emulated devices (3.5″ screens and low memory) the images were being scaled down quite a lot and the results were a lot less enjoyable but still an acceptable compromise considering previously the game would not run on these devices at all.

The next thing I started playing with was the different texture compression variables available for Android. I tried all of the settings (see screenshot below) in a different build and tested them against at least ten different devices with various architectures and screen dimensions and Android versions.

In each of the cases but one there was at least one test device that failed to start the game.  Once again exposing the issues of working with so many platform variables on Android.  Even when I built the APK with the (default) ETC selected one device failed the start up test.  So in the end the final build used the “Don’t override” setting which seemed to work on all devices.

Hopefully this is helpful to someone else out there and if it is try hitting the “Like” button below or sharing the link (the feedback keeps me going).

I found these references useful when troubleshooting my start up issues and learning more about compression on Android:

https://docs.unity3d.com/Manual/android-GettingStarted.html

https://docs.unity3d.com/Manual/class-TextureImporterAndroid.html

https://docs.unity3d.com/Manual/class-PlayerSettingsAndroid.html

https://answers.unity.com/questions/1406451/sprites-increase-android-apk-size.html

https://www.unity3dtips.com/unity-texture-compression-android-ios/

Unity Debugging with ADB for Android

Hi Zulu here… (First of all … sorry for the cat)

Let me say straight off that your first port of call for any Unity debugging should be the Unity Console.

Though sometimes you need more low level operating system logging for Android. This is where ADB (in lower case) comes in.

On Windows this is a command line tool to view the logs from a connected Android device.

The command line is not the only way to use the tool sometimes it’s better to use the Android Studio interface (a bit more graphical).

You will need to have your Android device connected to your workstation and USB debugging turned on  (Google that if you need to). You could also use an Android emulator on your desktop.

I use Leapdroid or KoPlayer.  (Leapdroid have now joined Google and no longer support the emulator but it’s still available to download on the internet).  I guess you could also use the emulator that comes with Android Studio.

When your game is installed and running on your device go to the directory in your workstation (PC) where the Android SDK Tools are.

On mine they are here:

C:\Users\<user_name>\AppData\Local\Android\sdk\platform-tools

In the tools directory open the monitor.exe (this tool was depreciated in Android Studio 3.0 and replaced with profiler.exe mine is still on the lower revision).

This documentation on the Android site is a good start investigating the profiler:

https://developer.android.com/studio/profile/android-profiler

You can also get into LogCat directly from Android Studio (if you have it open):

Go to  View | Tool Windows | Android Monitor

At the bottom of Android Monitor in it’s own tab is the LogCat console window. This contains all of the information about what’s happening in the Android operating system.

As you can see the LogCat console contains a lot. It logs everything.

To filter it type “tag:Unity” in the textbox at the top to see messages that relate to Unity.

Using adb logcat from the command line

Open a command prompt on your development workstation and find the location of your Android SDK platform-tools folder.

Mine was here:

/Users/YourUserName/Library/Android/sdk/platform-tools

If you get this error when you run adb.exe using the command prompt:
‘adb’ is not recognized as an internal or external command operable program or batch file

You can add ‘adb’ to the $PATH environment variable (and restart the command prompt).

setx PATH "%PATH%;C:\Users\AppData\Local\Android\sdk\platform-tools"

 

To run logcat through the adb shell, the general usage is:

[adb] logcat [<option>] … [<filter-spec>] ..

This is the official Android Developer Logcat Command-Line Tool documentation:

https://developer.android.com/studio/command-line/logcat

but you can get –help on the command line.

It can be handy to know the device id of your Android phone/tablet whatever. This command will help:


C:\Users\<user_name>>C:\Users\<user_name>\AppData\Local\Android\sdk\platform-tools\adb.exe devices
List of devices attached
ce10171a5c19853003 device

 

You can specify that the log spew into a file instead of into your console (the console is pretty much useless as there is too much to scroll through).


C:\Users\<user_name>\AppData\Local\Android\sdk\platform-tools\adb.exe -d logcat > adb_logcat_out.txt
-d use USB device (error if multiple devices connected)

logcat show device log (logcat --help for more)
-s SERIAL use device with given serial (overrides $ANDROID_SERIAL)

 

The default Log Location on my machine was:
C:\Users\<user_name>\AppData\Local\Temp\adb.log

A few seconds of output got me a 6.5 MB file so a bit of filtering is advisable

If you run into trouble with the adb server just kill it and restart.


C:\Users\<user_name>\AppData\Local\Android\sdk\platform-tools\adb.exe kill-server

C:\Users\<user_name>\AppData\Local\Android\sdk\platform-tools\adb.exe logcat -s ce10171a5c19853003 DEBUG

C:\Users\<user_name>>C:\Users\<user_name>\AppData\Local\Android\sdk\platform-tools\adb.exe logcat -s ce10171a5c19853003 DEBUG
* daemon not running; starting now at tcp:5037
* daemon started successfully
--------- beginning of main
--------- beginning of system

 

If you want further help check out these pages from the Unity Manual and Tutorials:

https://docs.unity3d.com/Manual/TroubleShootingAndroid.html

https://docs.unity3d.com/Manual/LogFiles.html

https://unity3d.com/learn/tutorials/topics/mobile-touch/building-your-unity-game-android-device-testing

As a final word I’ll also direct you to this package called Device Console on the Unity Asset Store. I’ve not used it but it looks really good and for fifteen dollars might save you a lot of hassle.

https://assetstore.unity.com/packages/tools/utilities/device-console-44935

Key Quest! Google Play Store Key Signing and the Pain of a Long Slow Death

Should Google Manage Your Keys for Games built with Unity?

We recently had a problem that caused weeks of pain and struggle and it had nothing to do with coding. It was the damn java keystore signing process that we signed up for on the Google Play Store.

The basics are that the Google Play Store requires that all APKs be digitally signed with a certificate before they can be installed.  Apps must use the same certificate in order for users to be able to install new versions or updates.  This is a good and secure system. No issues here.

If you lose your key you cannot distribute any updates to your app/game. This would be really bad for some companies so Google offers to keep your keys safe so that you if you did lose them you can ask to have the key sent to you which gives you authority distribute again. Yay for Google!

But our problems start here in Unity when you build your game for Android the keystore is defined on the Player Settings tab of the Build Setting (CTRL+SHIFT+B).

In the first case when running your project from Unity the package (APK) is automatically signed with a debug certificate generated by the Android SDK tools. The debug keystore and certificate are in $HOME/.android/debug.keystore.

This debug certificate is insecure by design and can’t be used on the Google Play Store for publishing an Alpha release but you can upload it for Beta releases.  I think this is where we started going wrong.

When you upload an APK to the Play Store you can opt in to app signing by Google Play. They recommend it but it’s optional. If you prefer, you can continue managing your own keys.

The advantages of opting in to the Google Play Store App Signing program is that 1. You ensure that the app signing key is not lost. 2. If your app signing key is compromised only a user with an account linked to your app can manage an upload key which makes it harder to do something malicious. (If you sign in your apps are signed with an upload key proving your credentials – Google then manages your APK and assigns it the correct and valid signing key).

To quote their documentation: “When using Google Play App Signing, you will use two keys: the app signing key and the upload key. Google manages and protects the app signing key for you, and you keep the upload key and use it to sign your apps for upload to the Google Play Store.

When you use Google Play App Signing, if you lose your upload key, or if it is compromised, you can contact Google to revoke your old upload key and generate a new one. Because your app signing key is secured by Google, you can continue to upload new versions of your app as updates to the original app, even if you change upload keys.

If you lose your keystore or think it may be compromised, app signing by Google Play makes it possible to request a reset to your upload key. If you’re not enrolled in app signing by Google Play and lose your keystore, you’ll need to publish a new app with a new package name.”

Alright. Read that last bit again. It’s important and why app signing might be a really good idea. If you manage your key yourself and you lose it and want to make an update to your app then you have to publish your whole app again under a different name. Again just to drum that home … If you lose your keystore, the only solution is to upload a new instance of the app to the Google Play Store with a new key, a whole new store listing like it’s a different product, as it will not accept an APK signed with a different key.

See: https://support.google.com/googleplay/android-developer/answer/7384423?hl=en
(Manage your app signing keys) The support team only accepts key reset requests from the Play Console account owner. The account owner can fill out a form and attach the upload_certificate.pem file. Then you can update your keystores and API provider registration.

It seems easy and if you want to read funny people on the internet slagging off the Byzantine process check out the comments under this tutorial:
https://www.youtube.com/watch?v=qGoCF0Et_CU&feature=youtu.be

I was a little lost so I started looking for the help of my peers and of course from Unity.

I found a post from one poor soul who was in the same boat as me and the response from Unity Support was: “What do you want to be supported from Unity side? I see this unrelated to our build process.” So someone needs to have a little talk to that chap.

There are more than a few forum posts around this for Unity (and that last one is for andromo but the subject is the same issue).
https://answers.unity.com/questions/1434637/can-google-play-app-signing-be-used-with-unity-and.html
https://forum.unity.com/threads/android-signing.62137/
https://answers.unity.com/questions/1372982/how-i-can-sign-my-apk-with-an-google-plays-upload.html
https://stackoverflow.com/questions/50608172/unity-google-play-app-signing-issue-and-keystore
https://forums.andromo.com/discussion/1980/important-do-not-opt-in-to-google-play-app-signing

Look – and this is really the bottom line – it all got too frustrating and annoying trying to work out what the hell was going on and since I was only in my third release cycle I just opened up a new App on the Play Store and ditched the old one.  But that’s just not possible for anyone who has an App out there and has no other option. So this is the process to getting that pesky key back.

In the Google Play Store you can see your App Signing Keys here:

You got your App signing certificate – this is the one that actually signs your app.
SHA-1 certificate fingerprint (above)
SHA1: A8:C0:F2:25:E6:A4:17:A3:F7:13:7B:96:37:FB:B8:59:69:72:9B:8C

And your Upload certificate – this is the one that you use to upload with your APK so that Google knows it’s you.

Your upload key is only registered with Google and is used to authenticate the identity of the app creator.
Your upload key is removed from any uploaded APKs before being sent to users.

SHA-1 certificate fingerprint (above)
SHA1: 74:5A:11:31:6E:2E:C0:DD:8C:F5:6E:65:24:5F:77:B8:2C:EA:6A:9A

In my case the upload certificate was from the default android debug keystore (that I shouldn’t have used):

C:\Program Files\Java\jdk1.8.0_111\bin>keytool.exe -list -keystore C:\Users\<user>\.android\debug.keystore
Enter keystore password:

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

androiddebugkey, 10/08/2016, PrivateKeyEntry,
Certificate fingerprint (SHA1): 74:5A:11:31:6E:2E:C0:DD:8C:F5:6E:65:24:5F:77:B8:2C:EA:6A:9A

 

To generate and register a new upload key, follow the instructions in the Android Studio Help Center.
https://developer.android.com/studio/publish/app-signing#generate-key

You don’t need to use Android Studio you can also do it on the command line (which is easier I think).

First generate a private key using keytool. For example:

# keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias

C:\Program Files\Java\jdk1.8.0_111\bin>keytool -genkey -v -keystore D:\ZuluOneZero\Demo-Unity-Android-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias Demo4Unity
Enter keystore password:
Re-enter new password:

What is your first and last name?
[Zulu]: ZuluOneZero
What is the name of your organizational unit?
[Unknown]: TheDogRun
What is the name of your organization?
[Unknown]: ZuluOneZero
What is the name of your City or Locality?
[Unknown]: Melbourne
What is the name of your State or Province?
[Unknown]: Victoria
What is the two-letter country code for this unit?
[Unknown]: AU
Is CN=ZuluOneZero, OU=TheDogRun, O=ZuluOneZero, L=Melbourne, ST=Victoria, C=AU correct?
[no]: yes

Generating 2,048 bit RSA key pair and self-signed certificate (SHA256withRSA) with a validity of 10,000 days
for: CN=ZuluOneZero, OU=TheDogRun, O=ZuluOneZero, L=Melbourne, ST=Victoria, C=AU
Enter key password for <Demo4Unity>
(RETURN if same as keystore password):
Re-enter new password:
[Storing D:\ZuluOneZero\Demo-Unity-Android-key.jks]

Note: keytool is located in the bin/ directory in your JDK. To locate your JDK from Android Studio, select File > Project Structure, and then click SDK Location and you will see the JDK location
C:\Program Files\Java\jdk1.8.0_111\bin\keytool.exe
(I used this one but you will have a keytool for every JDK and JRE on your machine – doesn’t matter which one you use)

Then, export the certificate for the new key to PEM format:

# keytool -export -rfc -alias <upload> -file <upload_certificate.pem> -keystore <keystore.jks>

C:\Users\<user>\AppData\Local\GitHub\mingw32\bin\openssl.exe x509 -inform der -in C:\Users\<user>\Downloads\deployment_cert.der -out D:\ZuluOneZero\deployment_cert.pem

Add the certificate to the signing keystore:

keytool -export -rfc -alias Demo4Unity -file C:\Users\roderick\Downloads\upload_cert.der -keystore D:\ZuluOneZero\Demo-Unity-Android-key.jks

C:\Program Files\Java\jdk1.8.0_111\bin>keytool -export -rfc -alias Demo4Unity -file C:\Users\roderick\Downloads\upload_cert.der -keystore D:\ZuluOneZero\Demo-Unity-Android-key.jks
Enter keystore password:
Certificate stored in file <C:\Users\roderick\Downloads\upload_cert.der>

If you want to inspect the certificates (on Windows) right click and open with Crypto Shell Extensions.

Or you can inspect the certificates like this:

C:\Program Files\Java\jdk1.8.0_111\bin>keytool.exe -printcert -file C:\Users\<user>\Downloads\upload_cert.der
Owner: CN=ZuluOneZero, OU=TheDogRun, O=ZuluOneZero, L=Melbourne, ST=Victoria, C=AU
Issuer: CN=ZuluOneZero, OU=TheDogRun, O=ZuluOneZero, L=Melbourne, ST=Victoria, C=AU
Serial number: 3e64dcd1
Valid from: Thu Sep 13 16:28:59 AEST 2018 until: Mon Jan 29 17:28:59 AEDT 2046
Certificate fingerprints:
MD5: F8:D3:CF:84:88:8E:16:EA:3D:74:F0:7E:9E:18:13:C9
SHA1: BD:1B:A2:99:05:11:0E:F6:A0:B5:1A:7B:7D:EB:01:3C:8B:A7:98:6D
SHA256: 7C:24:86:CD:58:1A:2F:74:21:B0:A6:9B:3D:DF:BC:BE:2A:15:F3:23:B9:44:7F:98:5D:8D:FB:24:98:37:82:9C
Signature algorithm name: SHA256withRSA
Version: 3

Extensions:

#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 21 44 48 FA 63 97 2D B0 A4 92 2B 38 41 E4 2F 7D !DH.c.-…+8A./.
0010: EA 26 E0 10 .&..
]
]

You can inspect keystores like this:

C:\Program Files\Java\jdk1.8.0_111\bin>keytool.exe -list -keystore D:\ZuluOneZero\Demo-Unity-Android-key.jks
Enter keystore password:

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

demo4unity, 13/09/2018, PrivateKeyEntry,
Certificate fingerprint (SHA1): BD:1B:A2:99:05:11:0E:F6:A0:B5:1A:7B:7D:EB:01:3C:8B:A7:98:6D

 

All the detail above are dummy one’s for demonstration purposes only.

Endless Elevator Mechanics

Howdy. Xander here…

This is a quick demo of the basic play mechanics from our new game in development Endless Elevator.  We got the basic movement working a while ago (see our Smooth Moves post) and now that The Dog Run is in BetaTesting we can spend some more time working on this game.

(If you want to help with Beta Testing and be an early adopter of The Dog Run you can sign up here: https://play.google.com/apps/testing/com.ZuluOneZero.TheDogRun)

This clip below for Endless Elevator shows:

The Good Guy Cop Character movement (oh yeah he goes left and right)

Firing his awesomely powerful dumb dumb gun

Using (the eponymous) Elevator (see if you can spot the camera tracking bug!)

Traversing (the namesake) Escalators

Finally entering a doorway with a Power Cube (I’m not sure what it will look like in the final game yet). When he goes into a doorway with the special block the game flips and he goes into a Super Spy Store (not shown) where new fun weapons and power-ups are available!  Cool.