Use Unity Editor / Window / Profiler / Deep Profile = Toggle ON when testing for Garbage Generation.
What creates garbage in Creature Unity Runtimes?
CAUSE:
Heaviest garbage generation occurs due to per-frame usage of the "new" keyword.
EXAMPLE:
Code: Select all
Example 1A)
MeshBone::computeWorldDeltaTransforms
XnaGeometry.Vector3 cur_tangent = new XnaGeometry.Vector3(calc.Item1.X, calc.Item1.Y, 0);
Exmaple 1B)
MeshBone::computeDirs
return new Tuple<XnaGeometry.Vector4, XnaGeometry.Vector4> (tangent, normal);
Example 1C)
CreatureManager::RunCreature
public void RunCreature()
{
...
for (int i = 0; i < 2; i++)
{
...
foreach (var cur_bone_packet in bones_map)
{
XnaGeometry.Vector4 cur_bone_start_pt = new XnaGeometry.Vector4(0, 0, 0, 0);
XnaGeometry.Vector4 cur_bone_end_pt = new XnaGeometry.Vector4(0, 0, 0, 0);
}
}
...
}
Instance caching. Cache and reuse the object instances that cause garbage (for example cache and reuse your custom Tuple and XnaGeometry.Vector4 instances).
COST
The current cost of garbage per frame due to using uncached instances in a simple example we've used is 26.3kB. This is significant, and can certainly be brought down to 0kB per frame. A simple glance through the code will reveal that using metada for events for example, will further add to this number (usage of foreach on all available frame_callback(s) on each frame [sidenote: using the tryTrigger could be certainly replaced with a better solution]; for now, instead of foreach, you could just use for).
Don't use foreach, and if you must, use IEnumerator with it. Using for() cycle is GC-free. There are other things to avoid like Delegates (create garbage during subscribe/unsubscribe/call), Coroutines (create garbage when called), runtime Serialization/Deserialization, object creation (described above)/Destruction, using dynamic strings (use StringBuilder instead, if you must), and others, all create garbage. Use structs instead of classes, where applicable (they are created in Stack rather than on Heap, just like other value-types - meaning they are GC-free [cause no garbage]). Also, if you find that you need multiple instances of the same object each frame, you might want to create ObjectPool for such instances.
Bottom line, use Profiler + Deep Profile to profile your code and especially optimize the code inside loops/nested loops. You can easily see the ms/kb cost of per-frame GC in the Profiler, and focus on the heavy hitters first. Also, in C# Unity, Profiler.BeginSample(“SampleName”) / Profiler.EndSample() might help to locate the exact line of code where the garbage is being created.
I've seen other animation solutions for Unity run with 0GC-hit per frame, I'm sure You can too! Best wishes, hope this can help to make Creature better.