Wednesday, 7 March 2018

Using Linq to count how many times an object occurs in a list


You have a list full of objects. Some of the objects are duplicates, and you want know know how many of each distinct item you have in the list.

I searched around for some answers, and I did find some StackOverflow answers that almost got me to the result, but it wasn’t quite right.

In my example, the list I want to sort is a list of custom type Run ie List<Run>(). In my code, Run is a struct that looks like:

public struct Run
{
     public string RunID;
     public string Config;
}

The StackOverflow responses were mostly long and hard-to-read Linq statements. I like Linq a lot, but it’s not always easy on the eyes, especially once you start adding extensions.

Instead, I came up with the following:

void ProcessList (List<Run> runConfigs)
{
     var grouping = runConfigs.GroupBy(o => o.Config);
     foreach (var configGroup in grouping)
     {
          string configName = configGroup.Key.ToString();   
          string count = configGroup.Count<Run>().ToString();
     }
}

Doing the above code allows me to use configName and count however I please (which in my case was outputting them to a csv).

Here’s the same example but for a List<string>():

var grouping = listOfStrings.GroupBy(x => x);
foreach (var stringGroup in grouping)
{
    string name = stringGroup.Key.ToString();
    string count = stringGroup.Count().ToString();
}

If you step through this code with the debugger, it will show that 'name' is one of the distinct values in the list, and 'count' is how many times that object appears in the list. These values can now be used however you like.

Thursday, 1 March 2018

What is dynamic batching, and why is it off by default?

While reading this tutorial, I came to a section where it said something like “as you can see, dynamic batching has stopped working”. I did not see that. In the image in the tutorial “Saved by batching” on the stats panel had dropped to 0, but my stats panel still showed a number in the 1000s.

When I checked the player settings, I noticed dynamic batching was turned off. After a bit of investigation, I learned that dynamic batching is now off by default for 3d projects as of Unity 2018.1; but why is this useful?

A mesh is the part of a 3D object that describes its shape. When certain criteria are met, Unity is able to combine meshes from different GameObjects into one big mesh before they are drawn. This is called dynamic batching. The "dynamic" part means it happens while the game is running.

Sometimes (but not always!), it takes less time to draw one big mesh than it would to draw lots of smaller meshes. Dynamic batching occurs on the CPU, and drawing meshes occurs on the GPU. You can think of dynamic batching as spending CPU time to save GPU time. This means that it becomes more likely that the game becomes CPU-bound (meaning that the frame rate is lower than you want because the CPU is taking the most time), but you should ideally want as much as possible to happen on the GPU; that’s what it’s there for.

If your game is already CPU-bound, then dynamic batching will not help. But if your game is GPU-bound (meaning that the frame rate is lower than you want because the GPU is taking the most time), then it may help.

(FYI: The GPU equivalent of dynamic batching is GPU instancing.)

For these reasons, dynamic batching is desirable for old mobile devices that don’t have a GPU (or have a bad GPU), but it is not efficient for games intended for more modern devices.

Here is a helpful article that goes into a bit more detail: Why Are My Batches (Draw Calls) So High?
Also: https://docs.unity3d.com/Manual/DrawCallBatching.html