[Unity实战]一个简单的任务系统

1.任务管理类与任务类是一对一的关系,而任务管理类与其他类是一对多的关系。对于一对多,比较容易想到的就是观察者模式了。在观察者模式中,是观察者决定要监视的东西,而不是事件的发生者决定谁观察它。

2.对于任务类/任务条件类/任务奖励类来说,有逻辑意义上的,也有界面意义上的,因此要分开处理。


这里给出主要的逻辑代码:

[csharp] view plain copy
print ?
  1. using System.Collections;  
  2. using System.Collections.Generic;  
  3. using System.Xml.Linq;  
  4. using System;  
  5.   
  6. public class Task {  
  7.   
  8.     public TaskItem taskItem;//对应的UI面板  
  9.   
  10.     public string taskID;//任务ID  
  11.     public string taskName;//任务名字  
  12.     public string caption;//任务描述     
  13.     public List<TaskCondition> taskConditions = new List<TaskCondition>();  
  14.     public List<TaskReward> taskRewards = new List<TaskReward>();  
  15.   
  16.     //根据taskNum读取xml,实现初始化  
  17.     public Task(string taskID)  
  18.     {  
  19.         this.taskID = taskID;  
  20.         XElement xe = TaskManager.Instance.rootElement.Element(taskID);  
  21.         taskName = xe.Element("taskName").Value;  
  22.         caption = xe.Element("caption").Value;  
  23.   
  24.         IEnumerable<XElement> a = xe.Elements("conditionID");  
  25.         IEnumerator<XElement> b = xe.Elements("conditionTargetAmount").GetEnumerator();  
  26.   
  27.         IEnumerable<XElement> c = xe.Elements("rewardID");  
  28.         IEnumerator<XElement> d = xe.Elements("rewardAmount").GetEnumerator();  
  29.   
  30.         foreach (var s in a)  
  31.         {  
  32.             b.MoveNext();  
  33.             TaskCondition tc = new TaskCondition(s.Value, 0, int.Parse(b.Current.Value));  
  34.             taskConditions.Add(tc);  
  35.         }  
  36.   
  37.         foreach (var s in c)  
  38.         {  
  39.             d.MoveNext();  
  40.             TaskReward tr = new TaskReward(s.Value, int.Parse(d.Current.Value));  
  41.             taskRewards.Add(tr);  
  42.         }  
  43.     }  
  44.   
  45.     //判断条件是否满足  
  46.     public void Check(TaskEventArgs e)  
  47.     {  
  48.         TaskCondition tc;  
  49.         for (int i = 0; i < taskConditions.Count; i++)  
  50.         {  
  51.             tc = taskConditions[i];  
  52.             if (tc.id == e.id)  
  53.             {  
  54.                 tc.nowAmount += e.amount;  
  55.                 if(tc.nowAmount < 0) tc.nowAmount = 0;  
  56.                 if (tc.nowAmount >= tc.targetAmount)  
  57.                     tc.isFinish = true;  
  58.                 else  
  59.                     tc.isFinish = false;  
  60.   
  61.                 taskItem.Modify(e.id,tc.nowAmount);  
  62.             }  
  63.         }  
  64.   
  65.         for (int i = 0; i < taskConditions.Count; i++)  
  66.         {  
  67.             if (!taskConditions[i].isFinish)  
  68.             {  
  69.                 taskItem.Finish(false);  
  70.                 return;  
  71.             }  
  72.         }  
  73.         taskItem.Finish(true);  
  74.         e.taskID = taskID;  
  75.         TaskManager.Instance.FinishTask(e);  
  76.     }  
  77.   
  78.     //获取奖励  
  79.     public void Reward()  
  80.     {  
  81.         TaskEventArgs e = new TaskEventArgs();  
  82.         e.taskID = taskID;  
  83.         TaskManager.Instance.GetReward(e);  
  84.     }  
  85.   
  86.     //取消任务  
  87.     public void Cancel()  
  88.     {  
  89.         TaskEventArgs e = new TaskEventArgs();  
  90.         e.taskID = taskID;  
  91.         TaskManager.Instance.CancelTask(e);  
  92.     }  
  93. }  
using System.Collections;
using System.Collections.Generic;
using System.Xml.Linq;
using System;

public class Task {

    public TaskItem taskItem;//对应的UI面板

    public string taskID;//任务ID
    public string taskName;//任务名字
    public string caption;//任务描述   
    public List<TaskCondition> taskConditions = new List<TaskCondition>();
    public List<TaskReward> taskRewards = new List<TaskReward>();

    //根据taskNum读取xml,实现初始化
    public Task(string taskID)
    {
        this.taskID = taskID;
        XElement xe = TaskManager.Instance.rootElement.Element(taskID);
        taskName = xe.Element("taskName").Value;
        caption = xe.Element("caption").Value;

        IEnumerable<XElement> a = xe.Elements("conditionID");
        IEnumerator<XElement> b = xe.Elements("conditionTargetAmount").GetEnumerator();

        IEnumerable<XElement> c = xe.Elements("rewardID");
        IEnumerator<XElement> d = xe.Elements("rewardAmount").GetEnumerator();

        foreach (var s in a)
        {
            b.MoveNext();
            TaskCondition tc = new TaskCondition(s.Value, 0, int.Parse(b.Current.Value));
            taskConditions.Add(tc);
        }

        foreach (var s in c)
        {
            d.MoveNext();
            TaskReward tr = new TaskReward(s.Value, int.Parse(d.Current.Value));
            taskRewards.Add(tr);
        }
    }

    //判断条件是否满足
    public void Check(TaskEventArgs e)
    {
        TaskCondition tc;
        for (int i = 0; i < taskConditions.Count; i++)
        {
            tc = taskConditions[i];
            if (tc.id == e.id)
            {
                tc.nowAmount += e.amount;
                if(tc.nowAmount < 0) tc.nowAmount = 0;
                if (tc.nowAmount >= tc.targetAmount)
                    tc.isFinish = true;
                else
                    tc.isFinish = false;

                taskItem.Modify(e.id,tc.nowAmount);
            }
        }

        for (int i = 0; i < taskConditions.Count; i++)
        {
            if (!taskConditions[i].isFinish)
            {
                taskItem.Finish(false);
                return;
            }
        }
        taskItem.Finish(true);
        e.taskID = taskID;
        TaskManager.Instance.FinishTask(e);
    }

    //获取奖励
    public void Reward()
    {
        TaskEventArgs e = new TaskEventArgs();
        e.taskID = taskID;
        TaskManager.Instance.GetReward(e);
    }

    //取消任务
    public void Cancel()
    {
        TaskEventArgs e = new TaskEventArgs();
        e.taskID = taskID;
        TaskManager.Instance.CancelTask(e);
    }
}


[csharp] view plain copy
print ?
  1. using UnityEngine;  
  2. using System.Collections;  
  3. using System.Collections.Generic;  
  4. using System.Xml.Linq;  
  5. using System;  
  6.   
  7. public class TaskManager : MonoSingletion<TaskManager> {  
  8.   
  9.     public Dictionary<string, Task> dictionary = new Dictionary<string,Task>();//id,task  
  10.     public XElement rootElement;  
  11.   
  12.     public event EventHandler<TaskEventArgs> getEvent;//接受任务时,更新任务到任务面板等操作  
  13.     public event EventHandler<TaskEventArgs> finishEvent;//完成任务时,提示完成任务等操作  
  14.     public event EventHandler<TaskEventArgs> rewardEvent;//得到奖励时,显示获取的物品等操作  
  15.     public event EventHandler<TaskEventArgs> cancelEvent;//取消任务时,显示提示信息等操作  
  16.   
  17.     void Start()  
  18.     {  
  19.         MesManager.Instance.checkEvent += CheckTask;  
  20.         rootElement = XElement.Load(Application.dataPath + "/TestTask/Task.xml");//得到根元素  
  21.     }  
  22.   
  23.     public void GetTask(string taskID)  
  24.     {  
  25.         if (!dictionary.ContainsKey(taskID))  
  26.         {  
  27.             Task t = new Task(taskID);  
  28.             dictionary.Add(taskID, t);  
  29.   
  30.             TaskEventArgs e = new TaskEventArgs();  
  31.             e.taskID = taskID;  
  32.             getEvent(this, e);  
  33.         }  
  34.     }  
  35.   
  36.     public void CheckTask(System.Object sender, TaskEventArgs e)  
  37.     {  
  38.         foreach (KeyValuePair<string, Task> kv in dictionary)  
  39.         {  
  40.             kv.Value.Check(e);  
  41.         }  
  42.     }  
  43.   
  44.     public void FinishTask(TaskEventArgs e)  
  45.     {  
  46.         finishEvent(this, e);  
  47.     }  
  48.   
  49.     public void GetReward(TaskEventArgs e)  
  50.     {  
  51.         if (dictionary.ContainsKey(e.taskID))  
  52.         {  
  53.             Task t = dictionary[e.taskID];  
  54.             for (int i = 0; i < t.taskRewards.Count; i++)  
  55.             {  
  56.                 TaskEventArgs a = new TaskEventArgs();  
  57.                 a.id = t.taskRewards[i].id;  
  58.                 a.amount = t.taskRewards[i].amount;  
  59.                 a.taskID = e.taskID;  
  60.                 rewardEvent(this,a);  
  61.             }  
  62.         }  
  63.         dictionary.Remove(e.taskID);  
  64.     }  
  65.   
  66.     public void CancelTask(TaskEventArgs e)  
  67.     {  
  68.         if (dictionary.ContainsKey(e.taskID))  
  69.         {  
  70.             cancelEvent(this,e);  
  71.             dictionary.Remove(e.taskID);  
  72.         }  
  73.     }   
  74. }  
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Xml.Linq;
using System;

public class TaskManager : MonoSingletion<TaskManager> {

    public Dictionary<string, Task> dictionary = new Dictionary<string,Task>();//id,task
    public XElement rootElement;

    public event EventHandler<TaskEventArgs> getEvent;//接受任务时,更新任务到任务面板等操作
    public event EventHandler<TaskEventArgs> finishEvent;//完成任务时,提示完成任务等操作
    public event EventHandler<TaskEventArgs> rewardEvent;//得到奖励时,显示获取的物品等操作
    public event EventHandler<TaskEventArgs> cancelEvent;//取消任务时,显示提示信息等操作

    void Start()
    {
        MesManager.Instance.checkEvent += CheckTask;
        rootElement = XElement.Load(Application.dataPath + "/TestTask/Task.xml");//得到根元素
    }

    public void GetTask(string taskID)
    {
        if (!dictionary.ContainsKey(taskID))
        {
            Task t = new Task(taskID);
            dictionary.Add(taskID, t);

            TaskEventArgs e = new TaskEventArgs();
            e.taskID = taskID;
            getEvent(this, e);
        }
    }

    public void CheckTask(System.Object sender, TaskEventArgs e)
    {
        foreach (KeyValuePair<string, Task> kv in dictionary)
        {
            kv.Value.Check(e);
        }
    }

    public void FinishTask(TaskEventArgs e)
    {
        finishEvent(this, e);
    }

    public void GetReward(TaskEventArgs e)
    {
        if (dictionary.ContainsKey(e.taskID))
        {
            Task t = dictionary[e.taskID];
            for (int i = 0; i < t.taskRewards.Count; i++)
            {
                TaskEventArgs a = new TaskEventArgs();
                a.id = t.taskRewards[i].id;
                a.amount = t.taskRewards[i].amount;
                a.taskID = e.taskID;
                rewardEvent(this,a);
            }
        }
        dictionary.Remove(e.taskID);
    }

    public void CancelTask(TaskEventArgs e)
    {
        if (dictionary.ContainsKey(e.taskID))
        {
            cancelEvent(this,e);
            dictionary.Remove(e.taskID);
        }
    } 
}

思路(这里以怪物被消灭后为例):

1.怪物消灭后,发送信息到消息中心,消息中心再将消息分发给监听它的东西,例如得分增加,经验上升等等,其中包括发送给我们的TaskManager(如果没有消息中心,那么如果想增加一个观察者观察怪物消灭的信息,就要改动怪物的代码,相反,如果使用消息中心,那么只需要在新增的观察者中注册事件就可以了)

2.TaskManager将信息传递到正在执行的任务Task,Task根据条件判断是否完成任务,如果完成了,则通知TaskManager(两者是一对一的关系)

3.TaskManager将任务完成的消息分发出去


测试:

1.对于收集物品的任务,当收集完成后,再丢弃部分物品。结果:任务不显示完成,领取不了奖励

2.多个任务同时进行。结果:可以领取完成了任务的奖励

3.接受任务后再打开任务面板。结果:显示正常

4.任务中存在相同条件的。结果:正常



不足:

1.对于收集物品的任务,没有对物品起始数量进行初始化

2..等等


总结:

这里可以看到事件委托的强大了吧!



这是unitypackage:

http://yun.baidu.com/s/1gdH7sWF

Ps:导入unity后会发现报错,这时只需添加一个MonoSingletion类即可:http://blog.csdn.net/lyh916/article/details/45898343

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值