从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)

 

第九章: 任务奖励系统与副本业务系统

任务奖励系统UI资源制作

从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)_第1张图片

滑动列表选项设置技巧

给Content添加两个组件来控制滑动列表。

从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)_第2张图片

从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)_第3张图片

从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)_第4张图片

任务数据结构配置与拆分

首先给在MainCityWnd界面中添加打开TaskWnd界面的方法,然后在BaseData中添加数据配置的类型,这里有两个,一个是基本的类型,另外一个是任务完成度的类型。

public class TaskRewardCfg:BaseData
{
    public string taskName;
    public int count;
    public int exp;
    public int coin;
}

public class TaskRewardData:BaseData
{
    public int prgs;
    public bool taked;
}

任务奖励系统开发1

首先在服务器端配置任务奖励,主要在CfgSvc中进行,从xml读取任务奖励数据

public class TaskRewardCfg : BaseData
{
    public int count;
    public int exp;
    public int coin;
}

public class TaskRewardData : BaseData
{
    public int prgs;
    public bool taked;
}

    private Dictionary taskRewardDic = new Dictionary();
    private void InitTaskRewardCfg()
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(@"D:\u3dworkspace\DarkGod_第五章\Client\Assets\Resources\ResCfgs\taskreward.xml");

        XmlNodeList nodLst = doc.SelectSingleNode("root").ChildNodes;

        for (int i = 0; i < nodLst.Count; i++)
        {
            XmlElement ele = nodLst[i] as XmlElement;

            if (ele.GetAttributeNode("ID") == null)
            {
                continue;
            }
            int ID = Convert.ToInt32(ele.GetAttributeNode("ID").InnerText);
            TaskRewardCfg trc = new TaskRewardCfg
            {
                ID = ID
            };

            foreach (XmlElement e in nodLst[i].ChildNodes)
            {
                switch (e.Name)
                {
                    case "count":
                        trc.count = int.Parse(e.InnerText);
                        break;
                    case "exp":
                        trc.exp = int.Parse(e.InnerText);
                        break;
                    case "coin":
                        trc.coin = int.Parse(e.InnerText);
                        break;
                }
            }
            taskRewardDic.Add(ID, trc);
        }
        PECommon.Log("TaskRewardCfg Init Done.");
    }
    public TaskRewardCfg GetTaskRewardData(int id)
    {
        TaskRewardCfg agc = null;
        if (taskRewardDic.TryGetValue(id, out agc))
            return agc;
        return null;
    }

任务奖励系统开发2

给玩家数据添加一个任务数组,用来表示任务的完成情况

        public string[] taskArr;

在数据库中进行添加和进行初始化化

                    #region Task Arr
                    //任务完成情况 任务编号|完成情况|是否接任务
                    //1|0|0#2|0|0#4|0|0#  
                    string[] taskStrArr = reader.GetString("task").Split('#');
                    playerData.taskArr = new string[6];
                    for(int i = 0;i=5)
                        {
                            playerData.taskArr[i] = taskStrArr[i];
                        }
                        else
                        {
                            throw new Exception("DataError");
                        }
                    }
                    #endregion

从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)_第5张图片

任务奖励系统开发3

在服务器端DBMgr处理好taskAR的添加和查询,然后在数据库的表中添加task一栏。

新建一个TaskSys,用来处理服务器端Task的一些操作。

class TaskSys
{
    private static TaskSys instance = null;
    public static TaskSys Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new TaskSys();
            }
            return instance;
        }
    }
    private CacheSvc cacheSvc = null;

    public void Init()
    {
        cacheSvc = CacheSvc.Instance;
        PECommon.Log("TaskSys Init Done.");
    }
}

任务奖励系统开发4

在客户端解析任务奖励配置

    private Dictionary taskRewardDic = new Dictionary();
    private void InitTaskRewardCfg(string path)
    {
        TextAsset xml = Resources.Load(path);
        if (!xml)
        {
            PECommon.Log("xml file:" + path + " not exist", LogType.Error);
        }
        else
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml.text);

            XmlNodeList nodLst = doc.SelectSingleNode("root").ChildNodes;

            for (int i = 0; i < nodLst.Count; i++)
            {
                XmlElement ele = nodLst[i] as XmlElement;

                if (ele.GetAttributeNode("ID") == null)
                {
                    continue;
                }
                int ID = Convert.ToInt32(ele.GetAttributeNode("ID").InnerText);
                TaskRewardCfg trc = new TaskRewardCfg
                {
                    ID = ID
                };

                foreach (XmlElement e in nodLst[i].ChildNodes)
                {
                    switch (e.Name)
                    {
                        case "taskName":
                            trc.taskName = e.InnerText;
                            break;
                        case "count":
                            trc.count = int.Parse(e.InnerText);
                            break;
                        case "coin":
                            trc.coin = int.Parse(e.InnerText);
                            break;
                        case "exp":
                            trc.exp = int.Parse(e.InnerText);
                            break;
                    }
                }
                taskRewardDic.Add(ID, trc);
            }
        }
    }
    public TaskRewardCfg GetTaskRewardCfg(int id)
    {
        TaskRewardCfg agc = null;
        if (taskRewardDic.TryGetValue(id, out agc))
            return agc;
        return null;
    }

然后完善TaskWnd

using PEProtocol;
using System.Collections.Generic;
using UnityEngine;

public class TaskWnd : WindowRoot
{
    private PlayerData pd = null;
    private List trdLst = new List();
    protected override void InitWnd()
    {
        base.InitWnd();
        pd = GameRoot.Instance.PlayerData;
        RefreshUI();
    }

    private void RefreshUI()
    {
        trdLst.Clear();

    }
}

任务奖励系统开发5

完善RefreshUI方法,根据xml中的任务配置进行任务显示

    private void RefreshUI()
    {
        trdLst.Clear();

        List todoLst = new List();
        List doneLst = new List();

        //1|0|0
        for(int i = 0;i

从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)_第6张图片

任务奖励系统开发6

完善实例化的方法,把任务的详细信息进行显示

        //实例化
        for(int i =0;i();
            float prgVal = trd.prgs * 1.0f / trf.count;
            imgPrg.fillAmount = prgVal;
        }

任务奖励系统开发7

继续完善该方法,用来控制任务按钮点击的显示

            //代码控制点击事件
            Button btnTake = GetTrans(go.transform, "btnTake").GetComponent

下面是其他的方法

    private void ClickTakeBtn(string name)
    {
        Debug.Log("Name:"+name);
        //TODO
    }

    public void ClickCloseBtn()
    {
        SetWndState(false);
    }

从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)_第7张图片

任务奖励系统开发8

首先修改之前的一个BUG,每次创建预制体之前先要删除之前的预制体。

从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)_第8张图片

在GameMsg中添加上发送和接收任务奖励消息的类

    [Serializable]
    public class ReqTaskReward
    {
        public int rid;
    }

    [Serializable]
    public class RspTaskReward
    {
        //TODO
    }

客户端的点击完成任务按钮后,需要向服务器端发送信息,然后得到金币和经验值的信息

    private void ClickTakeBtn(string name)
    {
        Debug.Log("Name:"+name);

        string[] nameArr = name.Split('_');
        int index = int.Parse(nameArr[1]);
        GameMsg msg = new GameMsg
        {
            cmd=(int)CMD.ReqTaskReward,
            reqTaskReward = new ReqTaskReward
            {
                rid = trdLst[index].ID
            }
        };
        netSvc.SendMsg(msg);

        TaskRewardCfg trc = resSvc.GetTaskRewardCfg(trdLst[index].ID);
        int coin = trc.coin;
        int exp = trc.exp;
        GameRoot.AddTips(Constants.Color("获得奖励:", TxtColor.Blue) + Constants.Color(" 金币 +" + coin + " 经验 " + exp, TxtColor.Green));
    }

任务奖励系统开发9

服务器端对拿到的信息进行处理,首先需要拿到任务详情和任务完成情况

    public void ReqTaskReward(MsgPack pack)
    {
        ReqTaskReward data = pack.msg.reqTaskReward;

        GameMsg msg = new GameMsg
        {
            cmd = (int)CMD.RspTaskReward
        };

        PlayerData pd = cacheSvc.GetPlayerDataBySession(pack.session);

        TaskRewardCfg trc = cfgSvc.GetTaskRewardCfg(data.rid);
        TaskRewardData trd = CalcTaskRewardData(pd, data.rid);
    }

    public TaskRewardData CalcTaskRewardData(PlayerData pd,int rid)
    {
        TaskRewardData trd = null;
        for(int i=0;i

任务奖励系统开发10

完成任务后,在服务器端对数据进行添加后发送给客户端

        if(trd.prgs == trc.count&&trd.taked == false)
        {        
            pd.coin += trc.coin;
            PECommon.CalcExp(pd, trc.exp);
            trd.taked = true;
            //更新任务进度数据
            CalcTaskArr(pd, trd);

            if(!cacheSvc.UpdatePlayerData(pd.id,pd))
            {
                msg.err = (int)ErrorCode.UpdateDBError;
            }
            else
            {
                RspTaskReward rspTaskReward = new RspTaskReward
                {
                    coin = pd.coin,
                    lv=pd.lv,
                    exp = pd.exp,
                    taskArr = pd.taskArr
                };
                msg.rspTaskReward = rspTaskReward;
            }
        }
        else
        {
            msg.err = (int)ErrorCode.ClientDataError;
        }
        pack.session.SendMsg(msg);

其中需要有修改字符串数据TaskArr的方法

    public void CalcTaskArr(PlayerData pd,TaskRewardData trd)
    {
        string result = trd.ID + "|" + trd.prgs + (trd.taked ? 1 : 0);
        //查找索引号
        int index = -1;
        for(int i = 0;i

任务进度检测逻辑1

首先需要在引导系统中检测是否是该任务,然后更新进度

从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)_第9张图片

    public void CalcTaskPrgs(PlayerData pd,int tid)
    {
        TaskRewardData trd = CalcTaskRewardData(pd, tid);
        TaskRewardCfg trc = cfgSvc.GetTaskRewardCfg(tid);

        if(trd.prgs < trc.count)
        {
            trd.prgs += 1;
            //更新任务进度
            CalcTaskArr(pd, trd);


        }
    }

任务进度检测逻辑2

新增一个发送进度消息的类

    [Serializable]
    public class PshPower
    {
        public int power;
    }

TaskSys中的计算进度函数在计算完成后需要发送消息到客户端

    public void CalcTaskPrgs(PlayerData pd,int tid)
    {
        TaskRewardData trd = CalcTaskRewardData(pd, tid);
        TaskRewardCfg trc = cfgSvc.GetTaskRewardCfg(tid);

        if(trd.prgs < trc.count)
        {
            trd.prgs += 1;
            //更新任务进度
            CalcTaskArr(pd, trd);

            ServerSession session = cacheSvc.GetOnlineServersession(pd.id);
            if(session!=null)
            {
                session.SendMsg(new GameMsg
                {
                    cmd = (int)CMD.PshTaskPrgs,
                    pshTaskPrgs = new PshTaskPrgs
                    {
                        taskArr = pd.taskArr
                    }
                });
            }
        }
    }

在服务器端合适的地方调用这些函数,任务点

从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)_第10张图片

从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)_第11张图片

从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)_第12张图片

从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)_第13张图片

客户端进度显示更新

在客户端添加接收任务奖励消息的方法

从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)_第14张图片

    public void RspTaskReward(GameMsg msg)
    {
        RspTaskReward data = msg.rspTaskReward;
        GameRoot.Instance.SetPlayerDataByTask(data);

        taskWnd.RefreshUI();
        maincityWnd.RefreshUI();
    }

    public void PshTaskPrgs(GameMsg msg)
    {
        PshTaskPrgs data = msg.pshTaskPrgs;
        GameRoot.Instance.SetPlayerDataByTaskPrgs(data);
    }

我们强化升级一次,可以看到下面的情况 

从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)_第15张图片

副本选择界面UI资源

从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)_第16张图片

拆分副本业务系统

创建新的系统副本系统FubenSys来管理FubenWnd

using UnityEngine;

public class FubenWnd : WindowRoot
{
    protected override void InitWnd()
    {
        base.InitWnd();
    }

    public void ClickCloseBtn()
    {
        audioSvc.PlayUIAudio(Constants.UIClickBtn);
        SetWndState(false);
    }
}
using UnityEngine;

public class FubenSys : SystemRoot 
{
    public static FubenSys Instance = null;

    public FubenWnd fubenWnd;

    public override void InitSys()
    {
        base.InitSys();

        Instance = this;
        PECommon.Log("Init FubenSys...");
    }

    public void EnterFuben()
    {
        OpenFubenWnd();
    }

    #region Fuben Wnd
    public void OpenFubenWnd()
    {
        fubenWnd.SetWndState();
    }
    #endregion
}

对接任务引导

在主城引导系统中添加任务对接

从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)_第17张图片

在打开其他页面的同时,最后暂停导航

从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)_第18张图片

服务器副本数据定义

数据库中添加副本一栏,用来表示已经处于的副本数

副本关卡显示控制

本节根据上面的fuben来显示关卡

    public Button[] fbBtnArr;
    private PlayerData pd;
    public Transform pointerTrans;

    public void RefreshUI()
    {
        int fbid = pd.fuben;
        for(int i = 0;i

我们将数据库中的fuben设置为1002,运行可以看到下面的结果

从0开始的网游ARPG实战案例:暗黑战神(第九章:任务奖励系统与副本业务系统)_第19张图片

你可能感兴趣的:(ARPG实战)