基本结构
条件
完成或改变特定的条件,触发任务状态的改变,一般由各个系统触发;
任务
一般来说,当任务结束,也就是相应的条件完成,比如常见的主线、支线、每日、每周、委托、成就任务等
主要的配置项
Condition:
ConditionId | Type | Count | RelatedValue | Others |
条件Id | 触发类型 | 目标数量 | 关联值 | |
2 | 2 | 2 | 100 |
Type:
这个主要是设置相关的业务触发类型,不同的业务设置不同的值,这里建议将类型至少设置为ushort, 太小后期会出问题 ^ ^
Count:
目标值,当达到这个值时,任务完成 状态从 Active -> Complete
RelatedValue:
这个会根据不同的Type所在不同的Handler, 会有不同的处理方式,这里列举三种 1.完全匹配;2.部分匹配;3.比大小加部分匹配
条件的状态
public enum ConditionStatus
{
Init = 0,
Active = 10,
Complete = 20
}
Task:
TaskId | ActiveConditionIds | TakeType | TakeConditionIds | DeliveryType | CompleteConditionIds |
任务Id | 激活条件 | 接取类型 | 接取条件 | 提交类型 | 完成条件 |
4 | 2 | 2 | 2 | 1 | 1 |
ActiveConditionIds:
激活任务的条件id列表,满足则任务进入 Active 状态,否则 处于 Init 状态
TakeType:
当任务处于Active 状态时 根据这个类型判断 是 自动接取、手动接取、或NPC接取才进入Take 状态
TakeConditionIds:
接取任务的条件id列表,满足则 进入Take 状态 和 TakeType一起使用
DeliveryType:
任务处于Complete 状态时 根据这个状态判断 是 自动提交、手动提交、或NPC提交才进入Delivery 状态
CompleteConditionIds:
完成任务的条件id列表,满足则进入 Delivery 状态 和 DeliveryType 一起使用
任务的状态
public enum TaskStatus
{
Init = 0,
Active = 10,
Take = 20,
Complete = 30,
Delivery = 40,
}
这里建议将状态的枚举值设置的大一些,方便后期插入一些特殊的状态,要不然需要改许多已经写好的东西,踩过坑的都懂的为啥 ^ ^
状态说明
Active:
1.标志任务出现等结合业务
Take:
1.相关功能的开启关闭
2.任务条件开始被处理
Complete:
1.相关功能的开启关闭
2.任务关联的条件不再改变
Delivery:
1.一般这个状态发奖,像成就,可以结合配置手动领取奖励,主线可以自动发奖等;
2.相关功能的开启关闭
触发完成流程
模拟场景
接取任务后在地图频道发言1次 完成初次发言任务
条件配置如下 :
// 好友频道:1; 地图频道:2; 全服频道:3
public enum ChatChannelType
{
Friend = 1,
Area = 2,
Global = 3,
}
public enum ConditionType
{
#region 聊天发言相关 1-100
// RelatedValue 参考 ChatChannelType值
ChatAddCount = 1,
#endregion
}
ConditionId | Type | Count | RelatedValue | Others |
条件Id | 触发类型 | 目标数量 | 关联值 | |
3 | 1 | 1 | 2 |
任务配置如下:
public enum TakeType
{
Auto = 1,
Manuel = 2,
NPC = 3,
}
public enum DeliveryType
{
Auto = 1,
Manuel = 2,
NPC = 3,
}
TaskId | ActiveConditionIds | TakeType | TakeConditionIds | DeliveryType | CompleteConditionIds |
任务Id | 激活条件 | 接取类型 | 接取条件 | 提交类型 | 完成条件 |
4 | 1 | 1 | 3 |
流程如下:
玩家发言,聊天系统触发相关条件
触发条件 :
// 条件参数
public class ConditionParams
{
public ushort Type;
public int Count;
public List<long> RelatedValue;
}
// 发言
void SendChat(){
// ...
TriggerConditionType(new ConditionParams()
{
Type = 1,
Count = 1,
RelatedValue = new List<long>(){ (long)ChatChannelType.Area }
});
}
检查条件:
void TriggerConditionType(ConditionParams cp)
{
// 获取 这个条件类型的处理类Handler
var handler = GetHandlerByConditionType(cp.Type);
handler.Handle(cp);
}
void Handler(ConditionParams cp)
{
// 1.获取当前 身上ConditionType 为 cp.Type的条件
// 2.检查是否需要检查条件
// 3.检查符合条件的条件
// 根据不同的Handler 这里会有不同的比较方式
// 这里比较 cp.RelatedValue 是否与 配表的 RelatedValue 一致
// 4.改变条件的当前Count
// 根据不同的Handler 这里会有不同的处理方式
// 这里 每次到这里 当前Count++ 即可
// 推送当前Count数据
// 5.检查条件是否完成
// 如果完成推送当前条件状态数据
// 6.检查任务是否完成
// 如果完成推送任务数据
}
这里条件完成,回去检查其相关的任务是否完成,如果想要灵活一些,这里可以将条件的是否完成推送给另一个系统,处理到底是任务完成,还是其它的系统某些设定完成。这里建议不要将条件和任务强绑定,将两者分开,条件是灵活的,一旦固定在任务上,后期将无法利用条件来触发其它相关系统的功能,做过就知道了 ^ ^
总结
这里算是一个最简单版的条件、任务系统了,不过,这里有许多问题,前期可能问题不大,后期如果数据量大的话,问题就出来了。
比如条件Count频繁更新问题,如果很多任务使用这个条件,将会出现很多跟这个条件关联的数据,每次需要将这些数据全部更新,是否必要,是否可以使用一条数据来处理?
条件是灵活的,它可以被任何系统触发,如果有另一个非任务系统想要监听条件,这需要怎么办?是否硬套任务去做,增加系统的复杂度?