- Home /
Order an array of classes using 2 variables (Racing game, ranking system)
I'm trying to create a ranking system for a racing game, I have an array of AI cars and a separate variable for the players car. They are stored using 'Car' class which keeps track of the individual cars lap count and waypoint count (integers) - it also holds the car ID so I know which car is which.
I then combine all the cars (AI and Player) into one array called 'racePositions', I now want to sort that array first by the lap count (highest to lowest) and then look at the waypoint count to see which car is ahead of the other if they're on the same lap count.
E.g. The unsorted version of 'racePositions' might look like: [0] car: 1, currLap = 4, currWaypoint = 12 [1] car: 2, currLap = 4, currWaypoint = 2 [2] car: 3, currLap = 2, currWaypoint = 12 [3] car: 4, currLap = 6, currWaypoint = 5
But the sorted array would look like: [0] car: 4, currLap = 6, currWaypoint = 5 [1] car: 1, currLap = 4, currWaypoint = 12 [2] car: 2, currLap = 4, currWaypoint = 2 [3] car: 3, currLap = 2, currWaypoint = 12
I'm not sure how to do the sort and I've been looking at it for so long I think I've got the coders version of writers block. I feel like the answer is staring me in the face but I just can't see it haha, any help would be much appreciated :-) Thanks
Answer by Bunny83 · Mar 22, 2019 at 06:22 PM
The easiest way is to create a linearised sorting value. The lap count is the major sorting value so the current waypoint doesn't matter if the lap count differs. Only when the lap count is the same you need to differentiate by the waypoint.
A common way is to simply muliply the lap count by the number of waypoints and add the current waypoint index (assuming counting starts at 0). This way you get a continuous value For example if you have 24 waypoints it would look like this:
// unsorted
[0] car: 1, currLap = 4, currWaypoint = 12, position = 108 (==4*24 + 12)
[1] car: 2, currLap = 4, currWaypoint = 2, position = 98 (==4*24 + 2)
[2] car: 3, currLap = 2, currWaypoint = 12, position = 60 (==2*24 + 12)
[3] car: 4, currLap = 6, currWaypoint = 5, position = 149 (==6*24 + 5)
// sorted
[0] car: 4, currLap = 6, currWaypoint = 5, position = 149 (==6*24 + 5)
[1] car: 1, currLap = 4, currWaypoint = 12, position = 108 (==4*24 + 12)
[2] car: 2, currLap = 4, currWaypoint = 2, position = 98 (==4*24 + 2)
[3] car: 3, currLap = 2, currWaypoint = 12, position = 60 (==2*24 + 12)
Instead of the number of waypoints you could also use an arbitrary multiplier as long as it's large enough (100 or 1000 for example). You can simply sort the list based on the "position". This position can be calculated on the fly. For example if you have a List<Car> cars
you can simply do:
cars.Sort((a,b)=>(a.lap*1000+a.currentWayoint).CompareTo(b.lap*1000+b.currentWayoint));
A bit cleaner would be to implement a property / getter for the position in your car class and / or let your Car class implement the IComparable interface.
Thanks for your answer, I've gone with a slight variation of your second recommendation. For anyone who wants to know, after a lot of searching I came across this answer too: https://answers.unity.com/questions/913636/ranking-system-in-racing-game.html