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
It helps to have text of the code ins$$anonymous$$d of a png of the code, but I need a few things detailed before I can help.
I can say that Linq is not really suited for real time animation work - it is more of a convenience for query, not performance oriented like you need here. Your question acknowledges that, but I don't think anyone is going to squint hard enough to glean from this code and a terse description as to what you're really trying to do here.
Are all 5 lines which order playerPositions begin run for each loop through p? I can't tell exactly what playerPositions is, but is it not being reordered 5 times with the last result surviving?
Why reordered within the loop of p?
Frankly, the code is as much confusing as it is illustrative.
Zoom out and describe what you need to do, rather than ask why this code snippet isn't working out.
This phrase "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."
Ok, but what does the comparison do? Just a sorted order?
What is the larger objective(s)?
Answer by Bunny83 · Jul 22, 2018 at 12:44 AM
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[i] == 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<PlayerInput>().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.
Your answer
Follow this Question
Related Questions
assetBundle memory can not be free 0 Answers
Need help for a split screen multiplayer racing games 0 Answers
Picking up 2D collectables in an order? 0 Answers
Removing Tris/Verts/Polygons from an merged mesh? (C#) 0 Answers
reuse texture between quad 0 Answers