zoukankan      html  css  js  c++  java
  • 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。通过事件层层调用注册的函数去执行。

  • 相关阅读:
    电脑开机自动上线(电脑开机之后自动将电脑的远程端口映射到服务器,可以通过其他设备进行连接,实现随时访问自己的电脑)
    批处理(bat)用来监测Windows网络状态脚本
    js取消点击事件
    uni-app 几个实用的功能
    前端几个比较方便的正则验证
    element.ui时间选择器
    Vue pc端项目打包后在nginx中无法正常浏览,点击页面出现404
    微信小程序之选项卡的实现方法
    文本溢出显示省略号
    分享几道前端面试题(3)
  • 原文地址:https://www.cnblogs.com/binpan/p/4290515.html
Copyright © 2011-2022 走看看