Unity2D the Good, the Bad and the Ugly.

Hey guys, after more than one year working with Unity, I thought it was time to give some feedbacks. With Tamsen (aka Gsynuh) we worked on a 3D game which has been canceled unfortunately. Anyway we were really happy to use Unity3D for this project instead of using Away3D (we’re mostly AS3 developers).

Now Tamsen is working full time on A Blind Legend (we will provide you soon a blog report on this exciting project!), built with Unity3D. On my side I will help him on specific tasks, I’ve also several AS3 projects, and one game in progress using Unity2D.

For those of you who don’t know me, I worked on the Citrus Engine and so I’m very familiar with Starling framework (a 2D API). This background precision is important to understand my approach of Unity2D.

The Good
We were really happy of Unity’s Editor (we all know its Unity strength) working on the 3D game, and I really enjoy to use it with Unity2D. If you’ve never worked with Unity2D have a look on this great tutorial. I have long dreamed of something similar for the Citrus Engine but it would require many days of work. So we have some custom cheap editors which do their job really great on big project, but they are missing lots of features. Basically when you make a small 2D game with Starling, you create / display / position everything via code.

One of the key feature of Unity’s Editor is the ability to script Editor to create your own tool inside Unity. I didn’t try it myself, but Tamsen did and he loves it.

With Unity 4.6, there is the new GUI. I started my Unity2D game project with NGUI but dropped it as soon as I tested new Unity’s GUI! They made an excellent job, kudos guys. With Starling, we use Feathers for complex UI which works great but it’s a pain to add/customize, and the api is complex. A big app made with Feathers will be out soon and of course they will be a new blog post. Using Unity new GUI it was really easy to built our custom UI and even a designer could manipulate it thanks to the Editor.

Unity also comes with a really strong Vector math librarie. In AS3 I often used Nape (even if don’t use the physics at all) just for having a strong Vector math library. In Unity2D you can do directly amazing things:

while(Vector2.Distance(transform.pos1, pos2) > .01f)
	transform.pos1 = vector2.MoveTowards(transform.pos1, pos2, speed * Time.delta)

The Bad
Ok, so that was for the good things. Wait, what!? What about Unity2D itself? I think its overkill. Unity2D is base on Unity3D, and we’re still manipulating Vector3 to move our objects.

An other thing is coordinate manipulation. We’re often switching between Camera.main.ScreenToWorldPoint and Camera.main.WorldToScreenPoint. This kind of manipulation is classical in a 3D API but not all in a 2D one. In the following code, I put my stairs sprite in the bottom right corner. This is the crazy code:

SpriteRenderer stairs = GameObject.Find("Level/stairs").GetComponent<SpriteRenderer>();
stairs.transform.position = new Vector3(Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, 0, 0)).x - stairs.bounds.size.x / 2, -Camera.main.ScreenToWorldPoint(new Vector3(0, Screen.height, 0)).y + stairs.bounds.size.y / 2, 0);

It seems that Unity2D has the wind in its sails from the game developer community, but I wonder how they deal with some features. Let’s take a basic one : how to put a blur filter on a SpriteRender? I didn’t find a simple way, even after looking on the Unity Asset Store. My conclusion is that I’ve to write my own material with custom shader for the blur effect. And it would be the same for some other filters ColorMatrixFilter, DisplacementMapFilter… Are you serious, no one is using filter? Why are they not included by default, for a 3500€ framework that’s a shame!?

An other crazy thing is the impossibility to mask / clip 2D SpriteRenderer via Unity2D API. You will have to create your own shaders. This one is working fine (except on Nexus 7 and probably the Ouya due to Tegra 3).

An other thing which highlight the limit of Unity2D API is to work with TextureAtlas/SpriteSheet. Unity2D support them, and they have a great tool named Sprite Packer which is very useful. Note that you may also use TexturePacker. So Unity may combine sprites into a SpriteSheet (with many options), that’s great. However you can’t access to those sprites via code. For accessing the sprite needed you have to define a public property in your code and give the sprite reference via the editor.
Or if you really want to do it via code (and often you will!) you have to put them in the Resources folder and load them at runtime:

public List<Texture2D> spriteSheets; //note that here you make the link via the editor
private List<Sprite> _sprites = new List<Sprite>();
//loading texture in memory
for (int i = 0; i < spriteSheets.Count; ++i)
	_sprites.AddRange(Resources.LoadAll<Sprite>("world_three/symbols" + i).ToList<Sprite>());
//getting a Sprite
static public Sprite GetSprite(List<Sprite> sprites, string name) {
	for (int i = 0; i < sprites.Count; ++i) {
		if (sprites[i].name == name)
			return sprites[i];
	return null;

It isn’t very programmer friendly, isn’t it?

An other strange thing is the layer system: Order in Layer. You will expect that two sprites can’t have the same layer, but they can. So does the last object created will be on top or behind the previous one? It depends. Of what? No idea. Even if you move the object inside the Hierarchy, it doesn’t change anything. Even worse, if you have a Sprite Render’s child the order in layer doesn’t refer to the parents one but to the global one! You can imagine easily the nightmare on complex game… Why on earth each object hasn’t its own index and each children too according to their parents like in any display-list framework!?

The Ugly
There are bad things in Unity2D and there are also ugly things. It’s very common in a 2D game to have a Sprite as a container and push children inside which may have children etc. And you probably want to position this container according to its size. Hard to believe but it isn’t easy to do with Unity2D. 2D Bounds parent doesn’t consider children, you have to make your own function:

static public Bounds GetBounds(Transform parent) {
	Vector3 center = Vector3.zero;
	foreach (Transform child in parent)
		center += child.gameObject.renderer.bounds.center;
	center /= parent.childCount;
	Bounds bounds = new Bounds(center,Vector3.zero);
	foreach (Transform child in parent)
	return bounds;

In a game it’s very common to change Sprites’s alpha. Using Unity2D you must go through the color class unless you did it via the Editor. And you can’t change it directly, you have to change the whole color variable.

Color tmpColor = myObject.GetComponent<SpriteRenderer>().color;
tmpColor.a = 0;
myObject.GetComponent<SpriteRenderer>().color = tmpColor;

I know that many things (transform) work that way in Unity, but for small things like Color I can’t get the reason.

Working with Starling framework we have to manage SpriteSheets loading, maximum textures size (4096 x 4096 for an iPad retina, but 2048 x 2048 for an iPhone4S etc.), multi-resolution management (you won’t load the 4096 x 4096 assets on an iPhone 3GS). When you start with Unity2D you think that everything is automatically managed under the hood… but it isn’t. There is no magick here! In fact how does Unity manage the multi-resolution development? It doesn’t. You have to handle it yourself via your code. At thirst I thought Unity2D was smart enough to override my texture size depending my mobile device but it doesn’t. So how to manage assets between a 3GS and an iPad retina? Provide several resolutions but don’t put them in the Textures directory or both will be loaded. Also if you use the Editor for putting Sprite into stage it won’t handle the good SpriteSheet to use at runtime.
Also I lost 2 hours because I forgot to override a Texture Size to 2048×2048 for my iPhone4S. Unity2D didn’t gave me any error, just a crash on the device. And Xcode just told me: application received memory warning. It’s critical that those points are not clearly detailed in an official Unity blog post.

Please, tell me that I’m wrong on many points and correct me. Using Starling I can handle everything and know what the engine is doing. For a small game, for sure I will stay on Starling. However for a big one, Unity2D is really attractive if you work closely with graphic designer (or game designer adjusting physics in real time!), but for coder the API is hell! Please report your issue to make Unity2D better.

9 thoughts on “Unity2D the Good, the Bad and the Ugly.

  1. Ca fait 1 an et demi que j’utilise Unity sur des projets 2D. De ce que j’ai compris, c’est pas mal pour les codeurs gameplay comme moi mais un peu obscur pour ceux qui peuvent attaquer du code plus en profondeur.
    J’utilise TK2D qui est une super librairie, pratique pour taffer sur des projets conséquents. Niveau shader y’a les sprites dont tu parles (clipped / tiled / sliced) mais ils ne sont en effet pas dans Unity de base . Par contre la librairie d’anim et de gestion des sprites est pas mal cool.
    Contacte moi si tu veux + d’info ou en papoter.


    Unity2d est encore très mal foutu, mais l’interface, le unityeditor et les plugins font que j’ai pas envie d’aller voir ailleurs 🙂

  2. Right on, I am torn between the two platforms, unity because it makes you more employable these days, has a great IDE and has a great community and has massive support but as you say, coming from an as3 background some of the coding practices are just ugly as hell (probably due to them having to retain a link with their traditional 3D tools). the display tree hierarchy is bonkers also. I’m not saying as3 way is the right way nut after many years of using it, unity structure just seems wrong. Unfortunately the employment market for as3 devs is quite small and specialised these days. In London its mostly casino gaming companies. Everyone has gone to unity. Real shame as the starling platform is brilliant. I Just wish Adobe would support it more develop the tools, support the developers extending the platform. I do feel excited when using unity. There is a sense of moving forward. Even with the brilliant work done with the starling engine, this is Something I Just don’t feel as much with starling/air dev. Sometimes I just feel, if Adobe isn’t going to care, why should I… There’s this company called unity waving their hands saying look at us, we have great tools etc, come and see what we have… It’s a shame.. As3 is a beautiful language for 2d development, Adobe need to support it or sell the rights, drop the name ‘Flash’ and start marketing this platform for what it is. I feel the best way to build and deploy 2D apps across multiple devices with a minimum of fuss.

  3. I’m very happy to find someone that thinks pretty the same of me about the Unity3D.

    I’ve tried to make a simple 2D mobile game and I faced a lot of trouble that you mentioned over here. The first all measures are designed in a 3D standard, so you figure what the made about Unity2D is just to adapt sort part of the engine to handle 3D in a 2D scenario.

    The other point that makes my crazy is about to weave and bind all the stuff with the visual editor, so, if you’re a coder you must know about resource folders and others with same kind as well and know to make prefabs and sort of those things.

    Somehow I think Unity is a good platform for developing game because some features are amazing and fits well, however for some simple things, Unity turns a damn evil zombie that won’t stop seeking ya around

  4. Hi Aymeric, a nice write up from you, and i have encountered several of your listed issues personally.

    For me the main challenge moving on with one of my personal 2D games is texture tearing/ fluttering due to what is possibly a floating point issue and/or camera size related.

    it is not uncommon to see lines appearing between textures at runtime, even in games like ‘Retry’ from Rovio – And if they can’t solve it with their big budgets, who can right?

    There are countless posts on the Unity forums with people experiencing it, but no suitable solution for all situations.
    One commonly mentioned solution is to attach a resize script to the camera which does something like this:

    s_baseOrthographicSize = Screen.height / pixelToUnitSize/ 2.0f;
    Camera.main.orthographicSize = s_baseOrthographicSize;

    Which changes the size of the camera at runtime. The result is you get a camera size which is completely inappropriate for your game, with a single 128×128 tile looking enormous.

    As developers using the editor, we should have manual control over the camera and game framing WITHOUT having strange graphical anomalies.

    Have you encountered this, or attempted to make a tile based game? Would be interested if you overcame this without the use of a plugin.

    All the best!

  5. Hey John, I didn’t give a try to tile based game with Unity2D yet. But I already had this issue with a Starling game. And the key was to set an Extrude in Texture Packer. Did you already try this?

    But if had to make a tiled unity game, I’d definitely use 2D Toolkit. They have a built-in Tiled editor, a camera and a way to handle several sprites resolution like we did with Starling.

  6. Reason for the Color working like it does is because Color is not a class, its a struct, and structs are primitives and have no instances.
    I think some of your points are valid, the lack of filters is a shame, loading sprites run time can be cumbersome, although there is a memory management argument to be made there.
    Imho some of the issues you listed become irrelevant once you get a bit more conformable with the platform.

  7. Great blog post and I totally agree.
    I really want to use Unity (for 2d) – Such a rich IDE for developing games.
    But coming from Starling, the options for handling @1x / @2x textures is giving me a hard time :). So simple in Starling, and so hard in Unity.

  8. Well, you could manage it via the Resources folder but doing this you shouldn’t add visual stuff in Unity.
    It’ll be interesting to see how 2D Toolkit manage that.

Leave a Reply

Your email address will not be published. Required fields are marked *