Ylands Best practices
Making a great game may not be enough - your game needs to run well as well. If your game runs slow, it may not be a problem, if it is a puzzle game, but, for example, an action game will very likely become unplayable. An even if your game runs great you may run into problems if it takes up too much memory on mobile devices.
And that is where optimization and knowing what to do and what to avoid comes in. Let us share with you some tips that will help you have great, nicely running games.
You can make two kinds of games. PC only and Universal (PC + mobile phones).
If your game is meant to run only on PCs, then you definitely have it easier. Every decent PC has enough power to run rather complex games so even poorly optimized games usually run quite well. The tradeoff is obvious - your game can reach substantially fewer players.
Making a game that runs well enough even on mobiles can be tricky. There is an extreme range of mobile devices from super slow ones to ones that can almost compete with computers. Even though players can affect visual details ingame to make the game run better it is up to you to optimize it as best as you can. The better job you do, the more devices (and therefore players) will be able to play your game.
So, let's get started.
You won't run into memory problems on PC, but you surely can when running your game on mobile devices. To make sure your game won't be terminated by the device's operating system when it consumes more memory than allowed you should watch the memory gauge in the lower-left corner of the screen in the Editor (or click it to see more information). Try staying in the green. Going in yellow means potential problems and you shouldn't definitely be in red.
The rule of thumb when trying to save memory is - simpler objects (like building blocks, game objects) take less memory than sophisticated objects (like NPCs, animals etc.). Using more identical objects is better than using fewer unique ones so using one hundred items of the same type will consume less memory than having 5 different items.
Also the larger your map is, the more memory it requires (given that it contains terrain). The smaller the map, the better.
Please note, that this gauge shows only what is currently present in the open scene. If your game spawns a lot of / complex objects during runtime, this information may be less relevant.
Level design / game objects
Some games can be made just with few blocks, others require terrains, sophisticated buildings, vehicles, characters, numerous particle effects. And so it is only logical that the more complex your worlds are the more attention you need to pay what you place in them.
The basic optimization rule is the same as with the memory - the fewer different types of objects you use, the better will the game run. But there are many more things to bear in mind:
- good level design is one, where players, no matter where they look, see a similar scene complexity. This means that if you, for example, have a mostly empty scene with one very complex area, when players look around and this area comes to view a visible stutter in-game performance can be noticed.
- visually the most complex objects are NPCs and animals. They require quite a lot of both CPU and GPU power so if you're aiming at mobile devices (especially mid or low spec ones) you should be very careful with how much you put in your world
- there is no culling other than ignoring objects outside the camera frustum. In less technical language - what camera doesn't see takes up little to none performance. However, one needs to understand that these are the object positioned outside the camera cone (so it is above, below, to sides or behind the camera). Everything that is in front of you in this cone is rendered/calculated regardless of whether you see it or not. If you're looking into a wall, even though you don't see through it, the game does and still treats the objects behind it (performance-wise) as visible. The same goes for the terrain.
- a good game creator should check their game with the profiler we're providing exactly for these purposes - we will get to it shortly.
- A lot of objects is not a problem just for GPU. Each object in-game has its own collider (complex objects have more than one). Some colliders prevent the player from going through objects (entities like a brick) and some serve so you can focus them and pick them up (entities like grass). This is where Entity welding comes in. It can help by combining these colliders and so that there are fewer in your game (which helps performance). For example, a wall made from 20x20 cube bricks will then have just one big block collider instead of 400. Welding irregular entities may not have such a huge positive effect. At that moment you should consider if you need perfect collisions around objects. Maybe you have a building at a distance which is there only for visual purposes and a player never gets there. In cases like this, you should turn off collisions on the welded entity. In some cases you may try turning complex collisions on a welded entity off and putting around it Impassible barrier game logic object instead to act as a simple collider block.
Scripting, when done without following some basic rules can result in games that run awfully slow so let us mention few things to do and avoid:
- best scripting is event-driven, meaning that unless necessary, you shouldn't perform any continuous loops checking for state changes, the time elapsed etc. Before you run continuous loops in your code, check if there isn't a Game Logic that would suit your needs. Hook your code to Game Logic-specific events or listen for any in the game with Event Listeners.
- if you're performing anything very often inside very short Time Trigger event the chances are there are much cleaner and faster way of doing that
- note that every frame the game waits for the all the scripts to be processed and only then continues. This means that inefficient continuously running script will constantly lower your fps. If, on the other hand, you use from time to time very intensive scripting operations, this may create sudden fps drops. If this is your case, try not doing everything at once but spread the load over script executions. Remember, that consistently lower fps is better than high fps with noticeable fps drops.
- in general, the most performance heavy action is spawning a new entity. This may not be visible in the profiler since the actual scripting instruction to spawn something is fast but it can take time for the game engine to actually make the object appear. If you need to spawn object in runtime, consider having them ready in the editor and activating/deactivating them as needed as opposed to spawning and destroying them.
Testing your game
Even though testing your game in the Editor on PC won't show you how well your game will run on mobile phones, it is definitely important to test your game even so because you will be able to spot problems that on PC don't have such an impact but which will surely show very strongly on generally slower mobile devices.
You can run your game with PC and mobile profile. If you select a mobile profile you will be able to see how will the game differ visually (especially based on visuall quality settings) from what you see on PC.
When you start a test session in the Editor you will be able to show/hide Profiler windows which will give you information about scene complexity (polygons, draw calls), number of objects and script performance (when you you enable script profiling via F10).
If you have enabled Deep profiling in-game settings in the Editor you will even be able - once you gain mouse control after pressing ESC - browse the script profiling info and see a more complex breakdown of various script operations.
Please note that having script profiling enable (especially with Deep profiling activated) has its own slight impact on the script performance.