参考 : “海游移动” 博客
http://jxwgame.blog.51cto.com/943299/1602630
先考虑需求
在任何时候,我需要能够通过new创建一个任务(完成事件,获得奖励),任务自动开始运行 ,并且自动判断运行状态,是否完成等。
我们要做的,只是创建这个任务,并赋一些完成条件。
所以任务类(Class MyTask) 必须是脱离于Mono的独立类。并且有一些对任务的控制(开始,暂停,完成)。
大致如下
1 public class MyTask
3 public MyTask()
5 //构造一个任务并且自动开始
6 //createTask
任务建立后,需要不停地监测任务的状态,是个循环,在u3d中只能通过协程,而这个类不继承mono是没有协程的
所以建立一个TaskManager类,继承自mono。用来创建并且监测。
1 public class MyTaskManager:MonoBehavior
3 static MyTaskManager singleton;
5 public static TaskState CreateTask()
7 //专门用来startCorutine
8 if(singleton == null)
10 GameObject go = new GameObject("MyTaskManager");
11 singleton = go.AddComponent<MyTaskManager>();
12 }
14 //既然要创建对象,那么创建完成之后就必须返回给Task类。所以还要建立一个TaskState类用来返回
15 return new TaskState();
16 }
18 //不继承mono
19 public class TaskState
20 {
23 }
完整的3部分代码:
1 using UnityEngine;
2 using System.Collections;
4 /// <summary>
5 /// 任务类,用来被调用
6 /// </summary>
7 public class MyTask
9 //string TaskName;
11 MyTaskManager.TaskState task;
13 public delegate void FinishedHander(bool isFinished);
14 public event FinishedHander Finished;
16 public MyTask(IEnumerator c,bool autoStart = true)
17 {
18 //构造一个任务并且自动开始
19 //由于需要协程(检测运行状态),所以只能再写一个类来提供
20 task = MyTaskManager.CreateTask(c);
22 //将本类中的TaskFinished 加入到 MyTaskManager中的TaskFinished。 所以 在myTaskManager中调用的时候,
23 //会先调用myTaskmanager的taskState中的,然后再调用本类中的
24 task.Finished += TaskFinished;
26 if(autoStart)
27 {
28 //创建完之后运行
29 task.Start();
30 }
32 }
35 void TaskFinished(bool isFinished)
36 {
37 FinishedHander handler = Finished;
38 if(handler!=null)
39 {
40 handler(isFinished);
41 }
42 }
45 //任务有 停止,继续,终结等处理方式
46 public void Pause()
47 {
48 task.Pause();
49 }
51 public void Resume()
52 {
53 task.Resume();
54 }
56 public void Finish()
57 {
58 task.Finish();
59 }
1 using UnityEngine;
2 using System.Collections;
4 /// <summary>
5 /// 提供给MyTask类辅助
6 /// </summary>
7 public class MyTaskManager : MonoBehaviour
10 //单例
11 static MyTaskManager singleton;
12 public static TaskState CreateTask(IEnumerator c)
13 {
14 //既然要创建对象,那么创建完后就要返回,所以必须有个返回的类
15 if(singleton == null)
16 {
17 GameObject go = new GameObject("MyTaskManager");
18 singleton = go.AddComponent<MyTaskManager>();
19 }
20 return new TaskState(c);
21 }
26 //类 类
27 public class TaskState
28 {
29 IEnumerator coroutine; //用来保存传递过来的函数。
30 public enum State
31 {
32 Running,//正在运行
33 Paused, //暂停
34 Stopped,//停止/放弃
35 Finished,//完成
36 }
38 public State state;
40 public delegate void FinishedHander(bool isFinished);
41 public event FinishedHander Finished;
43 public TaskState(IEnumerator c)
44 {
45 coroutine = c;
46 state = State.Running;
47 }
50 public void Start()
51 {
52 //改变任务的状态,并且开启一个监测协程
53 state = State.Running;
54 singleton.StartCoroutine(TaskStateMonitor());
55 }
57 //与task中的操作相对应
58 public void Pause()
59 {
60 state = State.Paused;
61 }
62 public void Resume()
63 {
64 if (state == State.Paused)
65 {
66 state = State.Running;
67 }
68 }
69 public void Finish()
70 {
71 state = State.Finished;
72 }
74 //主要是用来判断是否完成任务
75 IEnumerator TaskStateMonitor()
76 {
77 yield return null;
78 IEnumerator e = coroutine;
79 while(state == State.Running)
80 {
81 if (state == State.Paused)
82 yield return null;
83 else
84 {
85 //IEnumerator 有current ,movenext,reset
86 //就是说不停地执行 new出来的任务,因为new出来的任务是Enumrator,直到不能movenext了
87 if(e !=null && e.MoveNext())
88 {
89 yield return e.Current;
90 }
91 else
92 {
93 state = State.Finished;
94 }
95 }
96 }
97 FinishedHander handler = Finished;
98 if (handler != null)
99 handler(true); //true
101 }
103 }
104 }
1 using UnityEngine;
2 using System.Collections;
4 /// <summary>
5 /// 使用示例
6 /// </summary>
7 public class UseTask : MonoBehaviour
10 IEnumerator TaskOne()
11 {
12 while(true)
13 {
14 Debug.Log("TaskOne running");
15 if(CheckTaskOneFinished())
16 {
17 Debug.Log("TaskOne Finished");
18 DealWithTaskOneFinished();
19 break; //跳出后 执行e.moveNext()就没有了,状态就finished
20 }
21 yield return null;
22 }
23 }
25 /// <summary>
26 /// 用来检测任务是否完成,里面放条件
27 /// </summary>
28 /// <returns></returns>
29 bool CheckTaskOneFinished()
30 {
31 if(Time.time >3)
32 {
33 return true;
34 }
35 else
36 {
37 return false;
38 }
39 }
41 void DealWithTaskOneFinished()
42 {
43 ///
44 }
47 void Start()
48 {
49 MyTask task = new MyTask(TaskOne());
51 //匿名添加finished后的操作。
52 task.Finished += delegate(bool value)
53 {
54 if(value)
55 {
56 Debug.Log("after 匿名 finished");
57 }
58 };
60 }
执行结果:
可以自行加一些任务的处理。完善整个系统。
重要几点:
1: IEnumerator : 我的理解是一个类似Interator的接口,它有三个方法。current,movenext,reset 。
每次就movenext去执行,执行到yield 位置。
2: yiled return: 每次调用到yield 的时候,就返回,下次在yiled之后的地方继续执行。
3: event 调用顺序 。 TaskState -> myTask 。所有的finished事件都是注册到TaskState中的。
所以当上述的任务正在执行的时候,会一直在while循环中,一直可以movenext,一旦完成条件达到,跳出循环。则movenext马上为null,
改变state为Finished。通过事件层层调用注册的函数去执行。