Skip to main content

Lists and Linq in Unity, do it!

·684 words·4 mins

I have been using C# for many years now in game dev and I love it. Most hardcore C++ guys have always given me grief but I still think the language is beautiful! Yes yes, its memory managed but thats a whole beast unto its self. At least I don"t have to spend a week looking for an illusive overwrite or leak. But each unto their own, we all make games and in todays world, fast to market is a big deal, especially with little to no budget.

One of the great things in C# is Lists. For those of you who don"t know them, they are basically dynamic arrays with a whole host of special functions. They are wonderful things, especially for inventory systems. There is a lot of debate about if they are significantly slower than arrays but the general rule is don"t add to them in a critical update loop. Besides being able to add and remove items dynamically, you can also just bake the list to an array using ToArray(). This way you can have a list that you use to manage your stack and once you are done, you can just bake it out.

So what I want to chat about here is Linq, which is C#“s look up language for lists. I always stayed away from it, erring and my years for “Doing things the right way” but Linq used in the right way can save you a lot of time. I have started using it for my data structure look ups in things like a store front or a player inventory. So consider this problem. You have a list of type DataItem. DataItem is a class that represents anything from the store. DataItem has a type enum associated with it explaining what type it is (eg: weapon, accessory, power up). Now I want to render this list out but filter it by category. Traditionally I would do it something like below.

//*** Loop, find match and render match
for(int i=0; i<dataItems.Count; i++){
	if(dataItems[i].type == Type.Weapon){

		//*** Render
		RenderListItem(dataItems[i]);
	}	
}

Pretty standard stuff right. So this same statement in Linq could look like below

//*** Get all the items for the corrisponding type
List aItems = dataItems.FindAll(oFind => oFind.type == Type.Weapon);

//*** Loop and render
for(int i=0; i<aItems.Count; i++){

	//*** Render
	RenderListItem(aItems[i]);
}

It does not look like much of an improvement, I know but the magic is not in the simple stuff, its when you have lots of stuff you want to compare. So lets say, I want to render only the items in the store that the player does now own. The player inventory data structure is slightly different from the item catalog so you cant just use a Contains(). Usually, you have a nested loop. Loop through your catalog and then for each item loop through your inventory. Not hard, just messy. See the equivalent Linq statement below.

//*** Get all the items for the corresponding type and that is not in the players inventory
List<DataItem> aItems = dataItems.FindAll(oFind => (oFind.type == Type.Weapon) && (inventory.Find(ooFind => oFind.uid == ooFind.uid) == null));

//*** Loop and render
for(int i=0; i<aItems.Count; i++){
	
	//*** Render
	RenderListItem(aItems[i]);
}

So now you begin to see. Its like SQL for lists. That little clause in FindAll just needs to return a bool and all your logic is compiled there. FindAll() then returns another list which you could then run further Linq queries on. You can use the Find() method to return single values back. This becomes useful when you want to query the player data on some complex condition. For instance, does the player have any of the matching special sword, shield and armor sets and does that sword have over 50% durability, if so give it to me.

This has become more and more a part of my everyday coding and I hope the article helped to bring it to your attention. If you want more info on Linq"s capabilities, there are tons of site on the internets but please start to use it, it starts to simplify so much!



Roger Miller
Author
Roger Miller
With 25 years in the technology industry, 6 in XR, 10 in the game industry, and on 4 continents, Roger comes with a breadth of knowledge. He has worked with industry-leading companies such as Ogilvy One, Amazon, and Meta, been a vendor for entertainment companies such as Unity, Amazon, Disney, and HBO, created solutions for BMW and Deloitte, and been nominated for awards such as the IMGA. He has spoken at Unity Unite, is a frequent speaker at Unity User Groups all over the country, and founded the Unity User Group in Bend, OR.