I already wrote an article about my favorite bug for this blog. Two days ago, we discovered one that is even more obscure...
A little bit of background: I used to work in the games industry for 6 years before I changed industries (also wrote about this here). Since I miss game development, I regularly meet with a friend of mine - an expert in animation and 3D graphics - to create smaller game projects in Unity.
Our current project is a 3D game that looks and feels like an ego shooter (without the shooting). In the current state, you can move around the map, look around and jump. Also, there is a robot that can detect your location and follows you automatically using Unity's powerful NavMesh feature to ease the wayfinding.
We were very happy with how it turned out when playing it in Unity's "Play Mode". This preview mode that is built into the editor should show you how the final product looks and feels. Unity's Manual even states that the
[...] Editor Play mode [allows you to] see how your published application plays.
So, last time we met, we made some good progress, checked it regularly in "Play Mode" and wanted to call it a day. The last thing we wanted to do is make a real build of the game running on the same PC we used to create it in order to double check how it behaves.
When we started the build, this happened:
In short - it was completely broken.
Two days ago, we met again and wanted to debug this. It would not make sense to continue if the fundamental game and control mechanics were completely broken. Whatever we tried, it always worked fine in "Play Mode" but broke apart in a platform specific build.
We tweaked all the settings. We created a completely new barebones project to narrow down the issue. It was frustrating.
In a nutshell, it took us over six hours to find the cause.
In Unity, there is a very handy feature available called "Virtual axes". These are pre-defined and ready to use in your game. They allow you to use very simple code to control player inputs without having to worry about what device is used.
For example, this code detects horizontal movement automatically. The values can be between -1 (far left) and 1 (far right):
float inputHorizontal = Input.GetAxis("Horizontal");
Here you can see how such an axis is defined in Unity - in this case it is named"Horizontal" and reacts to left and right arrows on the keyboard as well as the traditional a and d keys that are often used in 3D shooting games:
The thing is that Unity can define multiple axis with the same name. There is a second "Horizontal" axis that is detecting joystick actions. So the code above also automatically picks up those movements as well and moves the player acordingly.
The problem was not related to a joystick in our case but a device called Space Mouse Pro that is used by professional 3D designers to move around in x, y and z directions. We suspected this at one point in our trouble shooting and disconnected it from our PC but when the problem with the quick left movement of the player was still there, we dismissed this as the cause.
It turned out that the device driver was the problem. In Unity's "Play Mode", it was ignored since it is more or less running the game sandboxed within the editor context. However, in real Windows builds, this is detected as a joystick that is tilted to the left. Even when it is not connected!
As soon as we renamed the joystick axis from "Horizontal" to "HorizontalJoystick", this fixed both problems immediatelly. This way, when working with the "Horizontal" axis in our code, this fake movement was ignored and we could happily go home.
Never trust preview modes!