Linq Orderby alternative to this problem

Hello, I am currently working on a racing game which has a track divided in 3 parts and I created a function which checks all players in a list and compares them to: 1- The track number, the lap number per track, current node and the distance to next node. The only method that I found out works well in my case is the use of Linq, OrderBy. However, because I needed to check the player position every frame, I don’t know how to cache the reference and not iterate using GetComponent which allocates more memory in the heap thus calling GC more frequently. I got a lot of spikes on this function in the profiler.

playerPositions is a List of players to be ordered (gameobject type). They got Pathfinder script attached to them that calculates their position every frame.
I would be very gratefull if you could point me to a better approach to this problem without using lambda and linq perhaps.

Thanks

Sorry but watching at your code makes me shiver.

First of all why you use ToList after every linq expression? You can simply chain the IEnumerables and call ToList once at the end.

Second is the a reason why you don’t store the Pathfinder references in your List? That way you don’t need to call GetComponent at all. However if you want to keep it like that you can use Select to do the GetComponent only once per object before you do your sorting.

Next is your different sorting actions are independent from each other. Sorting the list each time will cause almost a worst case scenario as you first sort only on the percentate per node and then on the lap and then on the track. Also you currently sort it twice on “GetPath” which is completely pointless.

Now lets talk about the real weird stuff:
You iterate through the playerPositions list. In each iteration you stort the whole list you’re currently iterating over which makes absolutely no sense. Further more after each sorting you again iterate through all elements for no reason at all. There is only one playerPositions list. That means your condition

if (playerPositions *== playerPositions[p])*

is basically the same as doing
if (i == p)
assuming each player only exists once in that list. That means the whole inner loop could be replaced just by
playerPositions[p].GetComponent().PlayerPositionOnTrack = 1 + p;
As i said in the beginning you should doing the sorting only once before you iterate through the list and not each iteration. Your early exit at the beginning of your loop seems to be strange. Is it possible that an element in that list is going to be destroyed or deactivated? Are you sure you want to completely terminate the method when you find a null or deactivated element? Keep in mind that the first one could be a null element as well. Furthermore your sorting would not work if any element is actually null as GetComponent inside your sorting would cause a null reference exception. So i guess we can assume the elements are never null. Or if they can be null your code would throw exceptions as your conditions does not catch all cases.
Finally you could simplify your sorting drastically by combining your different sorting values into one linearized value. If you have a certain set max lap count you can simply combine the values into one. Even if the exact lap count is not known you can simply assum max 1000 per part. So the value would simply be
trackPart * 1000 + lap + nodePercentage
This assumes nodePercentage is a value between 0 and 1. So a player on part 2 and lap 3 with a percentage of 0.3458 would yield a value of “2003.3458”. You then can simply use the Sort method of the List class. This doesn’t require any linq enumerables to be created at all.
ps: Next time you want to include code in your question copy the text into the question, select the text and press the 101 / 010 button to mark it as code. Code inside images just makes it more difficult for us to reference your code or to post corrected / changed versions of it since we can not copy it.