[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.等等
总结:
这里可以看到事件委托的强大了吧!
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。