The story of a simple mobile game
Hello! We are a small team of two people who try to make games in their free time. More recently, we finally released our first modest creation and decided to share the experience of its creation with the habrasociety.

“Everyone has their own runners, but why are we worse? We, too, will be able to get an extremely simple game for phones in a month, ”we thought a little over a year ago, and it all started.
We drew a couple of sketches, wrote a 2-sheet dzdock and took Unity, with whom we already had little experience. Having decided that we can cope with a simple runner in about a month or two, we started to work.
Caution, under the cut quite a lot of pictures!
Prototype
So, we decided to create something very simple, one-button. The main idea is a character who runs and breaks stones on the go. The player needs to tap on the screen at some point in order to destroy the obstacle.
In about a week, a prototype was created, which consisted of the main character - Ogre, the Dinosaur chasing him and a generator of stones, which scattered into pieces even with the use of physics.
Graphically, all this was wrapped in a simple and bright flat-style. For the first steps - what you need.

One of the first sketches
Of course, we love hardcore games, but not like when you lose after one wrong press. Therefore, it was decided that in one round the player will have the right to 3 errors, after which the Dinosaur will eat the main character.
After playing a little prototype, we realized that you need at least some kind of gameplay. So we got hens. Their final implementation is quite different from what it was originally.
In the first implementation, Ogre threw a boomerang at the hens. In this case, the player needed to “cut” the chicken with his finger, just like fruit is cut in Fruit Ninja. And to get on the chicken it was necessary twice. The first time part of the plumage flew from her, the second time she turned into several chicken legs that flew into the mouth of the Dinosaur. Dino ate and wandered. Missed at least one chicken - the Dinosaur was angry and came closer. But it not only sounds bulky, but also played. The chickens were completely redone: instead of several birds and a boomerang, a flock of birds and, suddenly, a double-barreled shotgun. Not, well, really, this is a game, anything can happen here. Blue ogre running away from a dinosaur? YES! Shotgun? Why not? Chicken in the sky? Yes, this is not one chicken, but a whole flock, and we will now ridicule them!
Now, to kill a chicken, it was enough to tap on it. Chicken legs were removed, and if you do not kill the feathered bird in time, it will crash into the dinosaur's face, it will get angry and come closer.
A draft version of all these ideas was ready about 2 weeks after the start of development. The funny thing is that the gameplay prototype was not much different from the current release.
In total, we got a gameplay consisting of two alternating parts: breaking stones and shooting swarms of hens from a shotgun.
After the gameplay was more or less clear, we cut out unnecessary content and began to add the necessary elements. So over the next couple of months there appeared: an initial splash screen, several options for the background that replaced each other, other decorations, such as bushes and flowers, a simple tutorial, and Ogres began to appear bruises after hitting a stone. After that, it was time to put everything in order, which took most of the time.

Chicken legs and boomerangs were immediately sent to the trash
All characters underwent changes compared to the original images, more details were added. Only the hens immediately turned out to be excellent and graphically did not change at all.

Screenshot from the release version
In this game I wanted to try out skeletal animation. In the end, we decided to try the CCD plugin, which was demonstrated at one of the Unity conferences. Slightly modified, he lived up to the release version, and for this project we basically had enough. However, in the future, if skeletal animation is needed, we will definitely use more advanced tools.

Since the gameplay obliges the player to constantly be focused on breaking stones, I wanted to make the animation smooth and without unnecessary details. But we added a couple of pleasant little things, such as playful eyebrows, a jumping belly and a moving tuft of hair.

It turned out pretty smoothly. For the release voice acting, we bought several libraries with sounds in the Asset store, we recorded a couple of sounds ourselves. The music was ordered from an independent composer.
The only interesting fact was that no less than the sounds from the first Half-Life were used for draft voice acting. In particular, the stone broke with the characteristic sound of death from a hit from Gaussgan. Replacing it in the end with something more like breaking stones, for some time we could not get used to the new sound after such a native Gauss.
Well, what could be the menu in such a small game? But there it was, it turned out that a considerable number of buttons would have to be shoved so that there would be a minimal set now: help, records, app rating, mute. And you also need to remember to add the ability to disable ads. And you also need points, the best result and the player’s reward for setting a new record. Well, and, in the end, it is more pleasant to receive earned coins than just a jump in the counter.
Such rewards were a steadily increasing amount of money with a characteristic ringing of coins and an animation of the cup with applause in case of setting a record. Trivia, but nice.

One of the sketch menus. In fact, it looks the same in the release version.
By the way, after Unity 4.6, creating a UI has become a much simpler process, so here we are lucky.
After our prototype began to resemble the game more and more, we wondered how else we could lure the player to come back again, except for the table of records that we had originally planned.
As a basis, we decided to take the idea of collecting. The unlockable characters are cool, but long. It takes a lot of art, a lot of animations, more testing of how they all behave in the game. We also thought to make background landscapes and stones openable, but in the end we decided to collect eggs.
So we added an egg store, which, however, turned out to be a variety of trophies.

Egg store. Before buying, one can only guess what is hidden behind the silhouette.
By the way, this store was not so easy as it seemed from the beginning. As a result, we made a custom shader for eggs not yet purchased and finalized the standard ScrollRect.
We decided to try to add some kind of monetization. So to speak, try this thing technically and, perhaps, collect some tips.
As a result, our choice fell on one of the simplest options - advertising. Since we did not intend to embed banners directly into the game, thereby disfiguring the game scene, we decided to display interstitial ads in full screen at the end of every third round. It seems more or less democratic. We also added the ability to disable ads for a minimum payment (0.99 USD). Here the In-App Purchasing service from Unity helped us. Everything is pretty trivial, more details can be found in the official tutorial . Works for both iOS and Android.
You can also mention that the UI for this payment is slightly different for iOS and Android. The whole difference is that in iOS it is necessary to give the user the opportunity to manually restore his already made payment when changing the device or reinstalling the game (Android, as far as we know, does this automatically).
In addition, we added viewing video ads for coins, but here everything is strictly at the request of the player.
From advertising, they first started connecting AdMob, but pretty quickly switched to Appodeal . Of the advantages - a fairly simple integration and a good one. support for free service.
By the way, there were several problems with advertising, some of which still remain: the game crashes in the beginning on weak and not very devices, not all users display video for a fee (it is usually treated by resetting the advertising ID, but which of the users will do this )
To work with achievements and leaderboards in Unity there is a Social interface, which by default has an implementation for iOS. For Android, the implementation is, for example, in the plugin from Google - play-games-plugin-for-unity . When assembling for Android, you just need to put the initialization of the PlayGamesPlatform in the #if UNITY_ANDROID block, and the code associated with Social for Android and iOS can be used the same.
By default, play-games-plugin-for-unity also tries to build for iOS builds. To exclude it and use the implementation from Unity, you need to add the NO_GPGS key to the Scripting Define Symbols (located in Player Setting → Other Setting):

By the way, after adding play-games-plugin-for-unity to the project, we encountered a 65k problem when building under Android. They were saved by creating an empty project and throwing only Appodeal and play-games-plugin-for-unity into it.
When almost everything was ready, despite the tests on real devices, we ran into a performance problem. Looking ahead, I’ll say that optimization took a considerable amount of time.
Here are a few links to some of the most useful articles for us: about everything , about allocations in C # part 1 , about allocations in C # part 2 .

Our first problem was an obscene large number of Draw Calls - about 50. And then FrameDebugger , which first appeared in Unity 5.0, came to our aid . Looking at the step-by-step construction of the frame, repacking the texture atlases and setting up Order in Layer, we got an average of 15 Draw Calls. Already not bad. A little later, we again returned to this issue - we combined some atlases (for example, Ogre, Dinosaur, Kurochka and the nest are now stored in one texture), reduced the number of Sorting Layer, and as a result we got 7-8 Draw Calls on average.
In addition, FrameDebugger allows you to find graphics that are drawn, but which in the end are not visible on the resulting scene. For example, we did not remove the cloud above the Dinosaur’s head from the running animation, which is necessary only in the splash screen:

FrameDebugger in action
In addition to FrameDebugger, Xcode also perfectly shows what happens with rendering. It also allows you to see the construction of the frame, and it may differ from what FrameDebugger showed you:

Profiling with
Xcode We also learned about the second problem with Xcode: an unreasonably large number of vertices. Perhaps some will ask: “A sprite is 2 triangles, where does the heap of vertices come from?” The fact is that on modern graphics accelerators it’s cheaper to draw a mesh with a reasonable number of vertices than to process a bunch of transparent pixels. Therefore, Unity builds the mesh along the outline of the sprite, but does not always do this optimally.
Here, not free, but extremely useful SpriteSharp asset came to our aid. After applying it, the number of vertices in the scene rarely exceeds a thousand.

By the way, this feature can be disabled, and then the sprites will be built classically from two triangles. These settings are in the texture parameters:

You can find out the number of Draw Calls and the number of vertices even without using profilers - just look at Stats:

And some more tips:
Initially, the point counter was made using a dynamic font and options, which could cause a jerk with each successful breaking of the stone, as the counter increased by one, and at the same time the inscription mesh was rebuilt. The way out is to use the Custom set in the fonts themselves and turn off Best Fit in UI.Text.

You can learn about physics in Unity from a good article on Habré . Let’s say about us that in the release version we don’t use it at all.
For example, at first we had colliders on all stones and Ogre. However, there is no need to consider the intersection of Ogre with all the stones, it is enough to know the distance to the nearest one. Moreover, the distance is only in x - no square roots are needed.
We also had circle colliders on each chicken. Again, it makes no sense to check the intersection of the coordinates of the tap with all the colliders. Since with one tap you can kill up to two hens, it is enough to find the first two intersections and stop further calculations.
We searched for a hit by using the distance from the center of the chicken to the coordinates of the tap, and here you can also do without square roots - just use sqrMagnitude and the square of the radius. A bit more here .
For stones, we applied the “baking” of physics to the animation. On each stone, 3 animations were recorded for successful smashing with a fist and 3 when the Ogre crashes into a stone. In fact, it looks almost the same as with the use of physics simulations. The scripts that we wrote for baking can be found on bitbucket - suddenly someone will come in handy.
We also moved from the approach “each scene element is engaged in its own updating” to the “manager and a set of elements for which he is responsible” scheme.
For example, in the case of the hens, each of them could be endowed with its own Update method, in which she would look for the remaining hens and apply the logic of behavior in the pack. However, the chicken script we have contains only basic methods, such as turn around or die. The flock script is responsible for the behavior of all birds in the bunch.
This approach allows more flexible and centralized management of scene updates. For example, elements that do not affect gameplay can only be updated several times per second, instead of updating each frame. Or, if the collection is very large, do not update all the items in one Update, but distribute their updates frame by frame: frame N - update the first half of the collection, frame N + 1 - update the second half.
And you should always remember that every call to the MonoBehaviour method, like Update or Start, has a certain overhead. You can read more about this on the Unity blog .
The pool of objects is a “must have” when using Unity (and any other engine in principle). Fortunately, we had it from the beginning.
Well, you should never forget about the "overflow" float:

Metamorphoses in the distant worlds. At the top right, the coordinate value on the X axis
In our case, when the value reaches 100000 on the X axis, the scene shifts by -100000. Another technique that could be applied was to simulate movement. Ogre and Dinosaur stand still, and the whole environment moves from right to left.
To search for bottlenecks, always use profilers from both Unity itself and Xcode. And do it on a specific device, and not in the editor.
In conclusion of the chapter on optimization, I would like to add that, despite all efforts, lags still happen: activities related to advertising, payments, Google Play / Game Center and the operating system itself.
Well, of course, somewhere we ourselves overlooked.

Probably everyone knows that in order to release their application on iOS, you need some kind of mac-device? Yes, of course, you can try all sorts of tricks like “hackintosh” or make friends - the lucky owners of the MacBook.
It is not known how Apple will behave if it suddenly finds out that the application was uploaded from the hackintosh. And somehow I don’t feel like getting a banhammer and losing all my applications in the App Store. This option was abandoned immediately.
The alternative to constantly getting friends who have a poppy is doubtful, since building, debugging, profiling, and then uploading applications, updates, additional editing or corrections, rolling out updates and so on - all this requires more than one evening of work.
As a result, we got a Mac mini medium configuration. Here, by the way, the scheme works well: to develop on a powerful PC, and use a weak poppy only for activities related to the App Store.
Another interesting fact about the App Store is the description and screenshots you can upload from any platform, but video only from Safari no lower than 8, running on OS X no lower than 10.10. Moreover, up to 24 hours are allotted for video processing after uploading.
Well, in general, the rules for publishing are more stringent than on Google Play, so if you get Apple’s app, you’ll definitely be able to figure out Android.
By the time of receipt of the appraise, it now takes about two days. An article about the pitfalls of markets was not very long ago on Habré .
Well, in the official manual, the requirements for the posted materials are also pretty well described .
Posting on Google Play was much easier. Video and screenshots for the phones we have already been prepared, we just have to make versions for tablets with sizes of 7 and 10 inches and upload the video to YouTube.
After that, we prepared the release apk and checked everything on the beta test. Next, it was necessary to send it for consideration. And here you should be careful if you do not want to immediately release your application. We now knew that it was easy to do, and still stepped on this rake, releasing the Android version a little earlier than planned.
In this regard, we can say: always follow what is selected in the drop-down list on the Production page in the upper right:

And remember that after each delayed publication this parameter is reset to the standard publication.
By the time you receive the apprave, it usually takes several hours now.
Again, more details can be found all in the same article from Habr and the official manual on the preparation of materials.
Well, and for dessert - the main question: “Why so long ?!” (and almost a year and a half has passed since the start of work until the release).
In fact, the main gameplay, which came to the release almost unchanged, was created in the first month of development.
And then adding a store, menu, improvements, alterations, redrawing, fixing after updating Unity and waiting for bug fixes from them, optimization and a bunch of technical difficulties, which were done very slowly due to inexperience. For example, we spent several evenings just organizing the beta build and testing process for iOS.
There were problems with advertising, there were problems with the build for Android, when we connected all the plugins.
And of course, the “human factor”, it’s laziness. Because we were engaged in the game only in our free time and rather as a hobby, it was not always possible to do
something useful after a hard day's work .
However, the main goal for us was to go through a full development cycle: from prototype to release, and we did it.

“Everyone has their own runners, but why are we worse? We, too, will be able to get an extremely simple game for phones in a month, ”we thought a little over a year ago, and it all started.
We drew a couple of sketches, wrote a 2-sheet dzdock and took Unity, with whom we already had little experience. Having decided that we can cope with a simple runner in about a month or two, we started to work.
Caution, under the cut quite a lot of pictures!
Prototype
So, we decided to create something very simple, one-button. The main idea is a character who runs and breaks stones on the go. The player needs to tap on the screen at some point in order to destroy the obstacle.
In about a week, a prototype was created, which consisted of the main character - Ogre, the Dinosaur chasing him and a generator of stones, which scattered into pieces even with the use of physics.
Graphically, all this was wrapped in a simple and bright flat-style. For the first steps - what you need.

One of the first sketches
Prototype development
Of course, we love hardcore games, but not like when you lose after one wrong press. Therefore, it was decided that in one round the player will have the right to 3 errors, after which the Dinosaur will eat the main character.
After playing a little prototype, we realized that you need at least some kind of gameplay. So we got hens. Their final implementation is quite different from what it was originally.
In the first implementation, Ogre threw a boomerang at the hens. In this case, the player needed to “cut” the chicken with his finger, just like fruit is cut in Fruit Ninja. And to get on the chicken it was necessary twice. The first time part of the plumage flew from her, the second time she turned into several chicken legs that flew into the mouth of the Dinosaur. Dino ate and wandered. Missed at least one chicken - the Dinosaur was angry and came closer. But it not only sounds bulky, but also played. The chickens were completely redone: instead of several birds and a boomerang, a flock of birds and, suddenly, a double-barreled shotgun. Not, well, really, this is a game, anything can happen here. Blue ogre running away from a dinosaur? YES! Shotgun? Why not? Chicken in the sky? Yes, this is not one chicken, but a whole flock, and we will now ridicule them!
Now, to kill a chicken, it was enough to tap on it. Chicken legs were removed, and if you do not kill the feathered bird in time, it will crash into the dinosaur's face, it will get angry and come closer.
A draft version of all these ideas was ready about 2 weeks after the start of development. The funny thing is that the gameplay prototype was not much different from the current release.
In total, we got a gameplay consisting of two alternating parts: breaking stones and shooting swarms of hens from a shotgun.
After the gameplay was more or less clear, we cut out unnecessary content and began to add the necessary elements. So over the next couple of months there appeared: an initial splash screen, several options for the background that replaced each other, other decorations, such as bushes and flowers, a simple tutorial, and Ogres began to appear bruises after hitting a stone. After that, it was time to put everything in order, which took most of the time.

Chicken legs and boomerangs were immediately sent to the trash
Graphics and animation
All characters underwent changes compared to the original images, more details were added. Only the hens immediately turned out to be excellent and graphically did not change at all.

Screenshot from the release version
In this game I wanted to try out skeletal animation. In the end, we decided to try the CCD plugin, which was demonstrated at one of the Unity conferences. Slightly modified, he lived up to the release version, and for this project we basically had enough. However, in the future, if skeletal animation is needed, we will definitely use more advanced tools.

Since the gameplay obliges the player to constantly be focused on breaking stones, I wanted to make the animation smooth and without unnecessary details. But we added a couple of pleasant little things, such as playful eyebrows, a jumping belly and a moving tuft of hair.

Music and sound
It turned out pretty smoothly. For the release voice acting, we bought several libraries with sounds in the Asset store, we recorded a couple of sounds ourselves. The music was ordered from an independent composer.
The only interesting fact was that no less than the sounds from the first Half-Life were used for draft voice acting. In particular, the stone broke with the characteristic sound of death from a hit from Gaussgan. Replacing it in the end with something more like breaking stones, for some time we could not get used to the new sound after such a native Gauss.
End menu
Well, what could be the menu in such a small game? But there it was, it turned out that a considerable number of buttons would have to be shoved so that there would be a minimal set now: help, records, app rating, mute. And you also need to remember to add the ability to disable ads. And you also need points, the best result and the player’s reward for setting a new record. Well, and, in the end, it is more pleasant to receive earned coins than just a jump in the counter.
Such rewards were a steadily increasing amount of money with a characteristic ringing of coins and an animation of the cup with applause in case of setting a record. Trivia, but nice.

One of the sketch menus. In fact, it looks the same in the release version.
By the way, after Unity 4.6, creating a UI has become a much simpler process, so here we are lucky.
In-game store
After our prototype began to resemble the game more and more, we wondered how else we could lure the player to come back again, except for the table of records that we had originally planned.
As a basis, we decided to take the idea of collecting. The unlockable characters are cool, but long. It takes a lot of art, a lot of animations, more testing of how they all behave in the game. We also thought to make background landscapes and stones openable, but in the end we decided to collect eggs.
So we added an egg store, which, however, turned out to be a variety of trophies.

Egg store. Before buying, one can only guess what is hidden behind the silhouette.
By the way, this store was not so easy as it seemed from the beginning. As a result, we made a custom shader for eggs not yet purchased and finalized the standard ScrollRect.
Monetization
We decided to try to add some kind of monetization. So to speak, try this thing technically and, perhaps, collect some tips.
As a result, our choice fell on one of the simplest options - advertising. Since we did not intend to embed banners directly into the game, thereby disfiguring the game scene, we decided to display interstitial ads in full screen at the end of every third round. It seems more or less democratic. We also added the ability to disable ads for a minimum payment (0.99 USD). Here the In-App Purchasing service from Unity helped us. Everything is pretty trivial, more details can be found in the official tutorial . Works for both iOS and Android.
You can also mention that the UI for this payment is slightly different for iOS and Android. The whole difference is that in iOS it is necessary to give the user the opportunity to manually restore his already made payment when changing the device or reinstalling the game (Android, as far as we know, does this automatically).
In addition, we added viewing video ads for coins, but here everything is strictly at the request of the player.
From advertising, they first started connecting AdMob, but pretty quickly switched to Appodeal . Of the advantages - a fairly simple integration and a good one. support for free service.
By the way, there were several problems with advertising, some of which still remain: the game crashes in the beginning on weak and not very devices, not all users display video for a fee (it is usually treated by resetting the advertising ID, but which of the users will do this )
Connect Leaderboards
To work with achievements and leaderboards in Unity there is a Social interface, which by default has an implementation for iOS. For Android, the implementation is, for example, in the plugin from Google - play-games-plugin-for-unity . When assembling for Android, you just need to put the initialization of the PlayGamesPlatform in the #if UNITY_ANDROID block, and the code associated with Social for Android and iOS can be used the same.
By default, play-games-plugin-for-unity also tries to build for iOS builds. To exclude it and use the implementation from Unity, you need to add the NO_GPGS key to the Scripting Define Symbols (located in Player Setting → Other Setting):

By the way, after adding play-games-plugin-for-unity to the project, we encountered a 65k problem when building under Android. They were saved by creating an empty project and throwing only Appodeal and play-games-plugin-for-unity into it.
Optimization
When almost everything was ready, despite the tests on real devices, we ran into a performance problem. Looking ahead, I’ll say that optimization took a considerable amount of time.
Here are a few links to some of the most useful articles for us: about everything , about allocations in C # part 1 , about allocations in C # part 2 .

Batchy, batchy, batchy
Our first problem was an obscene large number of Draw Calls - about 50. And then FrameDebugger , which first appeared in Unity 5.0, came to our aid . Looking at the step-by-step construction of the frame, repacking the texture atlases and setting up Order in Layer, we got an average of 15 Draw Calls. Already not bad. A little later, we again returned to this issue - we combined some atlases (for example, Ogre, Dinosaur, Kurochka and the nest are now stored in one texture), reduced the number of Sorting Layer, and as a result we got 7-8 Draw Calls on average.
In addition, FrameDebugger allows you to find graphics that are drawn, but which in the end are not visible on the resulting scene. For example, we did not remove the cloud above the Dinosaur’s head from the running animation, which is necessary only in the splash screen:

FrameDebugger in action
In addition to FrameDebugger, Xcode also perfectly shows what happens with rendering. It also allows you to see the construction of the frame, and it may differ from what FrameDebugger showed you:

Profiling with
Xcode We also learned about the second problem with Xcode: an unreasonably large number of vertices. Perhaps some will ask: “A sprite is 2 triangles, where does the heap of vertices come from?” The fact is that on modern graphics accelerators it’s cheaper to draw a mesh with a reasonable number of vertices than to process a bunch of transparent pixels. Therefore, Unity builds the mesh along the outline of the sprite, but does not always do this optimally.
Here, not free, but extremely useful SpriteSharp asset came to our aid. After applying it, the number of vertices in the scene rarely exceeds a thousand.

By the way, this feature can be disabled, and then the sprites will be built classically from two triangles. These settings are in the texture parameters:

You can find out the number of Draw Calls and the number of vertices even without using profilers - just look at Stats:

And some more tips:
- Leave the final combination of texture atlases for later, when you really have settled down the contents of the scene.
- Carefully watch how you change the color of sprites. SpriteRenderer.color does not break the batch, but SpriteRenderer.material.color, like any other material change, breaks.
- Remember that dynamic batching has a number of limitations, for example, the meshes that will be merged cannot contain more than 900 vertex attributes in total. More details can be found on the official Unity website .
A bit about fonts
Initially, the point counter was made using a dynamic font and options, which could cause a jerk with each successful breaking of the stone, as the counter increased by one, and at the same time the inscription mesh was rebuilt. The way out is to use the Custom set in the fonts themselves and turn off Best Fit in UI.Text.

Optimization of logic and physics
You can learn about physics in Unity from a good article on Habré . Let’s say about us that in the release version we don’t use it at all.
For example, at first we had colliders on all stones and Ogre. However, there is no need to consider the intersection of Ogre with all the stones, it is enough to know the distance to the nearest one. Moreover, the distance is only in x - no square roots are needed.
We also had circle colliders on each chicken. Again, it makes no sense to check the intersection of the coordinates of the tap with all the colliders. Since with one tap you can kill up to two hens, it is enough to find the first two intersections and stop further calculations.
We searched for a hit by using the distance from the center of the chicken to the coordinates of the tap, and here you can also do without square roots - just use sqrMagnitude and the square of the radius. A bit more here .
For stones, we applied the “baking” of physics to the animation. On each stone, 3 animations were recorded for successful smashing with a fist and 3 when the Ogre crashes into a stone. In fact, it looks almost the same as with the use of physics simulations. The scripts that we wrote for baking can be found on bitbucket - suddenly someone will come in handy.
We also moved from the approach “each scene element is engaged in its own updating” to the “manager and a set of elements for which he is responsible” scheme.
For example, in the case of the hens, each of them could be endowed with its own Update method, in which she would look for the remaining hens and apply the logic of behavior in the pack. However, the chicken script we have contains only basic methods, such as turn around or die. The flock script is responsible for the behavior of all birds in the bunch.
This approach allows more flexible and centralized management of scene updates. For example, elements that do not affect gameplay can only be updated several times per second, instead of updating each frame. Or, if the collection is very large, do not update all the items in one Update, but distribute their updates frame by frame: frame N - update the first half of the collection, frame N + 1 - update the second half.
And you should always remember that every call to the MonoBehaviour method, like Update or Start, has a certain overhead. You can read more about this on the Unity blog .
The pool of objects is a “must have” when using Unity (and any other engine in principle). Fortunately, we had it from the beginning.
Well, you should never forget about the "overflow" float:

Metamorphoses in the distant worlds. At the top right, the coordinate value on the X axis
In our case, when the value reaches 100000 on the X axis, the scene shifts by -100000. Another technique that could be applied was to simulate movement. Ogre and Dinosaur stand still, and the whole environment moves from right to left.
To search for bottlenecks, always use profilers from both Unity itself and Xcode. And do it on a specific device, and not in the editor.
In conclusion of the chapter on optimization, I would like to add that, despite all efforts, lags still happen: activities related to advertising, payments, Google Play / Game Center and the operating system itself.
Well, of course, somewhere we ourselves overlooked.
Posting on the App Store

Probably everyone knows that in order to release their application on iOS, you need some kind of mac-device? Yes, of course, you can try all sorts of tricks like “hackintosh” or make friends - the lucky owners of the MacBook.
It is not known how Apple will behave if it suddenly finds out that the application was uploaded from the hackintosh. And somehow I don’t feel like getting a banhammer and losing all my applications in the App Store. This option was abandoned immediately.
The alternative to constantly getting friends who have a poppy is doubtful, since building, debugging, profiling, and then uploading applications, updates, additional editing or corrections, rolling out updates and so on - all this requires more than one evening of work.
As a result, we got a Mac mini medium configuration. Here, by the way, the scheme works well: to develop on a powerful PC, and use a weak poppy only for activities related to the App Store.
Another interesting fact about the App Store is the description and screenshots you can upload from any platform, but video only from Safari no lower than 8, running on OS X no lower than 10.10. Moreover, up to 24 hours are allotted for video processing after uploading.
Well, in general, the rules for publishing are more stringent than on Google Play, so if you get Apple’s app, you’ll definitely be able to figure out Android.
By the time of receipt of the appraise, it now takes about two days. An article about the pitfalls of markets was not very long ago on Habré .
Well, in the official manual, the requirements for the posted materials are also pretty well described .
Posting on Google Play
Posting on Google Play was much easier. Video and screenshots for the phones we have already been prepared, we just have to make versions for tablets with sizes of 7 and 10 inches and upload the video to YouTube.
After that, we prepared the release apk and checked everything on the beta test. Next, it was necessary to send it for consideration. And here you should be careful if you do not want to immediately release your application. We now knew that it was easy to do, and still stepped on this rake, releasing the Android version a little earlier than planned.
In this regard, we can say: always follow what is selected in the drop-down list on the Production page in the upper right:

And remember that after each delayed publication this parameter is reset to the standard publication.
By the time you receive the apprave, it usually takes several hours now.
Again, more details can be found all in the same article from Habr and the official manual on the preparation of materials.
Conclusion About the timing
Well, and for dessert - the main question: “Why so long ?!” (and almost a year and a half has passed since the start of work until the release).
In fact, the main gameplay, which came to the release almost unchanged, was created in the first month of development.
And then adding a store, menu, improvements, alterations, redrawing, fixing after updating Unity and waiting for bug fixes from them, optimization and a bunch of technical difficulties, which were done very slowly due to inexperience. For example, we spent several evenings just organizing the beta build and testing process for iOS.
There were problems with advertising, there were problems with the build for Android, when we connected all the plugins.
And of course, the “human factor”, it’s laziness. Because we were engaged in the game only in our free time and rather as a hobby, it was not always possible to do
something useful after a hard day's work .
However, the main goal for us was to go through a full development cycle: from prototype to release, and we did it.