DarkGod

思考并回答以下问题:

大纲

  • 登录注册系统
  • 网络通信系统
  • 角色展示系统
  • 任务引导系统
  • 副本战斗系统
  • 强化升级系统
  • 资源交易系统
  • 世界聊天系统
  • 任务奖励系统

码云地址:
https://gitee.com/Insister6633/DarkGod

架构

架构图

如图所示:

  • 1、GamRoot是一个外观模式类,引用了各种子系统,子UI脚本;
  • 2、引用分两类,一类是服务模块,一类是业务系统,业务系统都继承自SystemRoot;
  • 3、业务系统管理其下的各个界面xxxWnd类,这些类都继承自WindowRoot。

脚本目录

\System\GameRoot.cs 游戏启动入口

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
using PEProtocol;
using UnityEngine;

public class GameRoot : MonoBehaviour
{
public static GameRoot Instance = null;

public LoadingWnd loadingWnd;
public DynamicWnd dynamicWnd;

private void Start()
{
Instance = this;
DontDestroyOnLoad(this);
PECommon.Log("Game Start...");

ClearUIRoot();

Init();
}

private void ClearUIRoot()
{
Transform canvas = transform.Find("Canvas");
for (int i = 0; i < canvas.childCount; i++)
{
canvas.GetChild(i).gameObject.SetActive(false);
}
}

private void Init()
{
//服务模块初始化
NetSvc net = GetComponent<NetSvc>();
net.InitSvc();
ResSvc res = GetComponent<ResSvc>();
res.InitSvc();
AudioSvc audio = GetComponent<AudioSvc>();
audio.InitSvc();
TimerSvc timer = GetComponent<TimerSvc>();
timer.InitSvc();


//业务系统初始化
LoginSys login = GetComponent<LoginSys>();
login.InitSys();
MainCitySys maincity = GetComponent<MainCitySys>();
maincity.InitSys();
FubenSys fuben = GetComponent<FubenSys>();
fuben.InitSys();
BattleSys battle = GetComponent<BattleSys>();
battle.InitSys();

dynamicWnd.SetWndState();
//进入登录场景并加载相应UI
login.EnterLogin();
}

public static void AddTips(string tips)
{
Instance.dynamicWnd.AddTips(tips);
}

private PlayerData playerData = null;

public PlayerData PlayerData
{
get
{
return playerData;
}
}

public void SetPlayerData(RspLogin data)
{
playerData = data.playerData;
}

public void SetPlayerName(string name)
{
PlayerData.name = name;
}

public void SetPlayerDataByGuide(RspGuide data)
{
PlayerData.coin = data.coin;
PlayerData.lv = data.lv;
PlayerData.exp = data.exp;
PlayerData.guideid = data.guideid;
}

public void SetPlayerDataByStrong(RspStrong data)
{
PlayerData.coin = data.coin;
PlayerData.crystal = data.crystal;
PlayerData.hp = data.hp;
PlayerData.ad = data.ad;
PlayerData.ap = data.ap;
PlayerData.addef = data.addef;
PlayerData.apdef = data.apdef;

PlayerData.strongArr = data.strongArr;
}

public void SetPlayerDataByBuy(RspBuy data)
{
PlayerData.diamond = data.dimond;
PlayerData.coin = data.coin;
PlayerData.power = data.power;
}

public void SetPlayerDataByPower(PshPower data)
{
PlayerData.power = data.power;
}

public void SetPlayerDataByTask(RspTakeTaskReward data)
{
PlayerData.coin = data.coin;
PlayerData.lv = data.lv;
PlayerData.exp = data.exp;
PlayerData.taskArr = data.taskArr;
}

public void SetPlayerDataByTaskPsh(PshTaskPrgs data)
{
PlayerData.taskArr = data.taskArr;
}

public void SetPlayerDataByFBStart(RspFBFight data)
{
PlayerData.power = data.power;
}

public void SetPlayerDataByFBEnd(RspFBFightEnd data)
{
PlayerData.coin = data.coin;
PlayerData.lv = data.lv;
PlayerData.exp = data.exp;
PlayerData.crystal = data.crystal;
PlayerData.fuben = data.fuben;
}
}

Unity光照渲染原理

  • 直接光照(Direct Lighting):光源直接照射到物体表面所以产生的光照信息。
  • 间接光照(Indirect Lighting):光源照射到物体表面以后再反射到其它物体上所形成的光照信息
  • 环境光(Ambient Lighting):太阳照射大气层,散射产生天空光。环境光本质是间接光照,因为散射的本质就是反射。
  • 全局照明(Global Illumination):直接光照加上间接光照。

UI

\DarkGod\Client\Assets\Scripts\Common\WindowRoot.cs

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/****************************************************
文件:WindowRoot.cs
作者:
邮箱:
日期:
功能:UI界面基类
*****************************************************/

using System;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class WindowRoot : MonoBehaviour
{
protected ResSvc resSvc = null;
protected AudioSvc audioSvc = null;
protected NetSvc netSvc = null;
protected TimerSvc timerSvc = null;

public void SetWndState(bool isActive = true)
{
if (gameObject.activeSelf != isActive)
{
SetActive(gameObject, isActive);
}
if (isActive)
{
InitWnd();
}
else
{
ClearWnd();
}
}

public bool GetWndState()
{
return gameObject.activeSelf;
}

protected virtual void InitWnd()
{
resSvc = ResSvc.Instance;
audioSvc = AudioSvc.Instance;
netSvc = NetSvc.Instance;
timerSvc = TimerSvc.Instance;
}

protected virtual void ClearWnd()
{
resSvc = null;
audioSvc = null;
netSvc = null;
timerSvc = null;
}

#region Tool Functions

protected void SetActive(GameObject go, bool isActive = true)
{
go.SetActive(isActive);
}

protected void SetActive(Transform trans, bool state = true)
{
trans.gameObject.SetActive(state);
}

protected void SetActive(RectTransform rectTrans, bool state = true)
{
rectTrans.gameObject.SetActive(state);
}

protected void SetActive(Image img, bool state = true)
{
img.transform.gameObject.SetActive(state);
}

protected void SetActive(Text txt, bool state = true)
{
txt.transform.gameObject.SetActive(state);
}

protected void SetText(Text txt, string context = "")
{
txt.text = context;
}

protected void SetText(Transform trans, int num = 0)
{
SetText(trans.GetComponent<Text>(), num);
}

protected void SetText(Transform trans, string context = "")
{
SetText(trans.GetComponent<Text>(), context);
}

protected void SetText(Text txt, int num = 0)
{
SetText(txt, num.ToString());
}

protected void SetSprite(Image img, string path)
{
Sprite sp = resSvc.LoadSprite(path, true);
img.sprite = sp;
}

protected T GetOrAddComponect<T>(GameObject go) where T : Component
{
T t = go.GetComponent<T>();
if (t == null)
{
t = go.AddComponent<T>();
}
return t;
}

protected Transform GetTrans(Transform trans, string name)
{
if (trans != null)
{
return trans.Find(name);
}
else
{
return transform.Find(name);
}
}
#endregion

#region Click Evts
protected void OnClick(GameObject go, Action<object> cb, object args)
{
PEListener listener = GetOrAddComponect<PEListener>(go);
listener.onClick = cb;
listener.args = args;
}

protected void OnClickDown(GameObject go, Action<PointerEventData> cb)
{
PEListener listener = GetOrAddComponect<PEListener>(go);
listener.onClickDown = cb;
}

protected void OnClickUp(GameObject go, Action<PointerEventData> cb)
{
PEListener listener = GetOrAddComponect<PEListener>(go);
listener.onClickUp = cb;
}

protected void OnDrag(GameObject go, Action<PointerEventData> cb)
{
PEListener listener = GetOrAddComponect<PEListener>(go);
listener.onDrag = cb;
}
#endregion
}

Battle

Controller

\Battle\Controller\Controller.cs 表现实体控制器抽象基类

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
using System.Collections.Generic;
using UnityEngine;

public abstract class Controller : MonoBehaviour
{
public Animator ani;
public CharacterController ctrl;
public Transform hpRoot;

protected bool isMove = false;
private Vector2 dir = Vector2.zero;

public Vector2 Dir
{
get
{
return dir;
}

set
{
if (value == Vector2.zero)
{
isMove = false;
}
else
{
isMove = true;
}
dir = value;
}
}

protected Transform camTrans;

protected bool skillMove = false;
protected float skillMoveSpeed = 0f;

protected TimerSvc timerSvc;
protected Dictionary<string, GameObject> fxDic = new Dictionary<string, GameObject>();

public virtual void Init()
{
timerSvc = TimerSvc.Instance;
}

public virtual void SetBlend(float blend)
{
ani.SetFloat("Blend", blend);
}

public virtual void SetAction(int act)
{
ani.SetInteger("Action", act);
}

public virtual void SetFX(string name, float destroy)
{

}

public void SetSkillMoveState(bool move, float skillSpeed = 0f)
{
skillMove = move;
skillMoveSpeed = skillSpeed;
}

public virtual void SetAtkRotationLocal(Vector2 atkDir)
{
float angle = Vector2.SignedAngle(atkDir, new Vector2(0, 1));
Vector3 eulerAngles = new Vector3(0, angle, 0);
transform.localEulerAngles = eulerAngles;
}

public virtual void SetAtkRotationCam(Vector2 camDir)
{
float angle = Vector2.SignedAngle(camDir, new Vector2(0, 1)) + camTrans.eulerAngles.y;
Vector3 eulerAngles = new Vector3(0, angle, 0);
transform.localEulerAngles = eulerAngles;
}
}

\Battle\Controller\MonsterController.cs 怪物表现实体角色控制器类

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
using UnityEngine;

public class MonsterController : Controller
{
private void Update()
{
// AI逻辑表现
if (isMove)
{
SetDir();

SetMove();
}
}

private void SetDir()
{
float angle = Vector2.SignedAngle(Dir, new Vector2(0, 1));
Vector3 eulerAngles = new Vector3(0, angle, 0);
transform.localEulerAngles = eulerAngles;
}

private void SetMove()
{
ctrl.Move(transform.forward * Time.deltaTime * Constants.MonsterMoveSpeed);
// 给一个向下的速度,便于在没有apply root时怪物可以落地。Fix Res Error
ctrl.Move(Vector3.down * Time.deltaTime * Constants.MonsterMoveSpeed);
}
}

\Battle\Controller\PlayerController.cs 主角表现实体角色控制器类

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
using UnityEngine;

public class PlayerController : Controller
{
public GameObject daggerskill1fx;
public GameObject daggerskill2fx;
public GameObject daggerskill3fx;

public GameObject daggeratk1fx;
public GameObject daggeratk2fx;
public GameObject daggeratk3fx;
public GameObject daggeratk4fx;
public GameObject daggeratk5fx;


private Vector3 camOffset;

private float targetBlend;
private float currentBlend;

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

camTrans = Camera.main.transform;
camOffset = transform.position - camTrans.position;

if (daggerskill1fx != null)
{
fxDic.Add(daggerskill1fx.name, daggerskill1fx);
}
if (daggeratk2fx != null)
{
fxDic.Add(daggerskill2fx.name, daggerskill2fx);
}
if (daggeratk3fx != null)
{
fxDic.Add(daggerskill3fx.name, daggerskill3fx);
}

if (daggeratk1fx != null)
{
fxDic.Add(daggeratk1fx.name, daggeratk1fx);
}
if (daggeratk2fx != null)
{
fxDic.Add(daggeratk2fx.name, daggeratk2fx);
}
if (daggeratk3fx != null)
{
fxDic.Add(daggeratk3fx.name, daggeratk3fx);
}
if (daggeratk4fx != null)
{
fxDic.Add(daggeratk4fx.name, daggeratk4fx);
}
if (daggeratk5fx != null)
{
fxDic.Add(daggeratk5fx.name, daggeratk5fx);
}
}

private void Update()
{
#region Input
/*
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");

Vector2 _dir = new Vector2(h, v).normalized;
if (_dir != Vector2.zero) {
Dir = _dir;
SetBlend(Constants.BlendMove);
}
else {
Dir = Vector2.zero;
SetBlend(Constants.BlendIdle);
}
*/
#endregion

if (currentBlend != targetBlend)
{
UpdateMixBlend();
}

if (isMove)
{
// 设置方向
SetDir();
// 产生移动
SetMove();
// 相机跟随
SetCam();
}

if (skillMove)
{
SetSkillMove();
// 相机跟随
SetCam();
}
}

private void SetDir()
{
float angle = Vector2.SignedAngle(Dir, new Vector2(0, 1)) + camTrans.eulerAngles.y;
Vector3 eulerAngles = new Vector3(0, angle, 0);
transform.localEulerAngles = eulerAngles;
}

private void SetMove()
{
ctrl.Move(transform.forward * Time.deltaTime * Constants.PlayerMoveSpeed);
}

private void SetSkillMove()
{
ctrl.Move(transform.forward * Time.deltaTime * skillMoveSpeed);
}

public void SetCam()
{
if (camTrans != null) {
camTrans.position = transform.position - camOffset;
}
}

private void UpdateMixBlend()
{
if (Mathf.Abs(currentBlend - targetBlend) < Constants.AccelerSpeed * Time.deltaTime)
{
currentBlend = targetBlend;
}
else if (currentBlend > targetBlend)
{
currentBlend -= Constants.AccelerSpeed * Time.deltaTime;
}
else
{
currentBlend += Constants.AccelerSpeed * Time.deltaTime;
}
ani.SetFloat("Blend", currentBlend);
}

//////////////////////////////////////////////////////////////////////////
public override void SetBlend(float blend)
{
targetBlend = blend;
}

public override void SetFX(string name, float destroy)
{
GameObject go;
if (fxDic.TryGetValue(name, out go))
{
go.SetActive(true);
timerSvc.AddTimeTask(
(int tid) =>
{
go.SetActive(false);
},
destroy);
}
}
}

Entity

\Battle\Entity\EntityBase.cs 逻辑实体基类

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
using System.Collections.Generic;
using UnityEngine;

public abstract class EntityBase
{
public AniState currentAniState = AniState.None;

public BattleMgr battleMgr = null;
public StateMgr stateMgr = null;
public SkillMgr skillMgr = null;
protected Controller controller = null;
private string name;

public bool canControl = true;
public bool canRlsSkill = true;


public EntityType entityType = EntityType.None;

public EntityState entityState = EntityState.None;
public string Name
{
get
{
return name;
}

set
{
name = value;
}
}

private BattleProps props;
public BattleProps Props
{
get
{
return props;
}

protected set
{
props = value;
}
}

private int hp;
public int HP
{
get
{
return hp;
}

set
{
//通知UI层TODO
PECommon.Log(Name + ": HPchange:" + hp + " to " + value);
SetHPVal(hp, value);
hp = value;
}
}

public Queue<int> comboQue = new Queue<int>();
public int nextSkillID = 0;

public SkillCfg curtSkillCfg;

//技能位移的回调ID
public List<int> skMoveCBLst = new List<int>();
//技能伤害计算回调ID
public List<int> skActionCBLst = new List<int>();

public int skEndCB = -1;


public void Born()
{
stateMgr.ChangeStatus(this, AniState.Born, null);
}
public void Move()
{
stateMgr.ChangeStatus(this, AniState.Move, null);
}
public void Idle()
{
stateMgr.ChangeStatus(this, AniState.Idle, null);
}
public void Attack(int skillID)
{
stateMgr.ChangeStatus(this, AniState.Attack, skillID);
}
public void Hit()
{
stateMgr.ChangeStatus(this, AniState.Hit, null);
}
public void Die()
{
stateMgr.ChangeStatus(this, AniState.Die, null);
}

public virtual void TickAILogic() { }

public void SetCtrl(Controller ctrl)
{
controller = ctrl;
}

public void SetActive(bool active = true)
{
if (controller != null) {
controller.gameObject.SetActive(active);
}
}

public virtual void SetBattleProps(BattleProps props)
{
HP = props.hp;
Props = props;
}

public virtual void SetBlend(float blend)
{
if (controller != null)
{
controller.SetBlend(blend);
}
}

public virtual void SetDir(Vector2 dir)
{
if (controller != null)
{
controller.Dir = dir;
}
}

public virtual void SetAction(int act)
{
if (controller != null)
{
controller.SetAction(act);
}
}

public virtual void SetFX(string name, float destroy)
{
if (controller != null)
{
controller.SetFX(name, destroy);
}
}

public virtual void SetSkillMoveState(bool move, float speed = 0f)
{
if (controller != null)
{
controller.SetSkillMoveState(move, speed);
}
}

public virtual void SetAtkRotation(Vector2 dir, bool offset = false)
{
if (controller != null)
{
if (offset)
{
controller.SetAtkRotationCam(dir);
}
else
{
controller.SetAtkRotationLocal(dir);
}
}
}

#region 战斗信息显示
public virtual void SetDodge()
{
if (controller != null)
{
GameRoot.Instance.dynamicWnd.SetDodge(Name);
}
}

public virtual void SetCritical(int critical)
{
if (controller != null)
{
GameRoot.Instance.dynamicWnd.SetCritical(Name, critical);
}
}

public virtual void SetHurt(int hurt)
{
if (controller != null)
{
GameRoot.Instance.dynamicWnd.SetHurt(Name, hurt);
}
}

public virtual void SetHPVal(int oldval, int newval)
{
if (controller != null)
{
GameRoot.Instance.dynamicWnd.SetHPVal(Name, oldval, newval);
}
}

#endregion

public virtual void SkillAttack(int skillID)
{
skillMgr.SkillAttack(this, skillID);
}

public virtual Vector2 GetDirInput()
{
return Vector2.zero;
}

public virtual Vector3 GetPos()
{
return controller.transform.position;
}

public virtual Transform GetTrans()
{
return controller.transform;
}

public AnimationClip[] GetAniClips()
{
if (controller != null)
{
return controller.ani.runtimeAnimatorController.animationClips;
}
return null;
}

public AudioSource GetAudio()
{
return controller.GetComponent<AudioSource>();
}

public CharacterController GetCC()
{
return controller.GetComponent<CharacterController>();
}

public virtual bool GetBreakState()
{
return true;
}

public virtual Vector2 CalcTargetDir()
{
return Vector2.zero;
}

public void ExitCurtSkill()
{
canControl = true;

if (curtSkillCfg != null)
{
if (!curtSkillCfg.isBreak)
{
entityState = EntityState.None;
}
//连招数据更新
if (curtSkillCfg.isCombo)
{
if (comboQue.Count > 0)
{
nextSkillID = comboQue.Dequeue();
}
else
{
nextSkillID = 0;
}
}
curtSkillCfg = null;
}
SetAction(Constants.ActionDefault);
}

public void RmvActionCB(int tid)
{
int index = -1;
for (int i = 0; i < skActionCBLst.Count; i++)
{
if (skActionCBLst[i] == tid)
{
index = i;
break;
}
}
if (index != -1)
{
skActionCBLst.RemoveAt(index);
}
}

public void RmvMoveCB(int tid)
{
int index = -1;
for (int i = 0; i < skMoveCBLst.Count; i++)
{
if (skMoveCBLst[i] == tid)
{
index = i;
break;
}
}
if (index != -1)
{
skMoveCBLst.RemoveAt(index);
}
}

public void RmvSkillCB()
{
SetDir(Vector2.zero);
SetSkillMoveState(false);

for (int i = 0; i < skMoveCBLst.Count; i++)
{
int tid = skMoveCBLst[i];
TimerSvc.Instance.DelTask(tid);
}

for (int i = 0; i < skActionCBLst.Count; i++)
{
int tid = skActionCBLst[i];
TimerSvc.Instance.DelTask(tid);
}

//攻击被中断,删除定时回调
if (skEndCB != -1)
{
TimerSvc.Instance.DelTask(skEndCB);
skEndCB = -1;
}
skMoveCBLst.Clear();
skActionCBLst.Clear();

//清空连招
if (nextSkillID != 0 || comboQue.Count > 0)
{
nextSkillID = 0;
comboQue.Clear();
battleMgr.lastAtkTime = 0;
battleMgr.comboIndex = 0;
}
}
}

\Battle\Entity\EntityMonster.cs 怪物逻辑实体

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
using UnityEngine;

public class EntityMonster : EntityBase
{

public EntityMonster()
{
entityType = EntityType.Monster;
}

public MonsterData md;

private float checkTime = 2;
private float checkCountTime = 0;

private float atkTime = 2;
private float atkCountTime = 0;

public override void SetBattleProps(BattleProps props)
{
int level = md.mLevel;

BattleProps p = new BattleProps
{
hp = props.hp * level,
ad = props.ad * level,
ap = props.ap * level,
addef = props.addef * level,
apdef = props.apdef * level,
dodge = props.dodge * level,
pierce = props.pierce * level,
critical = props.critical * level
};

Props = p;
HP = p.hp;
}

bool runAI = true;

public override void TickAILogic()
{
if (!runAI)
{
return;
}

if (currentAniState == AniState.Idle || currentAniState == AniState.Move)
{
if (battleMgr.isPauseGame)
{
Idle();
return;
}

float delta = Time.deltaTime;
checkCountTime += delta;
if (checkCountTime < checkTime)
{
return;
}
else
{
Vector2 dir = CalcTargetDir();
if (!InAtkRange())
{
SetDir(dir);
Move();
}
else
{
SetDir(Vector2.zero);
atkCountTime += checkCountTime;
if (atkCountTime > atkTime)
{
SetAtkRotation(dir);
Attack(md.mCfg.skillID);
atkCountTime = 0;
}
else {
Idle();
}
}
checkCountTime = 0;
checkTime = PETools.RDInt(1, 5) * 1.0f / 10;
}
}
}

public override Vector2 CalcTargetDir()
{
EntityPlayer entityPlayer = battleMgr.entitySelfPlayer;
if (entityPlayer == null || entityPlayer.currentAniState == AniState.Die)
{
runAI = false;
return Vector2.zero;
}
else
{
Vector3 target = entityPlayer.GetPos();
Vector3 self = GetPos();
return new Vector2(target.x - self.x, target.z - self.z).normalized;
}
}

private bool InAtkRange()
{
EntityPlayer entityPlayer = battleMgr.entitySelfPlayer;
if (entityPlayer == null || entityPlayer.currentAniState == AniState.Die)
{
runAI = false;
return false;
}
else
{
Vector3 target = entityPlayer.GetPos();
Vector3 self = GetPos();
target.y = 0;
self.y = 0;
float dis = Vector3.Distance(target, self);
if (dis <= md.mCfg.atkDis)
{
return true;
}
else
{
return false;
}
}
}

public override bool GetBreakState()
{
if (md.mCfg.isStop)
{
if (curtSkillCfg != null)
{
return curtSkillCfg.isBreak;
}
else
{
return true;
}
}
else
{
return false;
}
}

public override void SetHPVal(int oldval, int newval)
{
if (md.mCfg.mType == MonsterType.Boss)
{
BattleSys.Instance.playerCtrlWnd.SetBossHPBarVal(oldval, newval, Props.hp);
}
else
{
base.SetHPVal(oldval, newval);
}
}
}

\Battle\Entity\EntityPlayer.cs 玩家逻辑实体

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
using UnityEngine;
using System.Collections.Generic;

public class EntityPlayer : EntityBase
{

public EntityPlayer()
{
entityType = EntityType.Player;
}

public override Vector2 GetDirInput()
{
return battleMgr.GetDirInput();
}

public override Vector2 CalcTargetDir()
{
EntityMonster monster = FindClosedTarget();
if (monster != null)
{
Vector3 target = monster.GetPos();
Vector3 self = GetPos();
Vector2 dir = new Vector2(target.x - self.x, target.z - self.z);
return dir.normalized;
}
else
{
return Vector2.zero;
}
}

private EntityMonster FindClosedTarget()
{
List<EntityMonster> lst = battleMgr.GetEntityMonsters();
if (lst == null || lst.Count == 0)
{
return null;
}

Vector3 self = GetPos();
EntityMonster targetMonster = null;
float dis = 0;

for (int i = 0; i < lst.Count; i++)
{
Vector3 target = lst[i].GetPos();
if (i == 0)
{
dis = Vector3.Distance(self, target);
targetMonster = lst[0];
}
else
{
float calcDis = Vector3.Distance(self, target);
if (dis > calcDis)
{
dis = calcDis;
targetMonster = lst[i];
}
}
}
return targetMonster;
}

public override void SetHPVal(int oldval, int newval)
{
BattleSys.Instance.playerCtrlWnd.SetSelfHPBarVal(newval);
}

public override void SetDodge()
{
GameRoot.Instance.dynamicWnd.SetSelfDodge();
}
}

Manager

\Battle\Manager\BattleMgr.cs 战场管理器

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
using System;
using System.Collections.Generic;
using PEProtocol;
using UnityEngine;

public class BattleMgr : MonoBehaviour
{
private ResSvc resSvc;
private AudioSvc audioSvc;

private StateMgr stateMgr;
private SkillMgr skillMgr;
private MapMgr mapMgr;

public EntityPlayer entitySelfPlayer;
private MapCfg mapCfg;

private Dictionary<string, EntityMonster> monsterDic = new Dictionary<string, EntityMonster>();

public void Init(int mapid, Action cb = null)
{
resSvc = ResSvc.Instance;
audioSvc = AudioSvc.Instance;

//初始化各管理器
stateMgr = gameObject.AddComponent<StateMgr>();
stateMgr.Init();
skillMgr = gameObject.AddComponent<SkillMgr>();
skillMgr.Init();

//加载战场地图
mapCfg = resSvc.GetMapCfg(mapid);
resSvc.AsyncLoadScene(mapCfg.sceneName, () => {
//初始化地图数据
GameObject map = GameObject.FindGameObjectWithTag("MapRoot");
mapMgr = map.GetComponent<MapMgr>();
mapMgr.Init(this);

map.transform.localPosition = Vector3.zero;
map.transform.localScale = Vector3.one;

Camera.main.transform.position = mapCfg.mainCamPos;
Camera.main.transform.localEulerAngles = mapCfg.mainCamRote;

LoadPlayer(mapCfg);
entitySelfPlayer.Idle();

//激活第一批次怪物
ActiveCurrentBatchMonsters();

audioSvc.PlayBGMusic(Constants.BGHuangYe);
if (cb != null) {
cb();
}
});
}

public bool triggerCheck = true;
public bool isPauseGame = false;

public void Update()
{
foreach (var item in monsterDic)
{
EntityMonster em = item.Value;
em.TickAILogic();
}

//检测当前批次的怪物是否全部死亡
if (mapMgr != null)
{
if (triggerCheck && monsterDic.Count == 0)
{
bool isExist = mapMgr.SetNextTriggerOn();
triggerCheck = false;
if (!isExist)
{
//关卡结束,战斗胜利
EndBattle(true, entitySelfPlayer.HP);
}
}
}
}

public void EndBattle(bool isWin, int restHP)
{
isPauseGame = true;
AudioSvc.Instance.StopBGMusic();
BattleSys.Instance.EndBattle(isWin, restHP);
}

private void LoadPlayer(MapCfg mapData)
{
GameObject player = resSvc.LoadPrefab(PathDefine.AssissnBattlePlayerPrefab);

player.transform.position = mapData.playerBornPos;
player.transform.localEulerAngles = mapData.playerBornRote;
player.transform.localScale = Vector3.one;

PlayerData pd = GameRoot.Instance.PlayerData;
BattleProps props = new BattleProps
{
hp = pd.hp,
ad = pd.ad,
ap = pd.ap,
addef = pd.addef,
apdef = pd.apdef,
dodge = pd.dodge,
pierce = pd.pierce,
critical = pd.critical
};

entitySelfPlayer = new EntityPlayer
{
battleMgr = this,
stateMgr = stateMgr,
skillMgr = skillMgr
};
entitySelfPlayer.Name = "AssassinBattle";
entitySelfPlayer.SetBattleProps(props);

PlayerController playerCtrl = player.GetComponent<PlayerController>();
playerCtrl.Init();
entitySelfPlayer.SetCtrl(playerCtrl);
}

public void LoadMonsterByWaveID(int wave)
{
for (int i = 0; i < mapCfg.monsterLst.Count; i++)
{
MonsterData md = mapCfg.monsterLst[i];
if (md.mWave == wave)
{
GameObject m = resSvc.LoadPrefab(md.mCfg.resPath, true);
m.transform.localPosition = md.mBornPos;
m.transform.localEulerAngles = md.mBornRote;
m.transform.localScale = Vector3.one;

m.name = "m" + md.mWave + "_" + md.mIndex;

EntityMonster em = new EntityMonster
{
battleMgr = this,
stateMgr = stateMgr,
skillMgr = skillMgr
};
//设置初始属性
em.md = md;
em.SetBattleProps(md.mCfg.bps);
em.Name = m.name;

MonsterController mc = m.GetComponent<MonsterController>();
mc.Init();
em.SetCtrl(mc);

m.SetActive(false);
monsterDic.Add(m.name, em);
if (md.mCfg.mType == MonsterType.Normal)
{
GameRoot.Instance.dynamicWnd.AddHpItemInfo(m.name, mc.hpRoot, em.HP);
}
else if (md.mCfg.mType == MonsterType.Boss)
{
BattleSys.Instance.playerCtrlWnd.SetBossHPBarState(true);
}
}
}
}

public void ActiveCurrentBatchMonsters()
{
TimerSvc.Instance.AddTimeTask((int tid) => {
foreach (var item in monsterDic) {
item.Value.SetActive(true);
item.Value.Born();
TimerSvc.Instance.AddTimeTask((int id) => {
//出生1秒钟后进入Idle
item.Value.Idle();
}, 1000);
}
}, 500);
}

public List<EntityMonster> GetEntityMonsters()
{
List<EntityMonster> monsterLst = new List<EntityMonster>();
foreach (var item in monsterDic)
{
monsterLst.Add(item.Value);
}
return monsterLst;
}

public void RmvMonster(string key)
{
EntityMonster entityMonster;
if (monsterDic.TryGetValue(key, out entityMonster))
{
monsterDic.Remove(key);
GameRoot.Instance.dynamicWnd.RmvHpItemInfo(key);
}
}

#region 技能施放与角色控制

public void SetSelfPlayerMoveDir(Vector2 dir)
{
//设置玩家移动
//PECommon.Log(dir.ToString());

if (entitySelfPlayer.canControl == false)
{
return;
}

if (entitySelfPlayer.currentAniState == AniState.Idle || entitySelfPlayer.currentAniState == AniState.Move)
{
if (dir == Vector2.zero)
{
entitySelfPlayer.Idle();
}
else
{
entitySelfPlayer.Move();
entitySelfPlayer.SetDir(dir);
}
}
}

public void ReqReleaseSkill(int index)
{
switch (index)
{
case 0:
ReleaseNormalAtk();
break;
case 1:
ReleaseSkill1();
break;
case 2:
ReleaseSkill2();
break;
case 3:
ReleaseSkill3();
break;
}
}

public double lastAtkTime = 0;
private int[] comboArr = new int[] { 111, 112, 113, 114, 115 };
public int comboIndex = 0;

private void ReleaseNormalAtk()
{
//PECommon.Log("Click Normal Atk");
if (entitySelfPlayer.currentAniState == AniState.Attack)
{
//在500ms以内进行第二次点击,存数据
double nowAtkTime = TimerSvc.Instance.GetNowTime();
if (nowAtkTime - lastAtkTime < Constants.ComboSpace && lastAtkTime != 0)
{
if (comboArr[comboIndex] != comboArr[comboArr.Length - 1])
{
comboIndex += 1;
entitySelfPlayer.comboQue.Enqueue(comboArr[comboIndex]);
lastAtkTime = nowAtkTime;
}
else
{
lastAtkTime = 0;
comboIndex = 0;
}
}
}
else if (entitySelfPlayer.currentAniState == AniState.Idle || entitySelfPlayer.currentAniState == AniState.Move)
{
comboIndex = 0;
lastAtkTime = TimerSvc.Instance.GetNowTime();
entitySelfPlayer.Attack(comboArr[comboIndex]);
}
}

private void ReleaseSkill1()
{
//PECommon.Log("Click Skill1");
entitySelfPlayer.Attack(101);
}

private void ReleaseSkill2()
{
//PECommon.Log("Click Skill2");
entitySelfPlayer.Attack(102);
}

private void ReleaseSkill3()
{
//PECommon.Log("Click Skill3");
entitySelfPlayer.Attack(103);
}

public Vector2 GetDirInput()
{
return BattleSys.Instance.GetDirInput();
}

public bool CanRlsSkill()
{
return entitySelfPlayer.canRlsSkill;
}

#endregion
}

\Battle\Manager\MapMgr.cs 地图管理器

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
using UnityEngine;

public class MapMgr : MonoBehaviour
{
private int waveIndex = 1; // 默认生成第一波怪物
private BattleMgr battleMgr;
public TriggerData[] triggerArr;

public void Init(BattleMgr battle)
{
battleMgr = battle;

// 实例化第一批怪物
battleMgr.LoadMonsterByWaveID(waveIndex);

PECommon.Log("Init MapMgr Done.");
}

public void TriggerMonsterBorn(TriggerData trigger, int waveIndex)
{
if (battleMgr != null)
{
BoxCollider co = trigger.gameObject.GetComponent<BoxCollider>();
co.isTrigger = false;

battleMgr.LoadMonsterByWaveID(waveIndex);
battleMgr.ActiveCurrentBatchMonsters();
battleMgr.triggerCheck = true;
}
}

public bool SetNextTriggerOn()
{
waveIndex += 1;
for (int i = 0; i < triggerArr.Length; i++)
{
if (triggerArr[i].triggerWave == waveIndex)
{
BoxCollider co = triggerArr[i].GetComponent<BoxCollider>();
co.isTrigger = true;
return true;
}
}

return false;
}
}

\Battle\Manager\SkillMgr.cs 技能管理器

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
using System.Collections.Generic;
using UnityEngine;

public class SkillMgr : MonoBehaviour
{
private ResSvc resSvc;
private TimerSvc timeSvc;

public void Init()
{
resSvc = ResSvc.Instance;
timeSvc = TimerSvc.Instance;
PECommon.Log("Init SkillMgr Done.");
}

public void SkillAttack(EntityBase entity, int skillID)
{
entity.skMoveCBLst.Clear();
entity.skActionCBLst.Clear();

AttackDamage(entity, skillID);
AttackEffect(entity, skillID);
}

public void AttackDamage(EntityBase entity, int skillID)
{
SkillCfg skillData = resSvc.GetSkillCfg(skillID);
List<int> actonLst = skillData.skillActionLst;
int sum = 0;

for (int i = 0; i < actonLst.Count; i++)
{
SkillActionCfg skillAction = resSvc.GetSkillActionCfg(actonLst[i]);
sum += skillAction.delayTime;
int index = i;
if (sum > 0)
{
int actid = timeSvc.AddTimeTask((int tid) => {
if (entity != null) {
SkillAction(entity, skillData, index);
entity.RmvActionCB(tid);
}
}, sum);
entity.skActionCBLst.Add(actid);
}
else
{
// 瞬时技能
SkillAction(entity, skillData, index);
}
}
}

public void SkillAction(EntityBase caster, SkillCfg skillCfg, int index)
{
SkillActionCfg skillActionCfg = resSvc.GetSkillActionCfg(skillCfg.skillActionLst[index]);

int damage = skillCfg.skillDamageLst[index];

if (caster.entityType == EntityType.Monster)
{
EntityPlayer target = caster.battleMgr.entitySelfPlayer;
if (target == null)
{
return;
}
//判断距离,判断角度
if (InRange(caster.GetPos(), target.GetPos(), skillActionCfg.radius)
&& InAngle(caster.GetTrans(), target.GetPos(), skillActionCfg.angle))
{
CalcDamage(caster, target, skillCfg, damage);
}
}
else if (caster.entityType == EntityType.Player)
{
//获取场景里所有的怪物实体,遍历运算
List<EntityMonster> monsterLst = caster.battleMgr.GetEntityMonsters();
for (int i = 0; i < monsterLst.Count; i++)
{
EntityMonster em = monsterLst[i];
//判断距离,判断角度
if (InRange(caster.GetPos(), em.GetPos(), skillActionCfg.radius)
&& InAngle(caster.GetTrans(), em.GetPos(), skillActionCfg.angle))
{
CalcDamage(caster, em, skillCfg, damage);
}
}
}
}

System.Random rd = new System.Random();

private void CalcDamage(EntityBase caster, EntityBase target, SkillCfg skillCfg, int damage)
{
int dmgSum = damage;
if (skillCfg.dmgType == DamageType.AD)
{
//计算闪避
int dodgeNum = PETools.RDInt(1, 100, rd);
if (dodgeNum <= target.Props.dodge)
{
//UI显示闪避 TODO
//PECommon.Log("闪避Rate:" + dodgeNum + "/" + target.Props.dodge);
target.SetDodge();
return;
}
//计算属性加成
dmgSum += caster.Props.ad;

//计算暴击
int criticalNum = PETools.RDInt(1, 100, rd);
if (criticalNum <= caster.Props.critical)
{
float criticalRate = 1 + (PETools.RDInt(1, 100, rd) / 100.0f);
dmgSum = (int)criticalRate * dmgSum;
//PECommon.Log("暴击Rate:" + criticalNum + "/" + caster.Props.critical);
target.SetCritical(dmgSum);
}

//计算穿甲
int addef = (int)((1 - caster.Props.pierce / 100.0f) * target.Props.addef);
dmgSum -= addef;
}
else if (skillCfg.dmgType == DamageType.AP)
{
//计算属性加成
dmgSum += caster.Props.ap;
//计算魔法抗性
dmgSum -= target.Props.apdef;
}
else { }

//最终伤害
if (dmgSum < 0)
{
dmgSum = 0;
return;
}
target.SetHurt(dmgSum);

if (target.HP < dmgSum)
{
target.HP = 0;
//目标死亡
target.Die();
if (target.entityType == EntityType.Monster)
{
target.battleMgr.RmvMonster(target.Name);
}
else if (target.entityType == EntityType.Player)
{
target.battleMgr.EndBattle(false, 0);
target.battleMgr.entitySelfPlayer = null;
}

}
else
{
target.HP -= dmgSum;
if (target.entityState == EntityState.None && target.GetBreakState())
{
target.Hit();
}
}
}

private bool InRange(Vector3 from, Vector3 to, float range)
{
float dis = Vector3.Distance(from, to);
if (dis <= range)
{
return true;
}
return false;
}

private bool InAngle(Transform trans, Vector3 to, float angle)
{
if (angle == 360)
{
return true;
}
else
{
Vector3 start = trans.forward;
Vector3 dir = (to - trans.position).normalized;

float ang = Vector3.Angle(start, dir);

if (ang <= angle / 2)
{
return true;
}
return false;
}
}

/// <summary>
/// 技能效果表现
/// </summary>
public void AttackEffect(EntityBase entity, int skillID)
{
SkillCfg skillData = resSvc.GetSkillCfg(skillID);

if (!skillData.isCollide)
{
//忽略掉刚体碰撞
Physics.IgnoreLayerCollision(9, 10);
timeSvc.AddTimeTask((int tid) => {
Physics.IgnoreLayerCollision(9, 10, false);
}, skillData.skillTime);
}

if (entity.entityType == EntityType.Player)
{
if (entity.GetDirInput() == Vector2.zero)
{
Vector2 dir = entity.CalcTargetDir();
if (dir != Vector2.zero)
{
entity.SetAtkRotation(dir);
}
}
else
{
entity.SetAtkRotation(entity.GetDirInput(), true);
}
}

entity.SetAction(skillData.aniAction);
entity.SetFX(skillData.fx, skillData.skillTime);

CalcSkillMove(entity, skillData);

entity.canControl = false;
entity.SetDir(Vector2.zero);

if (!skillData.isBreak)
{
entity.entityState = EntityState.BatiState;
}

entity.skEndCB = timeSvc.AddTimeTask((int tid) => {
entity.Idle();
}, skillData.skillTime);
}

private void CalcSkillMove(EntityBase entity, SkillCfg skillData)
{
List<int> skillMoveLst = skillData.skillMoveLst;
int sum = 0;

for (int i = 0; i < skillMoveLst.Count; i++)
{
SkillMoveCfg skillMoveCfg = resSvc.GetSkillMoveCfg(skillData.skillMoveLst[i]);
float speed = skillMoveCfg.moveDis / (skillMoveCfg.moveTime / 1000f);
sum += skillMoveCfg.delayTime;

if (sum > 0)
{
int moveid = timeSvc.AddTimeTask((int tid) => {
entity.SetSkillMoveState(true, speed);
entity.RmvMoveCB(tid);
}, sum);
entity.skMoveCBLst.Add(moveid);
}
else
{
entity.SetSkillMoveState(true, speed);
}

sum += skillMoveCfg.moveTime;
int stopid = timeSvc.AddTimeTask((int tid) => {
entity.SetSkillMoveState(false);
entity.RmvMoveCB(tid);
}, sum);
entity.skMoveCBLst.Add(stopid);
}
}
}

\Battle\Manager\StateMgr.cs 状态管理器

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
using UnityEngine;
using System.Collections.Generic;

public class StateMgr : MonoBehaviour
{
private Dictionary<AniState, IState> fsm = new Dictionary<AniState, IState>();

public void Init()
{
fsm.Add(AniState.Born, new StateBorn());
fsm.Add(AniState.Idle, new StateIdle());
fsm.Add(AniState.Move, new StateMove());
fsm.Add(AniState.Attack, new StateAttack());
fsm.Add(AniState.Hit, new StateHit());
fsm.Add(AniState.Die, new StateDie());

PECommon.Log("Init StateMgr Done.");
}

public void ChangeStatus(EntityBase entity, AniState targetState, params object[] args)
{
if (entity.currentAniState == targetState)
{
return;
}

if (fsm.ContainsKey(targetState))
{
if (entity.currentAniState != AniState.None)
{
fsm[entity.currentAniState].Exit(entity, args);
}
fsm[targetState].Enter(entity, args);
fsm[targetState].Process(entity, args);
}
}
}

System

\System\BattleSys.cs 战斗业务系统

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
using PEProtocol;
using UnityEngine;

public class BattleSys : SystemRoot
{
public static BattleSys Instance = null;
public PlayerCtrlWnd playerCtrlWnd;
public BattleEndWnd battleEndWnd;
public BattleMgr battleMgr;

private int fbid;
private double startTime;

public override void InitSys()
{
base.InitSys();
Instance = this;
PECommon.Log("Init BattleSys...");
}

public void StartBattle(int mapid)
{
fbid = mapid;
GameObject go = new GameObject
{
name = "BattleRoot"
};

go.transform.SetParent(GameRoot.Instance.transform);
battleMgr = go.AddComponent<BattleMgr>();

battleMgr.Init(mapid, () => {
startTime = timerSvc.GetNowTime();
});
SetPlayerCtrlWndState();
}

public void EndBattle(bool isWin, int restHP)
{
playerCtrlWnd.SetWndState(false);
GameRoot.Instance.dynamicWnd.RmvAllHpItemInfo();

if (isWin)
{
double endTime = timerSvc.GetNowTime();
//发送结算战斗请求
//TODO
GameMsg msg = new GameMsg
{
cmd = (int)CMD.ReqFBFightEnd,
reqFBFightEnd = new ReqFBFightEnd
{
win = isWin,
fbid = fbid,
resthp = restHP,
costtime = (int)(endTime - startTime)
}
};

netSvc.SendMsg(msg);
}
else
{
SetBattleEndWndState(FBEndType.Lose);
}
}

public void DestroyBattle()
{
SetPlayerCtrlWndState(false);
SetBattleEndWndState(FBEndType.None, false);
GameRoot.Instance.dynamicWnd.RmvAllHpItemInfo();
Destroy(battleMgr.gameObject);
}

public void SetPlayerCtrlWndState(bool isActive = true)
{
playerCtrlWnd.SetWndState(isActive);
}

public void SetBattleEndWndState(FBEndType endType, bool isActive = true)
{
battleEndWnd.SetWndType(endType);
battleEndWnd.SetWndState(isActive);
}

public void RspFightEnd(GameMsg msg)
{
RspFBFightEnd data = msg.rspFBFightEnd;
GameRoot.Instance.SetPlayerDataByFBEnd(data);

battleEndWnd.SetBattleEndData(data.fbid, data.costtime, data.resthp);
SetBattleEndWndState(FBEndType.Win);
}

public void SetMoveDir(Vector2 dir)
{
battleMgr.SetSelfPlayerMoveDir(dir);
}

public void ReqReleaseSkill(int index)
{
battleMgr.ReqReleaseSkill(index);
}

public Vector2 GetDirInput()
{
return playerCtrlWnd.currentDir;
}
}
0%