Phoning It In

I didn't have a plan for this week's post, so I was originally going to write about falling down internet rabbit holes and discovering that S Club 8's music was actually better than S Club 7's the entire time. Plus S Club 8 (much like their older counterpart) had their own TV show which starred Doc Brown from Back to the Future, and there was an American version of S Club 8 called American Juniors where one of the members was Lucy Hale from Pretty Little Liars. Also Gary Oldman's older sister plays Big Mo in EastEnders. That was a separate rabbit hole from the S Club stuff, but it still blew my mind. 

I was going to go in depth on all of that, but you're just getting the main points because it's time to discover the pain in the arse that is deploying to mobile.

One of the advantages of modern game engines is that they work on multiple platforms, often with a single button click. MonoGame requires a little bit of work since it isn't an engine, but it's still supposed to be pretty straight forward.

My general structure for a MonoGame game is to divide the solution up. One project will house the main code of the game, and then there will be additional projects for each other platform which can reference the main project and pass in any platform specific stuff.

Last year I started on a game which could run through Steam, as a native Windows 10 app, and through the Xbox One. All of that was incredibly simple to setup, and two the three problems I ran into, I can firmly blame on myself.

Problem 1 was that I was not using the right ID for the Steam build so none of the Steam integration was working. And it wasn't as simple as I was using the test ID that Steam use for their test project - I had changed the ID, but to something that wasn't the ID that had been assigned in Steamworks. It's a mistake that I ended up repeating earlier this year on Halloween Game.

Problem 2 was that on the Windows 10 app, it didn't like how I had written the save and load code since I was trying to save into a location that Windows had decided was read-only. I was expecting to have to write different code for saving and loading on different platforms, but I hadn't expected the need to rewrite my PC code.

Problem 3 was Visual Studio couldn't find my Xbox. I was running up and down the stairs, jotting down pairing codes to link the two but they weren't able to find each other. About an hour into doing this, I noticed that when my Xbox had switched over into Dev Mode, it had wiped out my network settings. So the reason Visual Studio couldn't find my Xbox was because it wasn't connected to the same network (or any network). This one I blame on Microsoft, because nobody would ever think "Gotta check my network settings are still intact" and would instead think what I thought in that it would remember them.

A couple of weeks ago, I added a couple of extra projects to Story Game - one for Android, and one for iOS. There aren't any templates for creating MonoGame projects inside the latest version of Visual Studio, so it has to be done through the command line. Trying to add these new projects to the solution through the command line resulted in an error because I hadn't installed Xamarin, which the mobile projects need to build.

After installing Xamarin, I still got command line errors but I was able to add the projects to the solution through Visual Studio so I just ignored them.

The Android version had errors everywhere. It said it couldn't find the code in my main project, even though it was literally right there, and it also said it couldn't find any of the XNA code in MonoGame, or even the System code. So I decided to give iOS a go.

Because Apple are Apple, you can't just plug in an iOS device to Windows and deploy the code. You need to pair the Windows device with a Mac, and then have the Mac connected to the iOS device. I had all that setup, and had read that Apple let you test one app for free so went ahead to enroll in their development program. Once I'd taken a picture of my ID, they asked me for some money so I backed away and discovered that testing for free is more convoluted.

Also, Apple now thinks my name is Damel because it combined the 'n' and the 'i' and I didn't correct it since it had scanned the rest of my name correctly so I didn't bother checking my first name.

I created a test app in Xcode on the Mac and made sure that the game and test app were using the same name, then I told Visual Studio to do it's magic. It did quite a lot of magic based on the messages showing in console, but then it errored. And Google did not provide me with a simple answer to the error. So I unloaded both the mobile projects and carried on doing other stuff.

A week later, I'd been working on Card Game and one of the projects did not like one of the other project's dependencies. After discovering the magic words 'PrivateAssets="All"', which fixed that exact problem, I wondered if this was the reason the Android project didn't work. It turns out that it was part of it.

Older Android and iOS MonoGame projects used to depend on a MonoGame.Portable project, but they now don't and use version 3.7 of MonoGame. My main project uses version 3.8 and is also using the desktop version of MonoGame as a base, since the Portable project is no longer a thing. The Android and desktop versions were conflicting, but adding the PrivateAssets tag into the main project made them play along.

After connecting an old Android tablet to my PC, I tried running the build and it failed for exactly the same reason that the iOS build failed - although I didn't clock it at the time. Turns out all I needed to do was go into the Configuration Manager and tick the Deploy checkbox. But then the Android build threw another error - the same one it had thrown when using the command line to try and add the project to the solution.

When creating an Android or iOS MonoGame project through the command line, it assumes that Xamarin is installed in a fixed location and adds a line to the project file to search for CSharp targets from that location. But when Xamarin installed itself on my PC, it decided to live somewhere else. The fix for this simply changing the line and telling it to look in the right place (a more permanent fix would be to jump into the Registry Editor and change an environment variable to point at the correct location, but that's too much effort).

I was now able to get a build onto Android, and watch as it immediately crashed on load. It didn't like my save / load code. No problem, I know how to fix that. Except when I did, it now complained at an even earlier point in the code by throwing a NotImplementedException, which made no sense for two reasons.

First, it had gone past that code last time to tell me that saving and loading didn't work, and I hadn't made any other changes.

Second, I wasn't throwing a NotImplementedException anywhere.

I deleted the build from the device and tried again, and this time it crashed a bit further along. So it turns out that if there was a build already on the device, it doesn't replace it properly and decides to make up errors. But the crash this time was from the input code because it had no idea what a controller was.

With that fixed, the game actually loaded. And then I found out that when one of my tutors had told me many years ago "MouseState also handle touch input", and I believed him because it sounds plausible, he was telling a big lie.

After adding touch screen support to my input manager, my game was now kind of working. There were still changes I needed to do like making options that were only selectable through keyboard or controller become touch friendly, but I was pretty confident in now being able to use MonoGame to port a game to Android.

I decided to revisit the iOS side of things a week later. I changed the CSharp targets, got my Mac and iPhone ready, and hit build. It still did not work. There was a warning that the version of XCode I was using was not supported, but I ignored that because Visual Studio seemed to skip over it to do other stuff, and developers don't read warnings.

Plus XCode told me it was definitely up to date - there was no button to update it in the App Store. And then I saw some text that said the latest version was not supported on my version of MacOS. After an hour of updating MacOS, and an hour of downloading XCode later, XCode decided to do the thing it does where it just hangs on a complete progress bar for a few hours.

I wasn't going to have a nap, but I did. And once I woke up, I washed and dried my clothes before it decided it was done.

Visual Studio still did not like something in the setup, and then I decided to actually read a warning and discovered I needed to do the Configuration Manager->Deploy thing. And then an icon appeared on my phone's home screen, before promptly crashing on load.

In copying some code from the Android project over, I'd somehow managed to declare that iOS builds were for PC and not mobile, so it was getting confused over what a controller was, just like Android had.

The Info.plist file - which is basically a settings file for iOS apps - wasn't opening in Visual Studio so I decided to edit a line in Notepad++ instead. For some reason, Visual Studio decided to wait until after I'd hit Ctrl+S in Notepad++, focused on Visual Studio, clicked the Build button and began building before telling me I'd changed a file externally. Visual Studio then ended up getting stuck during the build, so I forced it to close in Task Manager.

What followed was an hour of trying to get Visual Studio to properly reconnect to my Mac so it would display a list of devices for me to deploy to, and acknowledge that the Info.plist existed. Once everything was finally in sync again, I was able to start the iOS build.

There is a problem where it doesn't seem to register that half the screen exists so it's impossible to progress when you need to go to the right, but other than that it is fine for now.

It's approaching Sundown as I write this, which just so happens to be the name of S Club 8's best song, so that's it for this week.

Popular posts from this blog

Getting Started with the FireRed Decompilation

Tonight Matthew, I'm Going to Make...