魔剑之刃

思考并回答以下问题:

  • Func()委托的第几个参数是返回值?为什么又自定义自己的MyFunc()委托?怎么定义?
  • 对象池为什么使用Queue数据结构?

设计图

Util

\Public\Common\Util\MyActionAndFunc.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DashFire
{
public delegate void MyAction();
public delegate void MyAction<T1>(T1 t1);
...

public delegate R MyFunc<out R>();
public delegate R MyFunc<T1,out R>(T1 t1);
...
}

\Public\Common\Util\ObjectPool.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
using System;
using System.Collections.Generic;

namespace DashFire
{
public interface IPoolAllocatedObject<T> where T : IPoolAllocatedObject<T>, new()
{
void InitPool(ObjectPool<T> pool);
// Downcast 向下转换
T Downcast();
}

// ObjectPool并没有继承IPoolAllocatedObject,那个冒号是T的类型约束
public class ObjectPool<T> where T : IPoolAllocatedObject<T>, new()
{
// 维护一个队列,对这个队列进行操作
private Queue<T> m_UnusedObjects = new Queue<T>();

// 初始化队列,给队列填满对象
public void Init(int initPoolSize)
{
// 入列
for (int i = 0; i < initPoolSize; ++i)
{
T t = new T();
t.InitPool(this);
m_UnusedObjects.Enqueue(t);
}
}

// 申请对象实例
public T Alloc()
{
// 出列一个对象
if (m_UnusedObjects.Count > 0)
return m_UnusedObjects.Dequeue();
else
{
// 扩展
T t = new T();
if (null != t)
{
t.InitPool(this);
}
return t;
}
}

// 回收对象
public void Recycle(IPoolAllocatedObject<T> t)
{
if (null != t)
{
m_UnusedObjects.Enqueue(t.Downcast());
}
}

// 未使用的对象数量
public int Count
{
get
{
return m_UnusedObjects.Count;
}
}
}
}

Triggers

\Public\GfxModule\Skill\Trigers\ColliderScript.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
using UnityEngine;

// 需要挂载到游戏物体上,继承MonoBehaviour是为了自动触发某些函数
// 维护3个委托,提供设置和执行方法
public class ColliderScript : MonoBehaviour
{
// 维护了3个委托,其中两个方法的参数是Collider类型的对象
private DashFire.MyAction<Collider> m_OnTriggerEnter;
private DashFire.MyAction<Collider> m_OnTriggerExit;
private DashFire.MyAction m_OnDestroy;

// 给三个委托设置方法

// 参数是方法
public void SetOnTriggerEnter(DashFire.MyAction<Collider> onEnter)
{
m_OnTriggerEnter += onEnter;
}

public void SetOnTriggerExit(DashFire.MyAction<Collider> onExit)
{
m_OnTriggerExit += onExit;
}

public void SetOnDestroy(DashFire.MyAction onDestroy)
{
m_OnDestroy += onDestroy;
}

// end

// 销毁时自动调用,执行委托
void OnDestroy()
{
if (m_OnDestroy != null)
{
m_OnDestroy();
}
}

// 触发开始时自动调用,执行委托
internal void OnTriggerEnter(Collider collider)
{
if (null != m_OnTriggerEnter)
{
m_OnTriggerEnter(collider);
}
}

// 触发结束时自动调用,执行委托
internal void OnTriggerExit(Collider collider)
{
if (null != m_OnTriggerExit)
{
m_OnTriggerExit(collider);
}
}
}

\Public\GfxModule\Skill\Trigers\TriggerUtil.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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

namespace GfxModule.Skill.Triggers
{
public class TriggerUtil
{
private static float m_RayCastMaxDistance = 50;
private static int m_TerrainLayer = 1 << 16;
private static int m_CurCameraControlId = 0;
private static bool m_IsMoveCameraTriggerControl = false;

public static int CAMERA_CONTROL_FAILED = -1;
public static int CAMERA_NO_ONE_CONTROL = 0;
public static int CAMERA_CONTROL_START_ID = 1;

public static void OnFingerDown(DashFire.GestureArgs e)
{
if(DashFire.LogicSystem.PlayerSelfInfo != null)
{
DashFire.LogicSystem.PlayerSelfInfo.IsTouchDown = true;
}
}
}
}

\Public\GfxModule\Skill\Trigers\ColliderTriggerUtility.cs 把ColliderScript组件添加到对象

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
359
360
361
362
363
364
365
366
367
368
369
370
using System;
using System.Collections.Generic;
using UnityEngine;

namespace GfxModule.Skill.Triggers
{
public enum ColliderType
{
kSceneCollider,
kBoneCollider,
kSceneBoxCollider,
kBoneBoxCollider
}

// Collider附着的对象的信息
public class AttachConfig
{
public bool IsAttachEnemy;
public string AttachNodeName;
public Vector3 AttachRotation;
public int AttachImpact;
public int AttachImpactTime;
public int FallImpact;
public int FallImpactTime;
public int FinalImpact;
public int FinalImpactTime;

public AttachConfig()
{
IsAttachEnemy = false;
AttachNodeName = "";
AttachRotation = new Vector3(0, 0, 0);
AttachImpact = 0;
AttachImpactTime = -1;
FallImpact = 0;
FallImpactTime = -1;
FinalImpact = 0;
FinalImpactTime = -1;
}
}

// 当对一个类应用sealed修饰符时,此修饰符会阻止其他类从该类继承
internal sealed class ColliderTriggerInfo
{
private ColliderType m_ColliderType = ColliderType.kSceneCollider;
private string m_Prefab = "";
private Vector3 m_Position;
private string m_Bone = "";
private bool m_IsAttach = false;

private AttachConfig m_AttachConfig = new AttachConfig();

private Vector3 m_Size;
private Quaternion m_Eular;
private bool m_IsShow = false;
private Dictionary<BeHitState, StateImpact> m_StateImpacts = new Dictionary<BeHitState, StateImpact>(); // 枚举 => 包含此枚举的对象
private Dictionary<int, string> m_CollideLayerHandler = new Dictionary<int, string>();

private GameObject m_Collider = null;

// 克隆
public ColliderTriggerInfo Clone()
{
ColliderTriggerInfo copy = new ColliderTriggerInfo();
copy.m_ColliderType = m_ColliderType;
copy.m_Prefab = m_Prefab;
copy.m_Position = m_Position;
copy.m_Bone = m_Bone;
copy.m_IsAttach = m_IsAttach;
copy.m_AttachConfig = m_AttachConfig;

copy.m_Size = m_Size;
copy.m_Eular = m_Eular;
copy.m_IsShow = m_IsShow;
copy.m_StateImpacts = m_StateImpacts;
copy.m_CollideLayerHandler = m_CollideLayerHandler;
m_Collider = null;
return copy;
}

/// <summary>
/// 对外提供的创建触发器的接口
/// 又调用了私有的CreateSceneOrBoneCollider方法
/// </summary>
/// <param name="obj"></param>
/// <param name="liveTime"></param>
/// <param name="onTriggerEnter"></param>
/// <param name="onTriggerExit"></param>
/// <param name="onDestroy"></param>
public void CreateTriger(GameObject obj, float liveTime, object onTriggerEnter,
object onTriggerExit, object onDestroy)
{
switch(m_ColliderType)
{
case ColliderType.kSceneCollider:
case ColliderType.kBoneCollider:
CreateSceneOrBoneCollider(obj, liveTime, onTriggerEnter, onTriggerExit);
break;

case ColliderType.kSceneBoxCollider:
case ColliderType.kBoneBoxCollider:
CreateBoxCollider(obj, liveTime, onTriggerEnter, onTriggerExit, onDestroy);
break;
}
}

public void Load(List<ScriptableData.ISyntaxComponent> statements)
{
foreach (ScriptableData.ISyntaxComponent statement in statements)
{
ScriptableData.CallData stCall = statement as ScriptableData.CallData;
if (null != stCall)
{
if (stCall.GetId() == "scenecollider")
{
LoadSceneColliderConfig(stCall);
}
else if (stCall.GetId() == "bonecollider")
{
LoadBoneColliderConfig(stCall);
}
else if (stCall.GetId() == "stateimpact")
{
LoadStateImpactConfig(stCall);
}
else if (stCall.GetId() == "sceneboxcollider")
{
LoadSceneBoxColliderConfig(stCall);
}
else if (stCall.GetId() == "boneboxcollider")
{
LoadBoneBoxColliderConfig(stCall);
}
else if (stCall.GetId() == "oncollidelayer")
{
LoadCollideLayerConfig(stCall);
}
else if (stCall.GetId() == "attachenemy")
{
LoadAttachEnemyConfig(stCall);
}
}
}
}

public Dictionary<BeHitState, StateImpact> GetStateImpacts()
{
return m_StateImpacts;
}

public string GetCollideLayerMessage(int layer)
{
string message = "";
m_CollideLayerHandler.TryGetValue(layer, out message);
return message;
}

public AttachConfig GetAttachConfig()
{
return m_AttachConfig;
}

public GameObject GetCollider()
{
return m_Collider;
}

public string Prefab
{
get { return m_Prefab; }
}

/// <summary>
///
/// </summary>
/// <param name="obj">需要添加Trigger的对象</param>
/// <param name="liveTime">此对象的生存时间</param>
/// <param name="onTriggerEnter">给对象的ColliderScript组件对象的m_OnTriggerEnter委托添加的方法</param>
/// <param name="onTriggerExit">给对象的ColliderScript组件对象的m_OnTriggerExit委托添加的方法</param>
private void CreateSceneOrBoneCollider(GameObject obj, float liveTime,
object onTriggerEnter,
object onTriggerExit)
{
GameObject collider_obj = DashFire.ResourceSystem.NewObject(m_Prefab, liveTime) as GameObject;

if (null == collider_obj)
{
Debug.LogError("------create collider failed! " + m_Prefab);
return;
}
m_Collider = collider_obj;
Transform[] transes = collider_obj.GetComponentsInChildren<Transform>();

foreach(Transform child in transes)
{
child.gameObject.SendMessage("SetOnTriggerEnter", onTriggerEnter, SendMessageOptions.DontRequireReceiver);
child.gameObject.SendMessage("SetOnTriggerExit", onTriggerExit, SendMessageOptions.DontRequireReceiver);
}

if (m_ColliderType == ColliderType.kSceneCollider)
{
Vector3 pos = obj.transform.position + obj.transform.rotation * m_Position;
collider_obj.transform.position = pos;
}
else
{
Transform node = TriggerUtil.GetChildNodeByName(obj, m_Bone);
if (node != null)
{
collider_obj.transform.parent = node;
collider_obj.transform.localPosition = Vector3.zero;
collider_obj.transform.localRotation = Quaternion.identity;
if (!m_IsAttach)
{
collider_obj.transform.parent = null;
}
}
}
}

private void CreateBoxCollider(GameObject obj, float liveTime, object onTriggerEnter,
object onTriggerExit, object onDestroy)
{
GameObject collider = GameObject.CreatePrimitive(PrimitiveType.Cube);
collider.transform.localScale = m_Size;
BoxCollider boxcollider = collider.GetComponent<BoxCollider>();

if (boxcollider != null)
{
boxcollider.isTrigger = true;
}
collider.layer = LayerMask.NameToLayer("SceneObj");;
Rigidbody rigidbody = collider.AddComponent<Rigidbody>();
rigidbody.useGravity = false;
ColliderScript cs = collider.AddComponent<ColliderScript>();

if (cs != null)
{
cs.SetOnTriggerEnter((DashFire.MyAction<Collider>)onTriggerEnter);
cs.SetOnTriggerExit((DashFire.MyAction<Collider>)onTriggerExit);
cs.SetOnDestroy((DashFire.MyAction)(onDestroy));
}
if (!m_IsShow)
{
MeshRenderer mesh = collider.GetComponent<MeshRenderer>();
if (mesh != null)
{
GameObject.Destroy(mesh);
}
}

if (m_ColliderType == ColliderType.kBoneBoxCollider)
{
Transform child = TriggerUtil.GetChildNodeByName(obj, m_Bone);
if (child != null) {
collider.transform.parent = child;
} else {
Debug.LogError("not find bone " + m_Bone);
}
}
else
{
collider.transform.parent = obj.transform;
}

collider.transform.localPosition = m_Position;
collider.transform.localRotation = m_Eular;
if (!m_IsAttach)
{
collider.transform.parent = null;
}
m_Collider = collider;
GameObject.Destroy(collider, liveTime);
}

private void LoadSceneColliderConfig(ScriptableData.CallData stCall)
{
if (stCall.GetParamNum() >= 2)
{
m_ColliderType = ColliderType.kSceneCollider;
m_Prefab = stCall.GetParamId(0);
ScriptableData.CallData param1 = stCall.GetParam(1) as ScriptableData.CallData;
if (null != param1)
m_Position = ScriptableDataUtility.CalcVector3(param1);
}
}

private void LoadBoneColliderConfig(ScriptableData.CallData stCall)
{
if (stCall.GetParamNum() >= 3)
{
m_ColliderType = ColliderType.kBoneCollider;
m_Prefab = stCall.GetParamId(0);
m_Bone = stCall.GetParamId(1);
m_IsAttach = bool.Parse(stCall.GetParamId(2));
}
}

private void LoadSceneBoxColliderConfig(ScriptableData.CallData stCall)
{
m_ColliderType = ColliderType.kSceneBoxCollider;
if (stCall.GetParamNum() >= 5)
{
m_Size = ScriptableDataUtility.CalcVector3(stCall.GetParam(0) as ScriptableData.CallData);
m_Position = ScriptableDataUtility.CalcVector3(stCall.GetParam(1) as ScriptableData.CallData);
m_Eular = ScriptableDataUtility.CalcEularRotation(stCall.GetParam(2) as ScriptableData.CallData);
m_IsAttach = bool.Parse(stCall.GetParamId(3));
m_IsShow = bool.Parse(stCall.GetParamId(4));
}
}

private void LoadBoneBoxColliderConfig(ScriptableData.CallData stCall)
{
m_ColliderType = ColliderType.kBoneBoxCollider;
if (stCall.GetParamNum() >= 6)
{
m_Size = ScriptableDataUtility.CalcVector3(stCall.GetParam(0) as ScriptableData.CallData);
m_Bone = stCall.GetParamId(1);
m_Position = ScriptableDataUtility.CalcVector3(stCall.GetParam(2) as ScriptableData.CallData);
m_Eular = ScriptableDataUtility.CalcEularRotation(stCall.GetParam(3) as ScriptableData.CallData);
m_IsAttach = bool.Parse(stCall.GetParamId(4));
m_IsShow = bool.Parse(stCall.GetParamId(5));
}
}

private void LoadStateImpactConfig(ScriptableData.CallData stCall)
{
StateImpact stateimpact = TriggerUtil.ParseStateImpact(stCall);
m_StateImpacts[stateimpact.m_State] = stateimpact;
}

private void LoadCollideLayerConfig(ScriptableData.CallData stCall)
{
if (stCall.GetParamNum() >= 2)
{
int layer = LayerMask.NameToLayer(stCall.GetParamId(0));
string message = stCall.GetParamId(1);
if (!string.IsNullOrEmpty(message))
{
if (m_CollideLayerHandler.ContainsKey(layer))
{
m_CollideLayerHandler[layer] = message;
}
else
{
m_CollideLayerHandler.Add(layer, message);
}
}
}
}

private void LoadAttachEnemyConfig(ScriptableData.CallData stCall)
{
if (stCall.GetParamNum() >= 8)
{
m_AttachConfig.IsAttachEnemy = true;
m_AttachConfig.AttachNodeName = stCall.GetParamId(0);
m_AttachConfig.AttachRotation = ScriptableDataUtility.CalcVector3(stCall.GetParam(1) as ScriptableData.CallData);
m_AttachConfig.AttachImpact = int.Parse(stCall.GetParamId(2));
m_AttachConfig.AttachImpactTime = int.Parse(stCall.GetParamId(3));
m_AttachConfig.FallImpact = int.Parse(stCall.GetParamId(4));
m_AttachConfig.FallImpactTime = int.Parse(stCall.GetParamId(5));
m_AttachConfig.FinalImpact = int.Parse(stCall.GetParamId(6));
m_AttachConfig.FinalImpactTime = int.Parse(stCall.GetParamId(7));
}
}


}
}

SkillSystem

\Public\SkillSystem\ISkillTriger.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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

// 属于SkillSystem命名空间
namespace SkillSystem
{
// 接口
public interface ISkillTriger
{
ISkillTriger Clone(); // 克隆触发器,触发器只会从DSL实例一次,之后都通过克隆产生新实例
long GetStartTime(); // 开始时间
void Init(ScriptableData.ISyntaxComponent config); // 从DSL语言初始化触发器实例
void Reset(); // 复位触发器到初始状态
bool Execute(object sender, SkillInstance instance, long delta, long curSectionTime); // 执行触发器,返回false表示触发器结束,下一tick不再执行
void Analyze(object sender, SkillInstance instance); // 语义分析,配合上下文sender与instance进行语义分析,在执行前收集必要的信息
}

// 抽象类继承接口
public abstract class AbstractSkillTriger : ISkillTriger
{
public virtual long GetStartTime()
{
return m_StartTime;
}

public void Init(ScriptableData.ISyntaxComponent config)
{
ScriptableData.CallData callData = config as ScriptableData.CallData;
if (null != callData)
{
Load(callData);
} else
{
ScriptableData.FunctionData funcData = config as ScriptableData.FunctionData;
if (null != funcData)
{
Load(funcData);
}
else
{
ScriptableData.StatementData statementData = config as ScriptableData.StatementData;
if (null != statementData)
{
// 是否支持语句类型的触发器语法?
Load(statementData);
}
else
{
//error
}
}
}
}
// 可以不实现,只需要把方法设为abstract或virtual
public abstract ISkillTriger Clone();
public virtual void Reset() { }
public virtual bool Execute(object sender, SkillInstance instance, long delta, long curSectionTime) { return false; }
public virtual void Analyze(object sender, SkillInstance instance) { }

protected virtual void Load(ScriptableData.CallData callData)
{
}

protected virtual void Load(ScriptableData.FunctionData funcData)
{
}

protected virtual void Load(ScriptableData.StatementData statementData)
{
}

protected long m_StartTime = 0;
}
}

\Public\SkillSystem\SkillInstance.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
using System;
using System.Collections.Generic;
using DashFire;

/// <summary>
/// DSL
/// 和暗黑战神的XML文件配置差不多,暗黑战神是CG,这边是技能
/// 留给策划自己配置。可以想见一个成熟的框架对游戏开发的助力,搭建的速度是非常快的。
/// skill(10001) // 技能id
/// {
/// section(80)
/// {
/// disableinput(10);
/// animation("jump");
/// sound("haha.mp3");
/// };
/// section(10)
/// {
/// animation("kan");
/// addimpact(123,43);
/// };
/// section(1000)
/// {
/// checkinput(skillQ,skillE); // 检查输入
/// complex_triger(123)
/// {
/// configdata1(1231);
/// configdata2(3432)
/// {
/// subconfigdata(1232,321321);
/// subconfigdata(12d32,3fd21321);
/// };
/// };
/// };
/// onstop
/// {
/// triger();
/// };
/// oninterrupt
/// {
/// triger();
/// };
/// onmessage("npckilled",12) // 发送消息
/// {
/// triger();
/// };
/// };
/// </summary>
namespace SkillSystem
{
public sealed class SkillSection
{
private long m_Duration = 0;
private long m_CurTime = 0;
private bool m_IsFinished = true;
private List<ISkillTriger> m_Trigers = new List<ISkillTriger>();
private List<ISkillTriger> m_LoadedTrigers = new List<ISkillTriger>(); // 已经加载过

// 技能持续时间
public long Duration
{
get
{
return m_Duration;
}
}
// 技能已经开始了多长时间
public long CurTime
{
get
{
return m_CurTime;
}
}
// 技能是否结束
public bool IsFinished
{
get
{
return m_IsFinished;
}
}

public SkillSection Clone()
{
SkillSection section = new SkillSection();
foreach (ISkillTriger triger in m_LoadedTrigers)
{
section.m_LoadedTrigers.Add(triger.Clone());
}
section.m_Duration = m_Duration;
return section;
}
}
}

\Public\SkillSystem\ISkillTrigerFactory.cs 工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using System;
using System.Collections.Generic;

namespace SkillSystem
{
public interface ISkillTrigerFactory
{
// 产生ISkillTriger
// 参数是ISkillTriger的配置
ISkillTriger Create(ScriptableData.ISyntaxComponent trigerConfig);
}

public class SkillTrigerFactoryHelper<T> : ISkillTrigerFactory where T : ISkillTriger, new()
{
public ISkillTriger Create(ScriptableData.ISyntaxComponent trigerConfig)
{
T t = new T ();
t.init(trigerConfig);
return t;
}
}
}

\Public\SkillSystem\SkillConfigManager.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
using System;
using System.Collections.Generic;
using DashFire;

// 属于技能系统命名空间
namespace SkillSystem
{
// 密封类不允许被继承
public sealed class SkillConfigManager
{
/// <summary>
/// 如果不存在就加载
/// </summary>
/// <param name="id">技能ID</param>
/// <param name="file">配置</param>
public void LoadSkillIfNotExist(int id, string file)
{
if (!ExistSkill(id))
{
LoadSkill(file);
}
}

public bool ExistSkill(int id)
{
return null != GetSkillInstanceResource(id);
}

public void LoadSkill(string file)
{
if (!string.IsNullOrEmpty(file))
{
ScriptableData.ScriptableDataFile dataFile = new ScriptableData.ScriptableDataFile();
#if DEBUG
if (dataFile.Load(file))
{
Load(dataFile);
}
#else
// Obfuscated混淆
dataFile.LoadObfuscatedFile(file, GlobalVariables.Instance.DecodeTable);
Load(dataFile);
#endif
}
}

public void LoadSkillText(string text)
{
ScriptableData.ScriptableDataFile dataFile = new ScriptableData.ScriptableDataFile();
#if DEBUG
if (dataFile.LoadFromString(text, "skill"))
{
Load(dataFile);
}
#else
dataFile.LoadObfuscatedCode(text, GlobalVariables.Instance.DecodeTable);
Load(dataFile);
#endif
}


}
}

Internal

\Public\GfxLogicBridge\Internal\ResourceManager.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
using System;
using System.Collections.Generic;
using UnityEngine;

namespace DashFire
{
/// <summary>
/// 资源管理器,提供资源缓存重用机制。
///
/// todo:分包策略确定后需要修改为从分包里加载资源
/// </summary>
internal class ResourceManager
{
private ObjectPool<UsedResourceInfo> m_UsedResourceInfoPool = new ObjectPool<UsedResourceInfo>();

private HashSet<int> m_PreloadResources = new HashSet<int>();
private Dictionary<string, UnityEngine.Object> m_LoadedPrefabs = new Dictionary<string, UnityEngine.Object>();
private List<string> m_WaitDeleteLoadedPrefabEntrys = new List<string>();

private LinkedListDictionary<int, UsedResourceInfo> m_UsedResources = new LinkedListDictionary<int, UsedResourceInfo>();
private Dictionary<int, Queue<UnityEngine.Object>> m_UnusedResources = new Dictionary<int, Queue<UnityEngine.Object>>();
private float m_LastTickTime = 0;

public static ResourceManager Instance
{
get { return s_Instance; }
}
private static ResourceManager s_Instance = new ResourceManager();

internal void PreloadResource(string res, int count)
{
UnityEngine.Object prefab = GetSharedResource(res);
PreloadResource(prefab, count);
}

internal void PreloadResource(UnityEngine.Object prefab, int count)
{
if (null != prefab)
{
if (!m_PrefabResources.Contains(prefab.GetInstanceID()))
m_PrefabResources.Add(prefab.GetInstanceID());

for ()
{

}

}
}

internal UnityEngine.Object GetSharedResource(string res)
{
UnityEngine.Object obj = null;
if (string.IsNullOrEmpty(res))
{
return obj;
}

if (m_LoadedPrefabs.ContainsKey(res))
{
obj = m_LoadedPrefabs[res];
}
else
{
if (GlobalVariables.Instance.IsPublish)
{
obj = ResUpdateHandler.LoadAssetFromABWithoutExtension(res);
}
if (obj == null)
{
obj = Resources.Load(res);
}

if (obj != null)
{
m_LoadedPrefabs.Add(res, obj);
}
else
{
UnityEngine.Debug.Log("LoadAsset failed:" + res);
}
}
return obj;
}
}
}

AISystem

\Public\GameObjects\AiCommand\IAiCommand.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DashFire
{
public interface IAiCommand
{
// 返回true表明命令结束,可以从命令队列里移除了
bool Execute(long deltaTime);
void Recycle();
}
}

\Public\AiSystem\AbstractAiCommand.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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DashFire
{
// 这个类必须IAiCommand和IPoolAllocatedObject两个接口中的所有方法
public abstract class AbstractAiCommand<T> : IAiCommand, IPoolAllocatedObject<T> where T : AbstractAiCommand<T>, new()
{
private T m_DowncastObj = null;
private ObjectPool<T> m_Pool = null;

public T Downcast()
{
return m_DowncastObj;
}

// 接口特性,派生类必须实现未实现的方法(接口里的 方法 、属性、索引器、事件都是public型的);如果是抽象类继承的,至少要声明成抽象的,以供实体类来实现。
public abstract bool Execute(long deltaTime);

public void Recycle()
{
if (null != m_Pool)
{
m_Pool.Recycle(this as T);
}
}

public void InitPool(ObjectPool<T> pool)
{
m_DowncastObj = this as T;
m_Pool = pool;
}
}

public abstract class AbstractNpcAiCommand<T> : AbstractAiCommand<T> where T : AbstractAiCommand<T>, new()
{
private NpcInfo m_Npc = null;
private AbstractNpcStateLogic m_Logic = null;

public DashFire.NpcInfo Npc
{
get { return m_Npc; }
}

public DashFire.AbstractNpcStateLogic Logic
{
get { return m_Logic; }
}

public void SetContext(NpcInfo npc, AbstractNpcStateLogic logic)
{
m_Npc = npc;
m_Logic = logic;
}
}

public abstract class AbstractUserAiCommand<T> : AbstractAiCommand<T> where T : AbstractAiCommand<T>, new()
{
private UserInfo m_User = null;
private AbstractUserStateLogic m_Logic = null;

public DashFire.UserInfo User
{
get { return m_User; }
}

public DashFire.AbstractUserStateLogic Logic
{
get { return m_Logic; }
}

public void SetContext(UserInfo user, AbstractUserStateLogic logic)
{
m_User = user;
m_Logic = logic;
}
}
}

GameObjects

\Public\GameObjects\NpcManager.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
using System;
using System.Collections.Generic;
using System.Text;

namespace DashFire
{
public sealed class NpcManager
{
private List<NpcInfo> m_DelayAdd = new List<NpcInfo>();

private LinkedListDictionary<int, NpcInfo> m_Npcs = new LinkedListDictionary<int, NpcInfo>();

private Queue<NpcInfo> m_UnusedNpcs = new Queue<NpcInfo>();

private Heap<int> m_UnusedIds = new Heap<int>(new DefaultReverseComparer<int>());

private int m_NpcPoolSize = 1024;

private const int c_StartId = 20000;
private const int c_MaxIdNum = 10000;
private const int c_StartId_Client = 30000;
private int m_NextInfoId = c_StartId;

private SceneContextInfo m_SceneContext = null;

public DamageDelegation OnDamage;

public NpcManager(int poolSize)
{
m_NpcPoolSize = poolSize;
}

public void SetSceneContext(SceneContextInfo context)
{
m_SceneContext = context;
}
}
}

GfxLogicBridge

\Public\GfxLogicBridge\SharedData\InvokeArgs.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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

namespace DashFire
{
public class TemporaryEffectArgs
{
public string Resource;
public float Duration;
public float X;
public float Y;
public float Z;

public TemporaryEffectArgs(string resource, float duration, float x, float y, float z)
{
Resource = resource;
Duration = duration;
X = x;
Y = y;
Z = z;
}
}

public class SkillParam
{
public int TargetId;
public int SkillId;
}

public class GestureArgs
{
public GestureArgs()
{

}

/// 开始位置
public float startPositionX;
public float startPositionY;
/// 当前位置
public float positionX;
public float positionY;
/// 开始时间
public float startTime;
/// 花费时间
public float elapsedTime;
/// 开始游戏坐标
public float startGamePosX;
public float startGamePosY;
public float startGamePosZ;
/// 游戏中坐标
public float gamePosX;
public float gamePosY;
public float gamePosZ;
/// 游戏中寻路使用的坐标
public float airWelGamePosX;
public float airWelGamePosY;
public float airWelGamePosZ;
/// 手势名称
public string name;
/// 手势方向
public float towards;
/// 移动类型
public TouchType moveType;
/// 是否选中目标
public int selectedObjID;
/// 段数
public int sectionNum;
/// 技能攻击范围
public float attackRange;
/// 输入类型
public InputType inputType;
}

public enum GestureEvent : int
{
OnLine = 0,
OnEasyGesture = 1,
OnFingerDown = 100,
OnFingerMove = 101,
OnFingerUp = 102,
OnTwoFingerDown = 103,
OnTwoFingerMove = 104,
OnTwoFingerUp = 105,
OnSingleTap = 201,
OnDoubleTap = 202,
OnLongPress = 203,
OnSkillStart = 1000,
}

public enum TouchType : int
{
Move = 0,
Regognizer,
Attack,
}

public enum TouchEvent : int
{
Cesture = 0,
}

public enum InputType : int
{
Touch = 0,
Joystick = 1,
}

public static class Keyboard
{
public enum Event
{
Up,
Down,
LongPressed,
}
// 此枚举值需要与所用引擎的枚举定义一致
public enum Code
{
None,
Backspace = 8,
Delete = 127,
Tab = 9,
Clear = 12,
Return,
Pause = 19,
Escape = 27,
Space = 32,
Keypad0 = 256,
Keypad1,
...
Keypad9,
KeypadPeriod,
KeypadDivide,
KeypadMultiply,
KeypadMinus,
KeypadPlus,
KeypadEnter,
KeypadEquals,
UpArrow,
DownArrow,
RightArrow,
LeftArrow,
Insert,
Home,
End,
PageUp,
PageDown,
F1,
...
F15,
Alpha0 = 48,
Alpha1,
Alpha2,
Alpha3,
Alpha4,
Alpha5,
Alpha6,
Alpha7,
Alpha8,
Alpha9,
Exclaim = 33,
DoubleQuote,
Hash,
Dollar,
Ampersand = 38,
Quote,
LeftParen,
RightParen,
Asterisk,
Plus,
Comma,
Minus,
Period,
Slash,
Colon = 58,
Semicolon,
Less,
Equals,
Greater,
Question,
At,
LeftBracket = 91,
Backslash,
RightBracket,
Caret,
Underscore,
BackQuote,
A,
...
Z,
Numlock = 300,
CapsLock,
ScrollLock,
RightShift,
LeftShift,
RightControl,
LeftControl,
RightAlt,
LeftAlt,
LeftCommand = 310,
LeftApple = 310,
LeftWindows,
RightCommand = 309,
RightApple = 309,
RightWindows = 312,
AltGr,
Help = 315,
Print,
SysReq,
Break,
Menu,
Mouse0 = 323,
Mouse1,
Mouse2,
Mouse3,
Mouse4,
Mouse5,
Mouse6,
JoystickButton0, // 一直到19
JoystickButton1,
...
Joystick1Button0,
Joystick1Button1,
...
Joystick2Button0,
Joystick2Button1,
...
Joystick3Button0,
Joystick3Button1,
...
Joystick4Button0,
Joystick4Button1,
...
MaxNum
}
}

public static class Mouse
{
public enum Event
{
Up = 0,
Down,
LongPressed
}

public enum Code
{
LeftButton = 0,
MiddleButton,
RightButton,
NumMouseButtons,
InvalidMouseButton,
TheMouse = InvalidMouseButton,
MaxNum
}
}
}
0%