Hi, I'm Henry. In 2012 I quit my job as a programmer at BioWare to spend a year making my own indie games. This blog is about what happened next...

Like Spaceteam? Want to support my work?
Join the Spaceteam Admiral's Club!

The Spaceteam Networking Post

Many people have asked about the networking in Spaceteam, so it’s about time I wrote an official blog post. However, I’m currently rebuilding the entire game including the networking layer in Unity so I’ll write about both the Old System and the New System.

I’m also sharing a link to an early version of the New System, called “CaptainsMess“, as a Unity asset package. It’s not finished yet but Wifi connections work well enough for me to finish the rest of the game.

Please check it out and help me test and improve it!

CaptainsMess on GitHub: https://github.com/hengineer/CaptainsMess


The Old System (Spaceteam versions up to 1.8.x)

I wrote the original game for iOS using Objective-C and the Cocos2d game engine. It was later ported to Android by a company called Apportable. They have a cross-compiling SDK that generates Android apps from Objective-C code so there is no easily-accessible “Android source” to share. Apportable did make some of their Bluetooth code available though, which you can find here: https://github.com/apportable/Bluetooth

On iOS I used Bonjour (also known as ZeroConf) to discover other devices, which works over Wifi and Bluetooth. I wanted to make it as easy as possible to connect (users shouldn’t need to know or care *how* the game is connecting, they just want to play together!)

I learned a lot from the BeamIt! source code and also the “WiTap” sample code from Apple.

On iOS I used the NSNetServices API but I also used a third-party library called HHServices for additional Bluetooth support. I know that Zeroconf is an open protocol so I’m guessing there are probably implementations for Android.

When you choose “Play” the devices all start off as a clients and look for an available server. If they find one they try to connect to it. If they can’t find one within 3 seconds, they start advertising themselves as a server as well. When one of the connections completes successfully (client or server) the other one is cancelled. Eventually everyone gets connected. Sometimes this leads to more than one group (eg. 2 groups of 2, instead of one group of 4), but in practice this is pretty easy to fix by some players leaving and re-joining one at a time,

Once the devices are connected I use another third-party library called CocoaAsyncSocket to send messages and exchange data between phones. Again, I’m sure there are similar libraries for Android.

Other notes:

  • Bluetooth can only support 7 connections at most (I think this is a hardware limitation).
  • iOS and Android cannot connect over Bluetooth, I believe due to system-level restrictions. I’ve personally never encountered a mobile game or app that connects iOS to Android over Bluetooth. If you know a way to do this please let me know!
  • I broadcast a specific ID that represents the type of game being played, eg. “spaceteam_W_M” means that it’s a Wifi game with Massive mode turned on. That way players can only connect with other compatible games.
  • On Android when Bluetooth mode is turned on the server and client modes interfere with each other, so instead of having just the “Play” option I had to add “Host” and “Join” so the players must choose which mode they are using. It doesn’t switch between client and server automatically like on iOS.
  • Some Android devices/OS versions just don’t support DNS multicast over Bluetooth so I disable the Bluetooth option for those devices (the switch just says “Bluetooth not supported”).
  • Some Wifi routers don’t support “multicast protocols” or have “isolation mode” turned on, which lets devices connect to the internet but not to each other (the exact terminology may be different). There’s really nothing I can do about this, other than to suggest that people check their router settings to see if this mode can be changed…
  • On iOS I support devices running iOS 5.1.1 and higher but I’ve recently been having problems connecting iOS 8 to older OS versions so I may have to stop supporting iOS 5 and iOS 6.
  • On Android we support system version 2.3 and higher but on older devices even the Wifi can be unreliable (and I display a message warning about this and encouraging the user to upgrade if possible).

The New System (Spaceteam 2.0+)

I’m trying to replicate this system in Unity using as much out-of-the-box support as I can. My first attempt uses the Unity Networking HLAPI (High-Level API) introduced in Unity 5.1, specifically the NetworkLobbyManager and NetworkDiscovery classes. Unity’s source code for the HLAPI has been a great reference and is available here: https://bitbucket.org/Unity-Technologies/networking

I have my own subclass of NetworkLobbyManager and two NetworkDiscovery objects: one to broadcast and one to search.

When you choose “Play” the discovery server starts broadcasting its information and the discovery client starts searching.

The broadcast data holds information about the server, eg:

(version) : (unique peer id) : (is the server open?) : (number of players)

When this information changes, the server has to be restarted with new broadcast data and is treated as a “new” server, so the clients get another chance to decide whether to join it.

If the client finds an open server with at least 1 other player, it tries to join.

Otherwise, if nothing appropriate is found after 3 seconds, but there are enough solitary broadcasters to create a lobby then a decision is made for one of them to start a new (open) server. It’s important that the candidate is chosen unambiguously or they would split into multiple lobbies with one occupant each.

Currently the server candidate is picked naively using the lowest peer ID but this could easily be changed to favour the “best” device by comparing processor speed or something. Seems like a good idea but I’m not sure if it really matters yet.

Once players are connected to a lobby, the library then manages ready states and a countdown timer before sending a message to start the game.

So far only Wifi is supported but I’m planning to add Bluetooth support by integrating one or more 3rd-party Bluetooth libraries such as:

If you’ve used these libraries before I’d love to hear your experiences with them.

I may have to drop down to the Low-Level Network API in order to integrate them properly.

Some issues I ran into during development:

  • The broadcast data can’t be updated while the discovery server is running, so I have to restart the server every time I want to change the info. There is a bug in the Issue Tracker about this marked as Fixed but it still doesn’t work for me.
  • If I change the length of the broadcast data when I change the information (eg. using the strings “True” and “False”, which are different lengths, instead of 0 and 1) I got some weird buffer corruption. I’m going to investigate further, but just a warning in case you play with that.
  • I’m just using a single scene for Lobby/Game/Offline/Online even though Unity supports different settings for all these states. Depending on which of these values are set, I got behaviour ranging from SyncVars not working to my NetworkDiscovery objects being destroyed. Watch out for these things if you use different scenes.

Anyway here’s the link to the first public version. Feedback and improvements are welcomed and encouraged!

CaptainsMess on GitHub: https://github.com/hengineer/CaptainsMess

Space out!

Henry


Unity Progress

I’m now fully committed to the Spaceteam rebuild.

It’s a big investment in the future of all my games and the sooner it happens the better. I’ve been wasting too much time tracking down obscure bugs which will soon become irrelevant, so I’ve stopped development on the 1.8 branch until the new version (2.0) is ready.

Sorry to everyone currently experiencing crashes, you’ll have to wait a bit longer for a fix. Thanks for your patience!

In the end I decided to go with Unity 5 and I’m really enjoying it so far.

The UI system makes it easy to scale and anchor elements so they work at different screen sizes. This was a pain to get right before and annoying to test, so the new system is a pleasure to use.

The Particle system is powerful enough that I can directly recreate most of the effects I was using. I can now use Animations for some sequences I was previously doing in code.

There are handy built-in features like Serialization and JSON parsing that I get for free.

And I love being able to easily make custom visualizers and editors that work right in the Editor.

Here are some more notes on how I’m using Unity:

Project Setup

  • I’m using C# for the CaptainsMess networking portion and Javascript for the game code. But I’m considering moving everything to C# so I can get full debugger support (I’m assuming you can’t do source-level debugging in Javascript?).
  • I use Sublime Text 3 on the Mac as my script editor, but I’m also looking at Visual Studio Code which has some nice integration features and debugger support. VSCode also works much better with C# than with Javascript.
  • I’m trying to use plugins from the Asset Store as much as I can. These are the ones that have sparked my interest so far:
    • I2 Localization. I have 12 languages to support!
    • xARM. Useful for testing multiple screen resolutions on different devices (iPhone 4, iPhone 6, iPad, Android tablet, etc)
    • Google Sheets for Unity (GSFU). Handy for getting simple data tables into the game, like level progression.
    • TexturePacker Importer. I already use TexturePacker to make sprite atlases for the Cocos2d version so I assume it will help here as well, although Unity has some built-in sprite packing so maybe I won’t need it.
    • Editor Console Pro. Search, filters, and colours for the debug console.
    • VSCode. Integration for the VSCode editor.
    • PlayMaker. I had heard good things about this tool so I wanted to check it out. I like being able to create state diagrams that not only provide a high-level view of the game logic but are also functional. I still haven’t decided whether I’ll use it in production.

#

Networking

  • At first I looked at the Photon framework but it turned out not to be a good fit for Spaceteam. Most of their services are online rather than local and if I want to use their Redistributable Server license it seems I’d have to pay for every 500 users, which is totally untenable for my needs.
  • My current plan is to just use the built-in Unity Networking. I don’t have to pay for it and it covers most of what I need already, so the CaptainsMess library may end up being a relatively thin wrapper around it.
  • The main classes I’m using are part of the High-Level API: NetworkManager and NetworkDiscovery
    • The NetworkManager class can start a server or client but has no discovery
    • The NetworkDiscovery class can broadcast and listen for other devices but has no server/client code
  • For the initial connection I’m also using NetworkLobbyManager and NetworkLobbyPlayer
    • These classes already track “slot” (ie. player index) and “ready” state so I don’t have to
  • The main thing I’ll have to add is the ability to search for games as a server and client at the same time. The current system only supports one NetworkManager object so I’ll have to work around this with some lower-level code.
  • This networking system seems to be quite new and I’ve encountered a few weird bugs and idiosyncrasies but they’re pretty minor so far.
  • Luckily, Unity has made the source code available which makes it much easier to debug and modify: https://bitbucket.org/Unity-Technologies/networking

General Tips

  • Remember to set “Playmode Tint” in Editor prefs so you don’t lose changes you make in Play Mode!
  • Don’t name Prefabs the same as Instances!
  • If you’re doing things with a networked Player object remember to check isLocalPlayer to avoid redundancy and confusion.
  • Changing a child object name after animating its properties breaks the connection and marks it “Missing”.
  • Reference for mixing C# and Javascript:

    http://docs.unity3d.com/412/Documentation/ScriptReference/index.Script_compilation_28Advanced29.html

  • Extend data classes from System.Object if you want them to be inspectable in the Editor (add [Serializable] in C#)
  • You can’t define generics in JS, but you can use them (with dot before brackets: List. instead of List)
  • Use builtin array[] in Javascript instead of Array if you want to see the items in an inspector.

I know that a bunch of you already know Unity so maybe you can help me answer some questions that I have.

My Questions

  1. Can I rearrange folders in Assets or should all extensions/plugins live at the root level? I’d like to put packages I download from the Asset Store into a subfolder but whenever I update something it wants to import it at the root level.
  2. Any tips for using the Animation Controller system as a regular state machine with transitions triggered in code? (eg. for abstract game states like Lobby, Setup, Intermission, Playing, etc). And if I do this should I be using “Trigger” parameters or just go directly to the state with Play(“StateName”)?
  3. If I have a bunch of unique objects (eg. UI screens like Title Screen, Credits Screen, etc.) should they all exist in the scene and get Activated/Deactivated as needed? Or should they only exist as prefabs and get Spawned when needed?
  4. How do you ‘diff’ scene files in source control (I use Git) to find out what changed? I’ve found some methods for saving them as text and plugins that claim to solve the problem but it seems like it could be error-prone. What do you recommend?
  5. Is there an advantage to separating things into Scene files if your game has very little content like mine? Will it be ok to have everything in one scene?

I’m officially on holiday now but I’m looking forward to continuing the project when I get back.

Thanks for listening and Happy Holidays!


Quandary

I’m reaching the point where my “technical debt” is finally catching up with me. The Spaceteam codebase is now 3 years old, using an out-of-date customized version of cocos2d for iOS (notably not cocos2d-x). I’m stuck with this code primarily so I can get the Android version for “free”. My Android build is reliant on the Apportable SDK, which I can still use and still works ok, but I can no longer update it or request new features. And it is difficult to debug.

But I’m trying to move on from Spaceteam, so why does this matter?

Well I still want to support the current players, and I’m starting to get Android bugs that are much harder (and in some cases, potentially impossible) for me to fix on my own. Some of them are just annoying but some are hard crashes, preventing the game from starting. Even if I can fix these bugs they end up taking a lot of time to diagnose and test. I can’t really get help from experienced Android programmers because there is no Android code to work with.

If my Android “solution” no longer works then this not only impacts Spaceteam and its various incarnations (Spaceteam ESL, Spaceteam Kids, etc.), but also my new projects like Blabyrinth that are based on the Spaceteam code. If I can’t easily get Blabyrinth to run on Android then I have no reason to stick with my ancient, cobbled-together, spaghetti Frankenstein code.

So I’m seriously considering rebuilding Spaceteam with new technology. It will take some intense work (at least a month) and if I do it right then nobody will notice that the game has changed. There won’t be any new features. Except that everything will work better. It’s a big investment in the future. Here are the advantages:

  • Lots of major bugs will no longer exist (…with a few minor ones to replace them)
  • The game will be much easier to maintain and extend
  • I’ll have control over the Android version
  • Lots of community support, both locally (friends in my co-working space and Montreal in general) and online
  • Much easier to find and hire development help if I need it
  • Opportunity to use better networking libraries
  • Possibility of a Windows Phone version!
  • I’ll feel a lot more comfortable and proud sharing the project source code with people 😃

If I can make it work then it will be a much happier note on which to end the main Spaceteam saga and finally move on to other things. So I’ve been investigating this over the past week.

The obvious engine choices are:

**

**

cocos2d-x: The cross-platform variant of the engine I’m currently using. This would be the most straightforward port because it’s very similar and supports almost all the same features. It’s tailored for 2D games, which is good for Spaceteam and Blabyrinth.

Unity: Unity has even more community support than cocos. I love Unity and I want to use it for future games, so getting more experience now is another bonus. They have recently improved their 2D, UI, and networking components, all of which are critical for my games. And they have high-quality reusable components available in their Asset Store.

I’ve experimented with both and so far I’m leaning towards Unity.

A Finer Mess

The other project that would be affected (positively) by this change is CaptainsMess, the much-delayed local multiplayer networking library that I want to make freely available.

The delays were due to higher priorities but also to the fact that in its current state it is iOS-only and still has connection issues so I wasn’t confident releasing it at this level of incompleteness.

But if I rebuild Spaceteam then I also have to rebuild the networking and make it work cross-platform, possibly as a Unity plugin, which I think will be much more useful to people.

Whatever form it takes, it will be the version that Spaceteam actually uses and so I would continue to support it. If I go ahead with the rebuild then the old version (if I released it) would be dead on arrival.

Anyway, I’m as frustrated by the delays to Blabyrinth as you are and very eager to work on it again, but I just wanted to explain and justify what I’ve been struggling with lately.

Space out!