对于任务系统来说,最重要的就是处理脚本之间的消息传递,所以任务系统的核心必定就是事件委托了。这里给出核心代码:
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.等等
总结:
这里可以看到事件委托的强大了吧!
原文:http://blog.csdn.net/lyh916/article/details/45767357