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

对于任务系统来说,最重要的就是处理脚本之间的消息传递,所以任务系统的核心必定就是事件委托了。这里给出核心代码:

using UnityEngine;
using System.Collections;

public class TaskCondition
{
    public string id;//条件id
    public int nowAmount;//条件id的当前进度
    public int targetAmount;//条件id的目标进度
    public bool isFinish = false;//记录是否满足条件

    public TaskCondition(string id, int nowAmount, int targetAmount, bool isFinish)
    {
        this.id = id;
        this.nowAmount = nowAmount;
        this.targetAmount = targetAmount;
        this.isFinish = isFinish;
    }

    public void Check(string id, int amount)
    {
        if (id == this.id)
        {
            nowAmount += amount;
            if (nowAmount >= targetAmount)
                isFinish = true;
            else
                isFinish = false;
        }
    }
}

using UnityEngine;
using System.Collections;

public class TaskReward
{
    public string id;//奖励id
    public int amount = 0;//奖励数量

    public TaskReward(string id, int amount)
    {
        this.id = id;
        this.amount = amount;
    }
}

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Xml.Linq;

public class Task : MonoBehaviour {

    public string id;//id
    public string caption;//任务描述

    public enum State
    {
        get,               //接受任务
        progress,          //进行任务
        finish,            //完成任务
        reward             //得到奖励
    }
    public State state = State.get;

    //接受任务时可能会触发:更新任务到任务面板中等操作
    public delegate void getDelegate(string info);
    public event getDelegate getEvent;

    //检查每个条件是否满足
    public delegate void checkDelegate(string id, int amount);
    public event checkDelegate checkEvent;

    //完成任务时可能会触发:提示完成任务等操作
    public delegate void finishDelegate(string info);
    public event finishDelegate finishEvent;

    //得到奖励时可能会触发:显示获取的物品等操作
    public delegate void rewardDelegate(string info);
    public event rewardDelegate rewardEvent;

    public List<TaskCondition> taskConditions = new List<TaskCondition>();
    public List<TaskReward> taskRewards = new List<TaskReward>();
    
    //根据id读取xml,进行初始化
    public Task(string id)
    {
        this.id = id;
        XElement xe = TaskManager.instance.xElement.Element("Task" + id);

        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), false);
            taskConditions.Add(tc);
            checkEvent += tc.Check;
        }

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

        getEvent += Notification.instance.PrintInfo;
        finishEvent += Notification.instance.PrintInfo;
        rewardEvent += Notification.instance.PrintInfo;
        Get();
    }

    //接受任务
    public void Get()
    {
        getEvent("接受任务Task" + this.id);
        state = State.progress;
    }

    //判断条件是否满足
    public void Check(string id, int amount)
    {
        checkEvent(id,amount);
        for(int i = 0;i < taskConditions.Count;i++)
        {
            if(!taskConditions[i].isFinish)
            {
                state = State.progress;
                return;
            }
        }
        state = State.finish;
        Finish();
    }

    //完成任务
    public void Finish()
    {
        finishEvent("任务" + this.id + "完成!!");
        state = State.reward;
    }

    //获取奖励
    public void Reward()
    {
        if (state != State.reward) return;
        TaskReward tr;
        for (int i = 0; i < taskRewards.Count; i++)
        {
            tr = taskRewards[i];
            rewardEvent("奖励物品" + tr.id + "奖励数量" + tr.amount);
        }
        DestroyTask();
    }

    public void DestroyTask()
    {
        Notification.instance.PrintInfo("奖励已获取,或者任务被取消!!");
        TaskManager.instance.tasks.Remove(this);
        TaskManager.instance.getEvent -= this.Get;
        TaskManager.instance.checkEvent -= this.Check;
        TaskManager.instance.rewardEvent -= this.Reward;
        Destroy(this);
    }
}

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Xml.Linq;

public class TaskManager : MonoBehaviour {

    public static TaskManager instance;
    public XElement xElement;
    public List<Task> tasks = new List<Task>();

    //接受任务时可能会触发:更新任务到任务面板中等操作
    public delegate void getDelegate();
    public event getDelegate getEvent;

    //检查每个条件是否满足
    public delegate void checkDelegate(string id, int amount);
    public event checkDelegate checkEvent;

    //得到奖励时可能会触发:显示获取的物品等操作
    public delegate void rewardDelegate();
    public event rewardDelegate rewardEvent;

    void Awake()
    {
        if (!instance)
            instance = this;
        else
            Destroy(this);    
    }

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

    public void CreateTask(string id)
    {
        for (int i = 0; i < tasks.Count; i++)
        {
            if (tasks[i].id == id)
                return;
        }

        Task t = new Task(id);
        tasks.Add(t);
        getEvent += t.Get;
        checkEvent += t.Check;
        rewardEvent += t.Reward;
    }

    public void RemoveTask(string id)
    {
        for (int i = 0; i < tasks.Count; i++)
        {
            if (tasks[i].id == id)
                tasks[i].DestroyTask();
        }
    }

    public void Get()
    {
        if (getEvent != null)
            getEvent();
    }

    public void Check(string id, int amount)
    {
        if (checkEvent != null)
            checkEvent(id,amount);
    }

    public void Reward()
    {
        if (rewardEvent != null)
            rewardEvent();
    }
}

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

1.怪物消灭后发送信息给监听它的东西,例如得分增加,经验上升等等,其中包括发送给我们的TaskManager

2.TaskManager将信息传递到正在执行的任务Task

3.任务Task再将信息传递到该任务的条件

这里为什么不直接将怪物消灭后的信息直接发送给条件呢?因为这个消息不知道哪个条件在监听它,而条件也不知道要监听哪些消息,这时就需要TaskManager这个中间体了

虽然消息传递很曲折,但是事件委托的效率比较高,所以应该不用担心效率方面的问题


测试:

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

2.任务完成后放弃任务。结果:领取不了奖励

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

技术分享

技术分享


不足:

1.由于对事件委托还没有进行深入的了解,所以在事件委托方面应该能进一步的优化

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

3.等等


总结:

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


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。