Thursday, February 13, 2014

Resources.Load


Resources.Load is an important (and dangerous) way of loading assets in runtime in Unity. The dangerous part is that once a resource is loaded, it will stay loaded until manually clearing it with UnloadAsset (Note: You can also use UnloadUnusedAssets to unload all assets that are currently not used - sort of like activating the garbage collector).

If you'll try loading a Sprite asset using Resources.Load<Sprite>, it will return null. The reason for that inconsistent behavior is the internal naming convention of unity. Unity creates a Sprite asset for each Texture2D which is marked as Sprite in the importer. The name of the sprite created is the same as the original Texture2D. When using Resources.Load, it will try loading the Texture2D and stop there, ignoring the Sprite. You can observe this behavior by trying to use LoadAll and for each file in the directory, print the name and the type - you will get 2 files of each name: one Texture2D and one Sprite.

The easy way to overcome this is to use Resources.LoadAll<Sprite> and put in the full path and not just the directory (the same path you would have used for Resources.Load). The documentation states:
If path refers to a file, only that asset will be returned. Only objects of type T will be returned.
This is correct. You will get an array of Sprites with a length of 1 which contains only the sprite you chose. This sounds like a workaround, and it in fact is. But there's no way around it unless the Unity team decide to either change the sprite naming convention of the engine or change Load<T> to ignore the first file it finds if it's of the wrong type.

Sprite image is property of Philipp Lenssen.

Wednesday, February 12, 2014

Continuous Integration and Unit Tests in Unity


Continuous Integration, and especially Unit Tests have been a subject of major confusion in the Unity community. For our current project, we've managed to set up a Continuous Integration environment with automated Unit Testing. How did we do that? What hurdles did we face? What are the practicalities of doing this? Read on!

The Problems


Limitations


Unit Testing in the Unity environment is limited at its core as most features of a game require user intervention. As there are some solutions, even one by unity, that can work from pipeline for every build but they work from inside Unity itself and require setting up scenes and such. Generally, with a generic Unit Testing environment, you can't test the Unity-specific functionality. But assuming you did good on encapsulation and separation of functionality from the UI, your actual code should be disconnected from the Unity stuff.

Dependencies


The other problem is that you can't really run anything which is found in the UnityEngine namespace, including Debug.Log. Those lines will probably be present in your code and you have to have a way to test them, but this is solvable.


The Solutions


Visual Studio


First of all, we've created a new Test Project in Visual Studio Express (which is free to use!). To this solution we added the project "Assembly-CSharp-vs.csproj" and connected it by dependency (reference) to the main test project. Now we can test our code as it's already referenced to UnityEngine and the actual csproj will be automatically updated when we edit it. We also used the built in testing tools of Visual Studio for simplicity.

Perforce


We've set up a Perforce system on Assembla (This is a bit tricky, i'll write more about it in the next post.) and set up a Jenkins server to monitor the perforce depot (it's like a repository for SVN) and run the tests in our project. You can do it with any combination of Source Control, hosting service (or your own repository) and Continuous Integration server.

Workarounds


This is the interesting part. As this whole setting can't work on its own flawlessly, we had to implement some simple workarounds to keep it running.

Setting Source Control on the build machine


Usually removed from the Source Control environment, this time we had to include the visual studio csproj files in the Source Control system. These files are automatically recreated by unity every time you add or remove a file in the editor. This needs to be passed on to the tester so it updates the project data with the relevant files.

Hiding Unity functionality


If you try running the tests you'll probably receive this nonsensical error:

Test method ############## threw exception: 
System.Security.SecurityException: ECall methods must be packaged into a system module.

This actually mean that you tried running something from UnityEngine in VisualStudio. Usually by following the trace you'll be able to get to the exact method it occurs in. Also, it seems to mostly come from rogue Debug.Log calls (although some of calls seem to originate from PlayerPrefs or WWW).s
One options is to remove them, but this can be hazardous if you want to keep logs at runtime. Our solution had 2 parts to it:

1) Replace Debug.Log with a modified log4net module. The only modification we added was to print Debug.Log whenever you log anything with the log4net module (also Debug.LogWarning and Debug.LogError when applicable). This means we're using log.Debug(string) instead of Debug.Log(string). This also helps us to send the logs somewhere safe or keep them in a file when necessary and not just print them in the editor.

2) Now that all the Debug.Log lines are moved into one file, we can hide them. The ideal solution would be to find a precompiled define statement which will only be compiled in unity (the editor or any other build platform, but not in Visual Studio). So we did just that. We added a #IN_UNITY precompiler header which only unity can read so it's false by default. In order to make Unity know about it we put two files in the Asset folder (the file names and their location is important) and called them smcs.rsp and gmcs.rsp. For more information about what are those files, look here (Ctrl+F for smcs). Then we put this line into both files: 

-define:IN_UNITY

And that's it! Now all those line will work from unity but not from Visual Studio.

Conclusion

The next post will include some information on how to make Jenkins work with Perforce in Assemble and why we couldn't use TeamCity. Hope you can make use of all this information. Please comment on this post if you have any further inquiries!

Sunday, February 9, 2014

Global Game Jam 2014


Global Game Jam is a global event where people gather together to produce games around a certain theme in 48 hours. This year's largest jamming site in the world was in Tel-Aviv, Israel. And I was there.
487 registered jammers gathered in Google offices near Azrieli Towers in center Tel-Aviv, formed teams and began creating amazing innovative games.

Our team (10 very talented people) was composed of 3 programmers, 2 artists, 2 level designers, 1 qa person, 1 composer, 1 producer and a dog.
We created the nice casual game Ego Monsters which can be played as a standalone for Windows, Max and Linux (the Linux version has some problems) and in a webplayer.
Try it out, you might like it.



And for the more technical stuff:
The game was - obviously - created using the Unity engine, using the new 2D architecture and Box2D physics engine. During the process I've discovered 2 bugs in the unity 2D framework (mostly concerning 2dPolygonCollider in conjunction with Rigid Bodies and runtime generation of colliders). I'm really not sure whether those bugs are actual Unity bugs or Box2D bugs but they were confirmed and will be dealt with soon (Thanks for the quick response, Unity team!).

The game was also featured in the official Unity blog with 3 more games out of the 2292 games made with Unity in the GGJ. This was a very pleasant surprise! Be sure to check out all the other cool games created in the game jam and tell me what you think about our game.