divillysausages.com

Performance tips for Unity 2d mobile

Update 09/2018: As this is one of my more popular posts, I've updated it with even more tips that I've learned in the meantime. At the time of writing the update, we're using Unity 2018.2.

At the minute I'm looking into performance with our latest game, so I figured I'd gather together all the different tips that I ended up using to get our game running back up at 60fps.

You see, it used to run at 60fps no problem, but as development continued and the Unity versions piled up, occasional hiccups became more and more obvious, so it was time to dig down and figure out what was going on behind the scenes. We're currently Android only (as it's a ton quicker to iterate and get everything working as it should), but The latest Unity version (5.3 as of - original - writing) seemed to exacerbate the performance problems on this.

Our game

There's no one silver bullet to optimisation, and what works for one person mightn't work for another, so with this in mind, this is our game constitutes of:

It goes without saying that the performance issues were found using the profiler, so if you have it, it's something you should be using.

Also, these tips are mainly focused on 2D. Your mileage may vary.

The dumb stuff

Let's get the dumb stuff out of the way first. These are the simple things you need to do, and don't need much discussion.

After that comes all the things that require a bit more effort on your part.

Let's go a bit deeper.

Control the garbage collector

One of the worst things that can happen in the middle of playing is the GC kicking in. You'll usually notice if it looks like your rendering is skipping every so often.

Now the important thing to remember is that the GC only kicks in when the application requests more memory. The default behaviour is to try and free some up before asking for more from the OS. This means that if you instantiate everything you need up front, and you have no other memory allocations during play, you'll never have a problem with the GC.

If you're using object pools, easy, right?

The killer is the hidden allocations. These can be big or small, but they build up until eventually your application requests another memory page, resulting in the GC crapping all over your game.

Now you might see something like a few hundred bytes every frame, and think, "No big deal". At 60fps, 100 bytes becomes ~6KB a second, ~350KB a minute. It all adds up.

In the CPU Usage of the profiler, you can sort by GC Alloc column to find out who's allocating and when. Removing as many of these allocations as possible means your game will have a smoother ride. Some will be outside of your control (such as physics engine allocations), but we can live with those.

In the Memory Area of the profiler, you can also take a snapshot of the current memory state, which you can use to help you see if there's a memory leak somewhere.

You can also call the GC yourself, using System.GC.Collect(). Do this when you can afford to. We do it, for example, at the end of a shot, when the ball has finished moving, but before the next player has taken their turn. We allow a collection here, which lowers the chance of it happening where it would be visible (such as when balls are moving).

It's possible to turn off Unity's GC, but it's undocumented and doesn't work on iOS, so I wouldn't recommend it. You also run the risk of having your app crash because of an out-of-memory error.

Logging

In relation to one of the previous points, you'll need to remove any calls to Debug.Log() etc that you have. This is because:

"No problem", you say, "I have my own log function that wraps Debug.Log(), so I only need to set a compilation constant inside there to early return out and not print anything!"

Sure, that'll solve the call itself, but a call to an empty function will still allocate the memory for the string message passed, giving you eventual garbage collection problems.

In the end, you have two three four solutions (James and Max from the comments showed a pretty neat way of removing Debug.Log() calls):

We originally went with the second option as it's easier in terms of dev (as I didn't know about the third one, but we now use that one as it's amazing), and you only need to run it just before a build, then Git revert the changes. On a Mac, you can make a shell script that goes something like this:

grep -rl --null "Debug.Log" "./Assets/Scripts" | xargs -0 sed -i "" 's|Debug.Log|//Debug.Log|g'

which uses grep to list all the files containing Debug.Log() calls, and pipes the result to sed which comments them out, in place.

There are a few things to bear in mind however:

NOTE: That whole previous section is great, and I was reasonably pleased with myself when I finally got it working, but just use the third or fourth option :P

Remove Global Illumination

This was one of the more recent additions to Unity, and it seems to be turned on by default. As we're not doing anything relating to lighting, you can turn them all off (Precomputed Realtime GI, Based GI, Fog, everything). You can find the option in the Windows > Lighting panel. You'll need to do it for each of your scenes.

Depending on your Unity version, you might still see some spikes of GI in the profiler. This is apparently a known bug and is already fixed in an upcoming alpha.

Force OpenGLES 2.0

Unity is optimised for OpenGLES 2.0, but will allow you to select 3.0. It's also set by default and kind of hidden in Player Settings > Other Settings, where you need to untick Automatic Graphics API and remove OpenGLES3 from the list.

It'll be selected if your phone supports it, but your performance will tank, so it's better to force 2.0. This one will obviously improve with time though.

To be transparent, we no longer specifically state OpenGLES 2.0. As far as I can tell, any issues have since been fixed.

Set your colour/depth buffer

Make sure you're using the right sized colour/depth buffer. You shouldn't use the 32bit colour buffer unless you notice banding in your gradients. As our app is pretty much gradient free, it was an easy switch to gain a lot in memory. Ditto for the depth buffer. 2D games shouldn't need much in the way of a depth buffer, so you can bring it right down. You can find these in Player Settings > Resolution and Presentation.

NOTE: Unity 5 seems to have done away with the ability to set your depth buffer. While it seems like the default is 16-bit (though I haven't found any confirmation of that so don't quote me on it), you can now only opt to disable it (and the Stencil buffer) altogether. You can also get a small bit more control using the DepthTextureMode property of the camera.

Set your quality settings

A few simple tweaks here can go a long way:

The two big ones are texture quality and anti aliasing. Texture quality directly impacts your memory and how long it takes to upload images to the GPU, while anti aliasing is applied to the entire screen, so on higher resolution devices it's going to be more expensive. The less passes for that, the better.

Canvas and the EventSystem

We're using the new UI (and you should be as well), and every UI element needs a Canvas parent. By default, one is created when you add a new UI element, and by default, each Canvas adds it's own Graphics Raycaster so that you can hittest against it. More than one of these however, and you can expect your performance to tank, so remove any that you don't need. If you have the profiler, you'll see this come up as EventSystem.

This doesn't seem to be much of an issue any more, however throwing all of your UI elements onto one Canvas does. It all comes down to redraw, and dirty blocks.

When a UI element moves or is changed, it's marked as dirty, in order to be redrawn. A dirty element will also force its parent to rebuild its geometry, and so on up the line. So basically, if you have one moving element (e.g. a timer, or a health bar), you can end up redrawing the entire Canvas.

If you have a Sub-canvas, or a Canvas nested inside another Canvas, this will isolate their children from their parent. You can alternatively have multiple canvases.

Generally speaking, you want all your static UI in one Canvas and all your dynamic stuff in another (or more, depending on refresh rates).

The Unity fundamentals on UI do an excellent job going in-depth with all of this.

Speaking of UI, unless you specifically want to click on an element, make sure to untoggle raycastTarget, otherwise that object'll be included for interaction. On UI heavy scenes, this can easily add up (we gained 10ms on our shop scene). If you're coming from flash, this is the equivalent of mouseEnabled.

I've also read that you can get a performance hit from not having a material on UI elements. I didn't particularly notice any difference, but there are some default UI materials included, so you can add them if you want.

Use the right shaders

Speaking of materials, make sure you're using the right shader on your materials. The default Sprite-Default for 2D sprites handles transparency, which is not ideal. Transparency on mobile is a real buzz kill, especially if you have it on large areas of the screen. On the profiler you'll see this come up as something like renderForwardTransparent(). As we're using tiles, changing the default for a lot of them to a basic unlit brought the rendering time down significantly.

This will obviously only work for solid sprites (i.e. square), and the fact of having a different material will split up Dynamic Batching, but the gains are worth it.

Watch out for Unity UI Text

Unity UI Text is pretty powerful, but it's not the fastest, and you need to be very careful how you use it. We have a lot of text on the screen, with different effects such as outline, and it was hitting performance bad. We've recently made the switch to the Text Mesh Pro asset, and aside from the first frame where it's generating the texture, it's takes about half the time to render. This was a huge gain on some scenes. It's not a drop-in replacement though; you'll need to go through and replace your textfields one by one, but it's definitely worth it.

If you want to stick with Unity Text anyway, then make sure:

Update: Unity have announced that TextMeshPro will become an official part of Unity!

Update: TextMeshPro is now built into Unity directly, and you can access it through the Unity Package Manager. If you already have it in your project (i.e. you bought the asset), then follow this guide on how to update your project. Fair warning, you lose easy access to the code, which is useful if you need to modify it (see the WebGL section below).

Watch out for overdraw

Overdraw is where the same pixel on the screen is hit multiple times. Aside from being redundant, when you combine it with transparent areas of sprites (and multiples thereof), it'll soon start to hurt. In an ideal world, you'd write to each pixel once, but this can be hard, especially with UI. In the Scene view, there's a dropdown that will show you the overdraw for the current scene, so you know where to apply your efforts.

Unity has a polygon mode which will replace your square sprites with much tighter outlines. You have more verticies and polygons, but less overdraw, so it can be a big help. If you're using TexturePacker (and you should be), then this is already built in for you.

Another thing to keep in mind is draw ordering. Normally, we'd be used to drawing a large background covering the screen, then drawing other elements over it. On mobile, it can be better to draw your front elements first, then make use of the depth buffer when drawing the background. A depth check is much quicker than overwriting a pixel.

Draw calls, Dynamic Batching, etc

By default Dynamic Batching should be activated (if not, you can find it in Player Settings > Other Settings). Basically it gathers up all sprites using the same material and renders them all in one draw call. There are a number of things that break batching, such as differing scales, tints, textures etc, so you might need to reorganise how you draw your elements, or combine textures into a spritesheet. A Text UI element will probably not be rendered with UI sprites, and for one example that we had, simply moving it from behind one Sprite to in front of it brought our draw calls from 3 to 7. Changing the Pos Z of the element will also probably break it.

Each draw call you have means a context switch for the GPU, which is expensive on mobile. I'd say any more than 10 is probably too many, and more than 20 will give you problems. Basically get it as low as you can, either through batching or combining your models/textures.

Static batching gives a better performance boost, but it means that you can't move, scale, or rotate anything that it's applied to. Unfortunately it also doesn't seem to work yet with SpriteRenderers, so it's only for meshes at the minute.

If you use the Frame Debugger to analyse your frames, most of the time it'll give you the reason why a batch change occurred.

Set up your audio properly

An easy thing to overlook is your AudioClip settings.

Making a few simple changes brought our app time-to-Home-screen down from around 30s to under 15s, as well as freeing up a lot of memory.

Enable Multithreaded rendering

This point is Android only (it's always enabled if you're using Metal on iOS), but in Player Settings > Other Settings you'll see a toggle for Multithreaded Rendering. This puts all rendering on another thread, freeing up your main thread for application logic, obviously a good thing.

It comes with it's own caveat though, as depending on what you're going with your project, especially if you interacting with textures, it can give graphic glitches. The only thing to do is try it for your project and see if you get away with it. It might also not work on some devices, though I'm not sure if Unity turns if off automatically or not.

If you see problems with it on certain devices, I almost say just disable that device, as the benefits are pretty awesome.

Scrolling

Doing any scrolling in your game menus? The new Unity UI has a scroll component built in, but its performance can be horrible. Solution: scroll the camera itself - if necessary create a new camera with the right necessary rect. Moving a camera is a simple matrix change, so the rendering is the same, while moving via a ScrollRect seems to modify all the RectTransforms all the way down, meaning everything has to be recalculated, and if you've half-way complicated UI, this can be a huge drain. Scrolling the camera alone can easily make it twice as quick. You might need to jump through hoops to get mouse coordinates working properly, but a bit of extra code to get rid of janky scrolling is doable.

Update 08/2016: TFG Studios got in touch through the comments to show off their optimised ScrollView. It looks pretty nice, but you can check it out yourself on YouTube

Know when to break from Unity

When you first come into Unity, everything is component-this and component-that, but sometimes you need to know when to break from Unity and do things a simpler, more direct way. As an example, when we first started making the map for the games, we did a naive approach where we use tiles and each tile has a component that helped with its behaviour; one for the tile properties (drag, etc), one for the physics, one for special considerations (e.g. flashing, or affecting the ball).

This works for quick projects, but pretty soon you realise that you've about 10k objects in the game, and most of them are useless. The properties were split off into static variables, the physics were removed and a collision/trigger mesh generated by our level tool instead (so one PolygonCollider2D instead of one for each tile that needs it), and any special cases were merged where possible, so we'd have one loop rather than 50 Update() methods running.

For the rendering, we also made use of a RenderTexture and Camera culling masks, so all those tiles would get rendered exactly once to the texture, then hidden. For some tiles we couldn't do this (e.g for the ones that break or flash), but for the vast majority we could, which meant that our map and border tiles are one simple mesh. And because the semi-transparent tiles are baked into the texture, we can apply one super fast non-transparent material to the mesh to get the quickest rendering possible.

Use threads where you need to

Because our game is multiplayer, we use sockets via TcpClient to send and receive messages. Originally we were doing a synchronous write and an async read. As the EndRead() method is on another thread, there was no problem when deserialising/decompressing the received message. But that left the problem of sending. Normally it wouldn't be too bad, but sometimes you would get a message being sent out while the ball is moving, and compressing/serialising to JSON are pretty slow operations, so you're looking at minimum 1 dropped frame. Even sending the shoot message as you fired would introduce a tiny bit of lag on the client, which meant the experience wasn't great.

A simple threading system is now in place which means that all that is pushed off the main thread, so there shouldn't be any impact because of it. Some of the logic in the game had to be rewritten to accomodate that - because the writes were synchronous before, we could reuse objects, which we can't do with async - but the performance gains are worth it. Joseph Albahari has a great resource on threading in C#.

WebGL

If you're building your game for web, there are a few things to keep in mind:

As memory is such a big issue, and even an empty project results in a pretty hefty download and an unskippable delay at the start while million-odd lines of JS are compiled, it's super important that you work on getting your project as slim as possible. To that end:

A somewhat broken, but useful tool to use is http://files.unity3d.com/build-report/, which you can use to see which libs are actually going into your build. It'll tell you if a lib is being added because of another library (e.g. Particles might require Wind), or scripts (though not which script).

We found out that we had the 5MB 3D Physics lib being added, even though we're a 2D game. Why, you ask?

Well, aside from UnityPurchasing for some reason (but UnityPurchasing doesn't work on the web, so we could just delete it), it was being brought in by TextMeshPro, which has a feature to let you make physics-enabled text in 3D, and thus had Collider references.

As mentioned above, because we had the code for TextMeshPro, we could go in and comment out the offending classes, but if you're using the Unity built-in TextMeshPro, you'll have to wait until (or if) they do it.

Check out the Lightweight render pipeline

This is a new addition but it's pretty awesome. Basically, Unity have opened up their rendering, allowing devs to make their own custom pipeline.

Honestly, looking at the code necessary to set it up gave me the shivers, but happily, Unity provide a Lightweight Pipeline and a HD Pipeline.

It's very easy to drop in and setup - if you're using the Unity shaders, you don't need to make any changes - and it simplifies rendering enough to give you a noticeable boost.

Check out the new ECS system

Another new one, and one we've not done yet. The new Entity Component System is definitely on the list for the next game though. Combined with the Job system, it's specifically built to take advantage of multithreaded systems, and lets you write high-performance code straight up.

Entities are reduced to mere ints. Components are nothing more than containers for data. The real meat comes with the Systems. They're made to treat lists of components all at once, and just bang it out.

If you've ever used something like Ash in AS3, you'll be right at home. One of the great advantages of this setup is that it becomes much easier to debug your code. You work on insular Systems, and only need to keep the code relative to that System in your head. You can modify freely without impacting the other Systems. It's a different way of thinking about things, but once you get into the swing of it, it's great.

Resources

While going through all of this over a number of different weeks and months, I started saving a list of useful links. In no particular order:

Conclusion

Optimisation is a pretty big subject, especially when so much of it is guesswork or slowed by the constant change > build > test cycle, which on mobile isn't quick. I also find the profiler on Unity not as good compared to others, such as Scout. Your history extends as far as the window, you can't select multiple frames to get averages (even though they have this information), and you can't save the results (update: you can now), so before and after comparisons either work through your memory, or screenshots.

Still, it's what we have to work with, so if you have it, use it, as sometimes, what's causing your slowdown isn't what you think it is. You don't need to profile all the time, premature optimisation being the devil and all, but you should do it regularly.

If there's anything I've missed, let me know! Happy hunting.

Comments

Jim

Very Nice article. Was not aware about the graphic raycaster on canvas. Will download and rate ;) your game for your precious avise

Vincent

Thanks for the tips, it helps alot!

Rodrigo

thanks it help me

bzor

much appreciated!

kweiko

That's really awesome tips, thanks for sharing!

James

There is a third option for logging. Create a method that takes a format string and arguments, like so:

[Conditional("LOGGING_DEBUG")]
public static void LogF(string format, params object[] arguments)
{
	UnityEngine.Debug.Log(string.Format(format, arguments));
}

That way if the method is removed from the final build, you won't incur the string concatenation costs.

Damian Connolly

Great tip James, I didn't know about that one! It's much handier than the way I'm currently doing it :D

Bogdan Rybak

Thank you James, I was searching for this tips for about a year! I Wish you success in all your projects!)

Andrey Sirota

UNITY UI TEXT section was very helpful for me!

I had "best fit" option with bad range - 0-300 and so on.
THX.

Jaysama

Very useful! Thanks! I think u forgot to mention font files, dynamic font was the killer in my previous game, especially if the text keeps changing (like incrementing score).

Damian Connolly

Thanks Jaysama, I've added a note!

TonyCoder

Cool article, it helps me alot

Andrey Sirota

Hi, Damian!

What about particles on mobile?
What about cool assets for profiling and detect problems on mobile?

Please add this sections

Regards

Damian Connolly

Hi Andrey!
We're currently using the Cartoon FX package for our particles, but I haven't had enough experience with particle systems on Unity to say that it's the best one.

For profiling, you can't go much better than the Unity profiler (though it needs an update for history length, multiple-frame select, and the ability to save profiles). It works on mobile, so you'll be able to get the info you need.

Javier

Thanks a lot for this post, sharing right now. Thanks, great job!!

TFG Studios

This scroll view is fine for basic things, but for large data sets maybe you'll want to optimize a little. check this https://www.youtube.com/watch?v=FOQV8AA50Rw

TS

Thanks! These tips will come in handy with my 2D game! Wish I had seen this before.

David

Hi, thanks for a great article!

For the Colour/Depth Buffer settings, you say they can be found at Player Settings > Resolution and Presentation. I don't see these option in Unity 5.4. Have they been moved to another location?

Thanks!

Damian Connolly

Hi David
The display buffer setting is still there: Player Settings > Resolution & Presentation > Use 32-bit Display Buffer.

As for the depth buffer, it seems like they've replaced the option of having a 16-bit depth buffer with just being able to completely disable it. Not an ideal solution, but the option can be found in Player Settings > Resolution & Presentation > Disable Depth and Stencil. You can get a little bit more control by using the DepthTextureMode of the camera.

Slake_it

Thanks a lot, the best optimization article I've read so far

Benjamin

Thanks a lot for this post!! The tips were really useful.

Amit

This is really good :) Can you share some tips for 3D too? I am doing a project on augmented reality where I had to insert about 30 3-d models in 1 scene, I found that upon build on android phone, the app takes about 40 seconds to load and start the camera.

Damian Connolly

Hi Amit
Most of my experience with Unity is 2D, so I wouldn't be able to give you definitive tips. Most of the same would apply though; watch your draw calls, share materials where you can, and use the profiler to know where your problem areas are.

Prashanth

Best optimization techniques captured in one place on Unity 3d.
Big thanks to Damian for sharing this inputs.Helped us lot to optimize our 2D app.
Wish there was buttons for donation (y).

Chris

Wow, thank you! That's by far, the best article I've ever seen on mobile optimization!

Question: Does it cause a problem to scale in the images transform? If not, do you need to match it to the canvas scaler... and do you have recommendations on best settings for the canvas scaler?

Thanks! Chris

Damian Connolly

Hi Chris
Thank you! To answer your question: in a general sense, scaling itself won't cause any particular issues. Obviously, unless your scale is (1,1,1), you're going to be doing it, but it's generally a matrix step and pretty quick. Where it can potentially cause a problem is the how you deal with any particular artifacts that arrive as a result.

Unless you're scaling is perfect (e.g. 1x, 2x, 4x), Unity is going to have to interpolate the pixels to get the final image. This can result in jagged edges or ugly artifacts. These can be combatted using (one or more of) mip-maps, filter mode (point, bilinear, trilinear), or anti-aliasing. Each one has its own performance impact, some more than others (e.g. if you can, don't use anti-aliasing). Most of the time however, it's not really a problem.

For the CanvasScaler, we use a screen space Canvas, with UI Scale Mode on the CanvasScaler set to Scale With Screen Size and a Reference Resolution set to the iPhone 5 screen size, which is our base model on which we model all our UI. I don't think there's particularly one "right" answer, it's all down to the effect that you're looking for.

Niels

Thx for the help!

f4bo

just poked here to say thankyou for this mine of tips, hope this page will keep pinned on the internet for the time being because how precious it is

tobiasschulz

Thank you, some new tips for me.

Aleksei

May you explain more about "Preload Audio Data". I did not understand, have I tick or untick this option for android game (for big mp3 files)?

Damian Connolly

Preload Audio Data just loads and decompresses your sound file in memory so that it's ready to play immediately when you go use it. Whether or not to set it depends on the type of sound in question. If it's a short sound file (e.g. a gunshot), then you can set it so you don't suffer the slight delay that comes from having to load the sound initially. For longer sounds, such as music, it's better to leave it off, as you'll suffer longer delays on app/scene startup. You'd also be using memory unnecessarily (long sounds like music should always be streamed, especially on mobile).

Hamza Stark

Thanks for this helpful article, I've applied some of the tips and my game is doing well now, but the android device still heating up while running it.

Damian Connolly

Hi Hamza,
If your device is heating up when running your game, then it suggests that you're doing a lot with the CPU or GPU (profile to find out which). Depending on the type of game, this may or may not be a problem. If it's a complex game with tons going on, or if it's running on a lower-end device or specific chips, then this might be "normal". If there's not much going on, then it means that you're over-taking the hardward for nothing (e.g. if you have your game running at 60fps, but it doesn't need to, or at least it doesn't need to all the time. Without knowing more about the game in question, it's hard to be sure.

Brogan

Thanks a lot for this blog. It helped a lot. I was creating a scroll snapping script (using ScrollRect UI) which worked perfectly in the editor but when I would try it on mobile it wasn't very responsive, but now its great.

One question. Do you think the Text component has improved since this post? i.e using Unity 5.6? I wondering if it still worth changing all my text components to the TextMesh Pro asset?

Damian Connolly

Hi Brogan,
In terms of performance, it's definitely worth it. In fact, Unity like it so much that TextMesh Pro is now part of Unity :) Right now it's free on the Asset store, and it should be directly integrated in later versions of Unity.

5argon

Thanks for the article.

For TextMeshPro (Unity's or not) I have something to say. It uses different material from the usual Unity Text. (It's Distance Field, (you can Google for Valve's paper) which allows crisp text on a big range of scaling despite very small texture size that store the text's texture) So it will impact your draw call if you make a switch from UGUI Text if they are sandwiched in between your other UIs. (Different material = set pass call) If you use UGUI Text it will batch nicely with other Image components.

One solution is to arrange the hierarchy so that Text Mesh Pro is rendered the last, but since Unity's UI render order depends on hierarchy order, you might have to move Text Mesh Pro out of your desired parent that you want. (You might have an animation on that parent that control this text, etc. so you cannot move out.)

But I have found that TMPro included "Distance Field Overlay" which have "Queue"="Overlay" specified in the shader. This means no matter where it is in the hierarchy it will be rendered the last. You should probably use this because most of the time nothing is blocking the text (so that your player can read it, of course) Use the frame debugger to confirm. (It will not really be the last in the screen, but the last in that canvas) You will still have draw call +1 when you make a switch, because the switch from Unity's UI texture to Distance Field, but that worths the crispness of TMPro.

Damian Connolly

Hi 5argon,
Great points. We've found the same thing in terms of hierarchy order, but Unity generally does a decent job of batching them all together, even if they're in different parents or animated. The frame debugger is essential here - from 5.6 onwards Unity will now also tell you why your call isn't batching, so you can be sure.

You do get the extra draw call, but honestly, if you've any half-way decent amount of text in your games/screens, the gains more than make up for it :)

Min Shin

So R U saying choosing compression format for mobile game is meaningless? Then, why is there option for compression format on mobile overiding option?

Damian Connolly

Hi Min Shin,
I was basing this on the Unity AudioFiles Manual page where they say:

When audio is encoded in Unity the main options for how it is stored on disk is either PCM, ADPCM or Compressed. [...] The default mode is Compressed, where the audio data is compressed with either Vorbis/MP3 for standalone and mobile platforms, or HEVAG/XMA for PS Vita and Xbox One.

So it looks like I mis-read this as saying only Vorbis/MP3 is used for mobile, but it's rather that's what happens if you choose Compressed mode, so that's my bad. I've updated the post.

TATAY

Thank you for this! I tried many of your tips and it works! the looks of my graphics is better than before! and a bit fast! :D

Burca

Omg, all the sections este helpfull, The tips and troços lerned here até invaluable, thanks a lot !

Sone

Ive been searching the web for this Optimization guide and found this Holy Grounds of Optimization.

i hope you continue this and update this to the current Unity version

paruthi

Great article, Keep this updated and add more..
very useful and collection of more optimization techniques in one place..

AllanDavis

Hello sir great article, I'd like to summarize this with four words: Sleep with my wife. It blew my brains out and I didn't even have to waste any of my shotgun shells! I've been addicted to heroin for the last 20 years but thanks to this article I am finally free. Thank you.

Max

Get around of Debug.Log calls:

#if UNITY_EDITOR
	Debug.unityLogger.logEnabled = true;
#else
	Debug.unityLogger.logEnabled = false;
#endif
madcode

Hi, Unity Profiler allows saving/loading data now.

Submit a comment

* indicates required