Unity3D 任務系統設計


 參考 : “海游移動” 博客 http://jxwgame.blog.51cto.com/943299/1602630

先考慮需求

在任何時候,我需要能夠通過new創建一個任務(完成事件,獲得獎勵),任務自動開始運行 ,並且自動判斷運行狀態,是否完成等。
我們要做的,只是創建這個任務,並賦一些完成條件。

所以任務類(Class MyTask) 必須是脫離於Mono的獨立類。並且有一些對任務的控制(開始,暫停,完成)。
大致如下

1 public class MyTask
2 {
3    public MyTask()
4    {
5       //構造一個任務並且自動開始
6       //createTask
7    }
8 }

任務建立后,需要不停地監測任務的狀態,是個循環,在u3d中只能通過協程,而這個類不繼承mono是沒有協程的
所以建立一個TaskManager類,繼承自mono。用來創建並且監測。

 1     public class MyTaskManager:MonoBehavior
 2     {
 3         static MyTaskManager singleton;
 4 
 5         public static TaskState CreateTask()
 6         {
 7             //專門用來startCorutine
 8             if(singleton == null)
 9             {
10                 GameObject go = new GameObject("MyTaskManager");
11                 singleton = go.AddComponent<MyTaskManager>();
12             }
13 
14             //既然要創建對象,那么創建完成之后就必須返回給Task類。所以還要建立一個TaskState類用來返回
15             return new TaskState();
16         }
17 
18         //不繼承mono
19         public class TaskState
20         {    
21 
22 
23         }
24     }

 

完整的3部分代碼:

 

 1 using UnityEngine;
 2 using System.Collections;
 3 
 4 /// <summary>
 5 /// 任務類,用來被調用
 6 /// </summary>
 7 public class MyTask
 8 {
 9     //string TaskName;
10 
11     MyTaskManager.TaskState task;
12 
13     public delegate void FinishedHander(bool isFinished);
14     public event FinishedHander Finished;
15 
16     public MyTask(IEnumerator c,bool autoStart = true)
17     {
18         //構造一個任務並且自動開始
19         //由於需要協程(檢測運行狀態),所以只能再寫一個類來提供
20         task =  MyTaskManager.CreateTask(c);
21 
22         //將本類中的TaskFinished 加入到 MyTaskManager中的TaskFinished。 所以 在myTaskManager中調用的時候,
23         //會先調用myTaskmanager的taskState中的,然后再調用本類中的
24         task.Finished += TaskFinished;
25 
26         if(autoStart)
27         {
28             //創建完之后運行
29             task.Start();
30         }
31       
32     }
33 
34 
35     void TaskFinished(bool isFinished)
36     {
37         FinishedHander handler = Finished;
38         if(handler!=null)
39         {
40             handler(isFinished);
41         }
42     }
43 
44 
45     //任務有 停止,繼續,終結等處理方式
46     public void Pause()
47     {
48         task.Pause();
49     }
50 
51     public void Resume()
52     {
53         task.Resume();
54     }
55 
56     public void Finish()
57     {
58         task.Finish();
59     }
60    
61 }
  1 using UnityEngine;
  2 using System.Collections;
  3 
  4 /// <summary>
  5 /// 提供給MyTask類輔助
  6 /// </summary>
  7 public class MyTaskManager : MonoBehaviour 
  8 {
  9 
 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     }
 22 
 23     
 24 
 25 
 26     //類 類
 27     public class TaskState
 28     {
 29         IEnumerator coroutine; //用來保存傳遞過來的函數。
 30         public enum State
 31         {
 32             Running,//正在運行
 33             Paused, //暫停
 34             Stopped,//停止/放棄
 35             Finished,//完成
 36         }
 37 
 38         public State state;
 39 
 40         public delegate void FinishedHander(bool isFinished);
 41         public event FinishedHander Finished;
 42       
 43         public TaskState(IEnumerator c)
 44         {
 45             coroutine = c;
 46             state = State.Running;
 47         }
 48 
 49 
 50         public void Start()
 51         {
 52             //改變任務的狀態,並且開啟一個監測協程
 53             state = State.Running;
 54             singleton.StartCoroutine(TaskStateMonitor());
 55         }
 56 
 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         }
 73 
 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
100                      
101         }
102 
103     }
104 }
 1 using UnityEngine;
 2 using System.Collections;
 3 
 4 /// <summary>
 5 /// 使用示例
 6 /// </summary>
 7 public class UseTask : MonoBehaviour
 8 {
 9     
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     }
24 
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     }
40 
41     void DealWithTaskOneFinished()
42     {
43         ///
44     }
45 
46 
47     void Start()
48     {
49         MyTask task = new MyTask(TaskOne());
50         
51         //匿名添加finished后的操作。
52         task.Finished += delegate(bool value)
53         {
54             if(value)
55             {
56                 Debug.Log("after 匿名 finished");
57             }
58         };
59 
60     }
61     
62 }

 

執行結果:

 

可以自行加一些任務的處理。完善整個系統。


重要幾點:
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。通過事件層層調用注冊的函數去執行。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM