I have 1000 floats… I want to rank them.
How?
You’ll have to be more specific. What do you mean by “rank”?
Do you mean sort them? As in from smallest to largest?
Hi thanks.
So here is the deal…
I have a racing game… only 3 players, but I am trying to build it out so it could handle 3 million if needed…
As such, anyone one player can be in any position of 1, 2, or 3 at any time…
I am debating having each player watch the other players, and if two are in front, he is in third…
… the other method that I am struggling with is having one manager, watch each and then juggle trying to figure out, player x is in position 1, 2, or three…
I think I am going to go with the latter if unless you have any other suggestions.
!!!
Cheers!
You’ll need to pick a frame of reference to rank the players by. In most racing games, this is done using the player’s distance on the track (either furthest away from the start line or closest to the finish line).
Sort the list of players by their track distance, and you’ve got your answer.
EDIT: I understand that you want this to be perfectly scalable to an infinite number of players, but
a) Realistically speaking, this isn’t going to happen. Most multiplayer games don’t support more than 8 players.
b) Even MMOs with “hundreds” of players are still subdivided in such a way that player management isn’t cumbersome. And sorting “hundreds” still won’t cause a significant performance loss.
If you really needed to because you really do have millions of people, you could spread out the sorting algorithm over several frames. But like I said, that realistically won’t happen. No need to make the work harder than it has to be.
Hi, I am using this as a solution if anyone is interested…
Ir works fine for a 3 player system… but where I am puzzled is to get it working on an infinite number system…
Cheers
#region ranking
List <Transform> players_tf;
bool isGo;
void set_opponents(){
Transform tf_ = tf_player_local;
players_tf.Add (tf_);
tf_ = ComputerPlayer_Mng.instance.tf_player_local;
players_tf.Add (tf_);
tf_ = PlayerController.instance.tf_player_local;
players_tf.Add (tf_);
isGo = true;
}
void Update(){
///for ranking......
if (isGo) {
//player local is always 0...
int rank = 1;
float z_local = players_tf[0].position.z;
float z_player2 = players_tf [1].position.z;
float z_player3 = players_tf [2].position.z;
if (z_local < z_player2) {
rank++;
}
if (z_local < z_player3) {
rank++;
}
tu_rank.setText (rank.ToString ());
}
}
#endregion
Use List.Sort() if you want to do it in-place, or (with linq) use List.OrderBy() to give you a new list.
e.g.
List<Player> players = new List<Player>();
// ... populate the list...
var rankedList = players.OrderBy(p => p.transform.position.z);
Now all you need to do is loop through rankedList and print the name of the players out.
Yah, the issue was this…
for(int i = 0; i < players.Count; i++){
///here I gather each players z position and store it in a list.
}
//sort said list...
zPosList.Sort();
///now the issue is, how do I get the player, associated with the new order?
If you use List, then yes, you’ve lost the association between players and their transforms.
So you need to keep a list of player gameobjects, or some MonoBehaviour-derived class. Or create a temporary struct to maintain that transform-player association.
For example’s sake, here’s how a temporary struct could be used (although it’s overkill here):
class SomeRaceManager
{
// Populate this somewhere in your game
static public List<GameObject> Players;
}
struct SortContainer
{
public string name;
public Transform t;
}
void SortPlayers()
{
List<SortContainer> listToSort = new List<SortContainer>();
foreach (var player in SomeRaceManager.Players)
{
listToSort.Add(new SortContainer()
{
name = player.name,
t = player.transform
});
}
// Create new sorted list
var sortedList = listToSort.OrderBy(container => container.t.position.z).ToList();
PrintPlayerRanks(sortedList);
// Or... do it in-place
listToSort.Sort((a,b) => a.t.position.z.CompareTo(b.t.position.z) );
PrintPlayerRanks(listToSort);
}
void PrintPlayerRanks(List<SortContainer> players)
{
for (int i = 0; i < players.Count; ++i)
Debug.Log(string.Format("Rank: {0}, Name: {1}", i + 1, players[i].name));
}
I highly recommend that you let your RaceManager handle the sorting and ranking logic, and just let the players query the RaceManager for their current rank.
Let me just repeat that in this example, the temporary struct is overkill when you’ve got a List available in SomeRaceManager, ready and waiting to be used for sorting. Just use OrderBy if you don’t want to mess with the original list.
Yes, I actually thought of this last night. Maybe we are connected thru the cosmos… honestly should have thought of that earlier.
Cheers