A message from our CEO about the future of Stack Overflow and Stack Exchange. Read now.
153

"Memory" and "efficiency" are commonly misused terms, so I'll give you an answer for four different elements that may affect the performance of your game. I will be oversimplifying way too many things to keep it short and concise, but there are tons of inaccuracies in this text below, so take it with a pinch of salt. However, the main concepts should be ...


58

the app crashes when it reaches 1.5Gb. This strongly suggests that you're not representing your tiles correctly, as this would mean that each tile is ~80 bytes in size. What you need to understand is that there needs to be a separation between the gameplay concept of a tile, and the visual tile that the user sees. These two concepts are not the same thing. ...


45

By authoring an audio clip with high BPM, then playing back at half speed you are effectively halving the sample rate. You can achieve a similar reduction in asset size without changing your workflow or any existing audio files by reducing the sample rate in the AudioClip inspector. Also checkout the various compression options on that page as they all ...


41

If you're planning to instantiate many instances of the same prefab, you should definitely think about using object pooling. Calling Unity's Instantiate function is one of the most taxing method calls you could make. Object pooling is when you instantiate prefabs before they are used. They are deactivated immediately upon instantiation and reactivated only ...


27

There are multiple algorithms that are much faster than A* when you need to recalculate a path with moving obstacles. See here under "Simple Recalculations". However, you're not likely going to find an off-the-shelf solution for any of them, so in 99% of cases they're overkill for a game. Your time would be better-spent using an existing, fully-optimized ...


26

Once an image is loaded off the disk and is formatted for rendering, it will use the same amount of memory regardless of whether that image was saved to disk using PNG, JPEG, or GIF. General rule of thumb: JPEG is a lossy format, and will degrade image quality in order to make the image smaller on disk. PNG, on the other hand, is a lossless image format, ...


22

Split the terrain into regions or chunks. Then only load the chunks that are visible to the players and unload the ones that are not. You can think of it like a conveyor belt, where you're loading chunks at one end and unloading them at the other as the player moves along. Always staying ahead of the player. You can also use tricks like instancing. Where if ...


17

We have a similar case with our RTS (KaM Remake). All units and houses are sprites. We have 18 000 sprites for units and houses and terrain, plus another ~6 000 for team colors (applied as masks). Long-stretched we also have some ~30 000 characters used in fonts. So there are some optimizations against RGBA32 atlases you are using: Split your sprites pool ...


16

Generally, you don't handle out-of-memory. The only sane option in software as large and complex as a game is to just crash/assert/terminate in your memory allocator as soon as possible (especially in debug builds). Out-of-memory conditions are tested for and handled in some core system software or server software in some cases but not usually elsewhere. ...


16

Modern open-world games simply don't fit in memory. Keep in mind that most games are still 32-bit due to the number of gamers with 32-bit OSes, and a 32-bit process at best can only have 4GB of addressed memory at a time (independent of virtual memory) but realistically is limited to 2-3 GB. Toss in fragmentation and the actual amount of usable objects you ...


16

What you need to do is separate terrain from live blocks. For example you could store the live blocks in a dictionary that uses a point as key. And then unload the terrain. This way your live blocks stay in memory in a way you see fit, and you can still look them up based on position, but the terrain is stored on disk for later retrieval. This will increase ...


14

You'd be hard pressed to find a mobile GPU that could use doubles even if you wanted to, so that part of the choice is pretty much made for you. There are only a few places where you might benefit from switching from single-precision floats in your game: recording a total elapsed time representing an absolute position that could be several kilometers from ...


13

Mick West's article explains the process of linearising entity component data, in full. It worked for the Tony Hawk series, years ago, on much less impressive hardware than we have today, to greatly improve performance. He basically used global, pre-allocated arrays for each distinct type of entity data (position, score and whatnot) and references each array ...


13

What you want is a memory profiler, Which Unity does have. Here: http://docs.unity3d.com/Manual/ProfilerMemory.html But your assumption is mostly right, if a gameObject is not visible to the camera it is not drawn, and it uses less resources, but it still must consume some. The gameObject still exists in memory, including all the textures, models scripts ...


13

Each glDraw* is a draw call. 1 glDrawArrays is 1 draw call. 1 glDrawElements is 1 draw call. It doesn't matter (so far as draw call count is concerned) how many vertices or indices you use, 1 glDraw* is 1 draw call. The simple cases of drawing quads (assuming the GL version you use hasn't removed quads) or triangles are not a good example for comparing ...


12

A very simple approach is to use "AI Level of Detail." Roughly, this means that you update AI more frequently the closer it is to the player/camera. You can also reduce the complexity of AI calculations that are farther out, esp. for path-finding. After all, if the player can't see the character well or at all, there's no point putting in a ton of effort ...


12

You only need to destroy the GameObject. By destroying the GameObject (Destroy(this.gameObject);), you also destroy the script (Destroy(this)) automatically. Destroying the script simply removes the component from the GameObject. Destroying the GameObject removes all of its components, and the GameObject itself. But there is an issue with your code. ...


10

Yes. A* is still the way to go in almost every case. It's your node cost calculation that becomes dynamic and therefore more complex to calculate and track. If you already know where the moving obstacles will be in the future your A* can take the temporality of obstacles into account in the cost function. E.g.: This node will be reached in 4 ticks, ...


9

1 kB = 1024 Bytes. Most of programming languages have 1 Byte = 1 character, so: If your lines are 1 character long, 1 kB = 1024 lines If your lines are 1024 characters long, 1 kB = 1 line If your lines are 25 characters long, 1 kB = about 40 lines BTW. if your programming language is compiled, it has nothing to do with memory-efficiency. BTW2: There is ...


9

I understand that having the same "size" each attachment can be aligned better, but practically speaking is it better to waste channels (or reserve them for future use) and having all the RTs of the same size or I should use just what needed? Having a unified 32bit aligned Render Targets is better, even if it means "wasting" some memory. This will be ...


9

Tiles and icons (even in UIs like window systems) are often in a size like 16x16 or 24x24 to make it easier to modify the tiles. Most times the tile size is a multiple of 8 because of the folowing reasons. It is relatively easy to shrink a tile with the size 32x32 to 16x16 by simply putting 4 pixels together (e.g. create the median/average of the 4 pixels). ...


7

If anything, the first option might be better for cache misses since generally you'll be iterating through, say, all the Renderable components at once. Just copy the data you need into that component to avoid cache misses due to looking up data. But it seems like you're suffering from design paralysis. Do you actually have a working game yet? Are the ...


7

As mentioned in PeterT's comment, you don't need to load all of your levels at once; instead you just load the current level and when the player transitions from that to a new one, you unload the current and load the new. That gets you down to about 100mb (the raw per-level cost), but we can go lower still. Consider a cube; right now you're defining each ...


6

Java's garbage collector is nondeterministic. There's System.gc(); but it will likely do nothing. See the StackOverflow question for further discussion.


6

For a 32-bit game, as most games are for a variety of reasons, even a game that comes on one single-sided DVD (4.3GB) already has far more content that can be fitted into a 32-bit address space. And that's assuming the content isn't compressed on disc, and a perfectly optimal, load everything at once into contiguous address space approach. Many games now ...


6

One option would be to load lighting information only as it appears on the screen. You would get one performance hit at the beginning as the full screen lighting is calculated, but from there you could cache the information and (as you mentioned) update it only when a light is flagged as modified. As you move across the world, you could calculate a short ...


5

Byte56's answer is good, and I started writing this as a comment to that but it got too long and contains some tips that might be more helpful in an answer. The approach is absolutely just as good for server as it is for a client. In fact it's probably more appropriate, given that the server will be asked to care about far more areas than a client will. The ...


5

Swapping textures will kill your performance. Modern hardware has only gotten more susceptible to this problem, not less, as the speed and power of the shader units and video RAM are growing much faster than the speed increases of the bus between system RAM and the GPU. The only sane approach is to cut down your texture sizes, or generate procedural ...


Only top voted, non community-wiki answers of a minimum length are eligible