15

This is a really general learning-based question, not a technical problem.

I'm making a game in Unity. The game involves a lot of pretty complex, high-object-count processes, and as such, I generate a lot of garbage. As everyone who makes games that use managed code knows, garbage collection spikes are a HUGE buzzkill. I am also trying to target mobile devices, so this pain is amplified.

My goal is simple: track down the procedures that generate the most garbage and pool and reuse the objects involved in order to reduce the load on the garbage collector. I have tackled all of the obvious classes, but my GC issues persist. If anyone can offer some greater wisdom here, please bring it on.

What I have been unable to track down in my research is a good way to measure GC load and track down problem spots in the code itself. I can get metrics from Unity and from diagnostics classes about the size of the memory pool (though I'm no expert on what any of those numbers really mean) and I can display the total number of GC collections that have happened since the start, but my knowledge of debugging this issue kind of ends there.

I know there MUST be better ways to solve this problem. Can anyone point me at the right tools or framework classes (or libraries?) that can help me out here? I've seen some mention of a debugger program (sgen?) that's part of Mono, but I can't find a download or let alone a guide for how to hook it up to a Unity game.

Any help would be greatly appreciated. Thanks.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
scone
  • 566
  • 1
  • 4
  • 12
  • 7
    Open ended tool recommendations are off-topic because of the volume of spam and bad quality answers they attract. However, I don't think the whole question is a bad question. Can you tweak this to make it more about the process and less about recommending tools? I fear if you leave it as-is, it will get closed. – psubsee2003 Dec 06 '13 at 00:01
  • How about `IDispose` are you using it properly? – janisz Dec 06 '13 at 00:04
  • Wouldn't presume to assume a best one, but a profiler should help. As might this previous question, http://stackoverflow.com/questions/9669963/monitoring-garbage-collector-in-c-sharp – Tony Hopkinson Dec 06 '13 at 00:17
  • @janisz `IDisposable` has exactly nothing at all to do with GC pressure situations. It's pretty much the opposite – it deals with unused memory outside the GC's control. – millimoose Dec 06 '13 at 00:29
  • @TonyHopkinson - Similar question, however I think this question is more specific to the Unity3D framework. In which case there is in fact a solid answer to what tool is 'best'. My answer below discusses further. Hope it helps. – S.Richmond Dec 06 '13 at 05:09

2 Answers2

15

For C# and Unity3D specifically, the profiler built into Unity3D is the best tool you'll have available to you. You should be able to get very far with the Unity Profiler. Specifically the CPU Profiler:

enter image description here

I have highlighted the most important column - GC Alloc - Which, on a frame-by-frame basis, shows memory that has been allocated for garbage collection. The aim of the game here is to make that column as consistently close to zero as possible.

I'd suggest spending a few hours in there, playing your game, pausing it and digging into areas of your code where GC Alloc is showing numbers.

Finally, I strongly suggest you check out this video tutorial by one of the developers of Unity on memory debugging and using the Unity Editor profiler properly.

S.Richmond
  • 11,412
  • 6
  • 39
  • 57
  • I would be grateful if you could please take a look at this question for me https://stackoverflow.com/questions/51089098/how-to-clone-several-game-objects-in-a-way-that-clone-properties-of-one-can-be-a – NSSwift Oct 24 '18 at 07:22
1

Caveat: it's all down to details: general principles are nice but you're right - real data is the right thing. Unfortunately it's hard to get for Unity: I've seen reports that DotTrace works for some aspects of Unity games but that most of Unity looks like a black box to it.

A useful rule of thumb is to look for new statements. It's a rule of thumb, not a 100% scientific principle (structs are created with new but they go on the stack... mostly...) but it's a good leading indicator of possible causes of fragmentation. If you "new" something up and let if just disappear ( go out of scope, be dereferenced, etc) it will end up in the garbage collector. Moreover if you new up a batch of items and dereference some of them you'll also fragment the heap which makes the collection spikes worse as the collector tries to defragment the memory.

This is why most recommendations in this space will be to use pools, as you're already doing.

Here are some general purpose links that might be useful in tackling memory management in Unity:

http://www.gamasutra.com/blogs/WendelinReich/20131109/203841/C_Memory_Management_for_Unity_Developers_part_1_of_3.php

http://andrewfray.wordpress.com/2013/02/04/reducing-memory-usage-in-unity-c-and-netmono/

theodox
  • 12,028
  • 3
  • 23
  • 36