我们按照配置表当中的文件,使用String.Split为主要方法来把对话内容拆分出来,使用String.Replalce方法来替换角色名字

GuideWnd脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public class GuideWnd : WindowRoot
{
public TextMeshProUGUI txtName;
public TextMeshProUGUI txtTalk;
public Image imgIcon;
public Button btnNextLine;

private PlayerData pd;
private AutoGuideCfg curtTaskData;
public string[] dialogArr;
private int curDialogIndex;
protected override void InitWnd()
{
base.InitWnd();
pd = GameRoot.Instance.PlayerData;
curtTaskData = MainCitySys.Instance.GetCurtTaskData();
dialogArr = curtTaskData.dilogArr.Split('#');
curDialogIndex = 1;
SetTalk();
btnNextLine.onClick.AddListener(NextLine);
}

private void SetTalk()
{
string[] talkLine = dialogArr[curDialogIndex].Split('|');
if (talkLine[0] == "0")
{
//Palyer
SetSprite(imgIcon,PathDefine.SelfIcon);
SetText(txtName, pd.name);
}
else
{
//curNPC
switch(curtTaskData.npcID)
{
case Constants.NPCWiseMan:
SetSprite(imgIcon,PathDefine.WiseManIcon);
SetText(txtName, "Wise Man");
break;
case Constants.NPCGeneral:
SetSprite(imgIcon, PathDefine.GeneralIcon);
SetText(txtName, "General");
break;
case Constants.NPCArtisan:
SetSprite(imgIcon, PathDefine.ArtisanIcon);
SetText(txtName, "Artisan");
break;
case Constants.NPCTrader:
SetSprite(imgIcon, PathDefine.TraderIcon);
SetText(txtName, "Trader");
break;
default:
SetSprite(imgIcon, PathDefine.GuideIcon);
SetText(txtName, "Task Guide");
break;
}
}
/*imgIcon.SetNativeSize(); // 如果img组件没有开启固定宽高比,需要此方法*/
SetText(txtTalk, talkLine[1].Replace("$name",pd.name));
}
private void NextLine()
{
audioSvc.PlayUIAudio(Constants.UIClickBtn);
var length = dialogArr.Length;
curDialogIndex += 1;
if (curDialogIndex >= length)
{
// To Do 向服务器发送任务引导完成信息
SetWndState(false);
}
else
{
SetTalk();
}
}
private void OnDisable()
{
btnNextLine.onClick.RemoveAllListeners();
}
}

服务器添加CfgSvc和BaseData

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;

public class CfgSvc : SingletonPattern<CfgSvc>
{
public void Init()
{
InitGuideCfg();
PECommon.Log("CfgSvc Init Done.");
}

#region 自动引导配置
private Dictionary<int, AutoGuideCfg> guideCfgDataDic = new Dictionary<int, AutoGuideCfg>();
private void InitGuideCfg()
{
var guideCfgAsset = File.ReadAllText(@"E:\UnityProjects\Plane_DarknessWarGodLearning\Assets\Resources\ResCfgs\guide.xml");
if (guideCfgAsset != null)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(guideCfgAsset);

XmlNodeList xmlNodeList = xmlDoc.SelectSingleNode("root").ChildNodes;
for (int i = 0; i < xmlNodeList.Count; i++)
{
XmlElement ele = xmlNodeList[i] as XmlElement;
if (ele.GetAttributeNode("ID") == null)
{
continue;
}
int ID = Convert.ToInt32(ele.GetAttributeNode("ID").InnerText);

AutoGuideCfg autoGuideCfg = new AutoGuideCfg { ID = ID };

foreach (XmlElement element in ele.ChildNodes)
{
switch (element.Name)//只读取需要的数据
{
case "coin":
autoGuideCfg.coin = int.Parse(element.InnerText);
break;
case "exp":
autoGuideCfg.exp = int.Parse(element.InnerText);
break;
}
}
guideCfgDataDic.Add(ID, autoGuideCfg);
}
}
}

public AutoGuideCfg GetAutoGuideData(int ID)
{
AutoGuideCfg autoGuideCfg = null;
if (guideCfgDataDic.TryGetValue(ID, out autoGuideCfg))
{
return autoGuideCfg;
};
return null;
}
#endregion
}
1
2
3
4
5
6
7
8
9
10
public class BaseData<T> where T : BaseData<T>
{
public int ID;
}

public class AutoGuideCfg : BaseData<AutoGuideCfg>
{
public int coin;
public int exp;
}

服务器GameMsg添加引导相关数据

需要定制ReqGuideRspGuide,以及相应的CMD,同时添加可能的ErrorCode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
namespace PEProtocol
{
[System.Serializable]
public class GameMsg : PENet.PEMsg
{
//...

public ReqGuide reqGuide;
public RspGuide rspGuide;
}

#region 引导相关
[System.Serializable]
public class ReqGuide
{
public int guideid;
}
[System.Serializable]
public class RspGuide
{
public int guideid;
public int coin;//具体奖励由服务端发送,客户端不进行关键奖励的计算
public int lv;
public int exp;
}
#endregion

public enum ErrorCode
{
//...
ServerDataError = 5,//服务器与客户端数据不一致,客户端开挂,强制下线
}

public enum CMD
{
//...

//主城相关 200
ReqGuide = 200,
RspGuide = 201,
}
}

服务器添加GuideSys

注意其中的CalcExp方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
using PEProtocol;
public class GuideSys : SingletonPattern<GuideSys>
{
private CacheSvc _cacheSvc;
private CfgSvc _cfgSvc;

public void Init()
{
PECommon.Log("GuideSys Init Done");
_cacheSvc = CacheSvc.Instance;
_cfgSvc = CfgSvc.Instance;
}

public void ReqGuide(MsgPack msgPack)
{
GameMsg msg = new GameMsg()
{
cmd = (int)CMD.RspGuide
};

ReqGuide reqGuideData = msgPack.msg.reqGuide;

PlayerData pd = _cacheSvc.GetPalyerDataBySession(msgPack.session);
AutoGuideCfg autoGuideCfg = _cfgSvc.GetAutoGuideData(reqGuideData.guideid);
//更新GuideID:
if(pd.guideid == reqGuideData.guideid)//防止玩家和服务器数据不一致
{
pd.guideid += 1;
//更新玩家数据
pd.coin += autoGuideCfg.coin;
CalcExp(pd, autoGuideCfg.exp);
}
else
{
msg.err = (int)ErrorCode.ServerDataError;
}
msgPack.session.SendMsg(msg);
}

private void CalcExp(PlayerData playerData,int addExp)
{
int curLv = playerData.lv;
int curExp = playerData.exp;
int addRestExp = addExp;
while(true)
{
int upNeedExp = PECommon.GetExpUpValByLv(curLv) - curExp;
if (addRestExp >= upNeedExp)
{
curLv += 1;
curExp = 0;
addRestExp -= upNeedExp;
}
else
{
playerData.lv = curLv;
playerData.exp = curExp + addRestExp;
break;
}
}
}
}

使用一个while(true)死循环来计算升级,分两种情况

  1. 当前增加的经验值不够一次升级:角色等级不变,加上增长的经验值
  2. 当前增加的经验值足够升级:角色等级升高,升高后角色当前等级的经验值需要从零开始重新计算,在这个死循环中,经验值越大升级的程度越高

NetSvc分发ReqGuide

1
2
3
4
5
6
7
8
9
10
private void HandOutMsg(MsgPack msgPack)
{
switch((CMD)msgPack.msg.cmd)
{
//...
case CMD.ReqGuide:
GuideSys.Instance.ReqGuide(msgPack);
break;
}
}