使用Unity3D 自主实战开发的赛车游戏实例,关键点记录 (五)之实时排名系统

一.综述

赛车游戏的实时排名系统与上一章介绍的道路碰撞检测系统密不可分,道路检测系统用来实时记录当前的赛车位置、圈数、已完成赛道的赛车排名,赛车距监测点距离等。而这些就是排名系统所依赖的

二.排名系统需要的各项数据

首先需要一个结构体,来记录排名系统各数据,我定义了如下的排名系统信息结构体

//记录所有比赛者排位有关的信息
    private Dictionary<GameObject, PlayersCurrentRaceInfo> _allPlayersRank = null;
//记录所有比赛者的排序结果(根据_allPlayersRank来排序)
public static List<GameObject> AllPlayersRankResult = new List<GameObject>();
/// <summary>
/// Players current race info.比赛者的当前竞赛信息
/// </summary>
public class PlayersCurrentRaceInfo
{
    public GameObject Player;
    //当前名次,这个值在比赛结束前都是0,然后比如第一个人完成比赛,则此值为1,第二个人完成比赛此值为1+ 1 == 2,以此类推
    public int Rank;
    //当前的圈数
    public int CircleCount;
    //在当前圈的位置
    public int Pos;
    //距最后一个触碰点的距离
    public float Distance;
}

上述字段_allPlayersRank 会在更新位置信息的函数UpdatePosInfo和更新圈数信息的函数UpdateCircleNumInfo中进行更新,这两个函数在道路检测体检测到玩家/敌人碰撞后,会调用这两个函数
1.UpdatePosInfo函数中更新
PlayersCurrentRaceInfo.Pos//位置信息
2.UpdateCircleNumInfo函数中更新
PlayersCurrentRaceInfo.CircleCount//圈数信息
PlayersCurrentRaceInfo.Rank//当前完成赛道的排名信息,如果当前玩家/敌人尚未完成赛道,则这个值是0,如果当前玩家/敌人是第二个完成赛道的,那这个值就是1,如果当前玩家/敌人是第一个完成赛道的,那这个值就是0,以此类推
3.每隔若干毫秒准备排名时,再对所有玩家与最后一个路点的距离进行计算,并存储到PlayersCurrenRaceInfo.Distance
进行排名的这些因素,先需要按照Rank排名,然后 是CircleCount,然后是Pos,然后是Distance。

三.排名逻辑

在FixedUpdate中每隔100次排名一次

    void FixedUpdate()
    {
        if (!_bStart) {
            return;
        }
        if (_frameCount == 100) {
        //这段是用来判断当前是否逆向行驶的
            if (!CheckifThePlayerIsInWrongDirection ())
            {
                if (PlayerDirectionWrongEvent != null) {
                    PlayerDirectionWrongArgs args = new PlayerDirectionWrongArgs();
                    args.Player = _player;

                    PlayerDirectionWrongEvent.Invoke (this, args);
                }
            }
            //如果当前是竞赛模式,就排序所有玩家
            if (ConfigurationManager.Instance.CurrentGameModel == ConfigurationManager.GameModel.RacingModel) {
                RankAllPlayers();
            }
            _frameCount = 0;
        }
        else {
            _frameCount++;
        }
        if (_bStart) {
            //更新当前比赛开始时间
            GetCurrentPlayTime();
        }
    }

使用RankAllPlayer函数进行排序,代码如下:

    void RankAllPlayers()
    {
    //更新所有玩家距离他们各自最后一个碰撞过的道路监测点的距离
        UpdatePlayersDistanceFromLastCollider ();
    //加载字典中所有的玩家排次表到列表中准备排序
        List<KeyValuePair<GameObject, PlayersCurrentRaceInfo>> list = new List<KeyValuePair<GameObject, PlayersCurrentRaceInfo>> (_allPlayersRank);
    //调用Comparion自定义排序规则进行排序
        list.Sort(Comparion);
    //清空排序结果列表,准备存储最新值
        AllPlayersRankResult.Clear ();
    //将排序后的结果存储
        for (int i = 0; i < list.Count; i++) {
            AllPlayersRankResult.Add (list[i].Value.Player);
        }
        //记录游戏玩家的名次到配置文件中,方便游戏管理器随时访问显示
ConfigurationManager.Instance.RacingModeCurrentRank = AllPlayersRankResult.IndexOf (_player) + 1;
    }

//按照比较顺序对排次表中的各排名因素进行比较
    int Comparion(KeyValuePair<GameObject, PlayersCurrentRaceInfo> x, KeyValuePair<GameObject, PlayersCurrentRaceInfo> y)
    {
        int compareValue = 0;
        compareValue = x.Value.Rank.CompareTo (y.Value.Rank);
        if (compareValue != 0) {
            return (0 -compareValue);
        }
        compareValue = x.Value.CircleCount.CompareTo (y.Value.CircleCount);
        if (compareValue != 0) {
            return (0 -compareValue);
        }
        compareValue = x.Value.Pos.CompareTo (y.Value.Pos);
        if (compareValue != 0) {
            return (0 -compareValue);
        }
        compareValue = x.Value.Distance.CompareTo (y.Value.Distance);
        if (compareValue != 0) {
            return (0 -compareValue);
        }
        return (0 -compareValue);
    }

你可能感兴趣的:(unity3d,自定义排序,赛车游戏,实时排名,字典排序)