游戏蛮牛学习群(纯技术交流,不闲聊):539178957
游戏蛮牛 手机端
开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

项目源码

关注:1400

当前位置:游戏蛮牛 资源专区 项目源码

查看: 1196|回复: 15

[Unity] Unity 实现任务系统TaskSystem

[复制链接]  [移动端链接]
3偶尔光临
218/300
排名
14597
昨日变化
7

6

主题

45

帖子

218

积分

Rank: 3Rank: 3Rank: 3

UID
198084
好友
4
蛮牛币
1540
威望
0
注册时间
2017-1-2
在线时间
140 小时
最后登录
2018-8-7
发表于 2018-5-8 22:09:52 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
本帖最后由 martin4500 于 2018-5-9 09:57 编辑

这段时间比较闲,所以抽时间写了游戏中常见的系统,任务系统,可以接受任务啊,然后通过刷怪等条件去触发任务条件,直到完成任务。
这个系统相对来说比较的简单,可以满足小型的游戏任务系统的基本要求吧!这里面的任务的描述是通过读取Json数据来获取的,当然你也可以去写Excel和XML格式的。序列化Json数据不是用的Unity自带的 JsonUtility.FromJson函数,因为有个更强大的Json解析插件Json .Net for Unity2.0,直接支持对Dictionary类型的支持,这样省事多了,可以在AssetStore直接下载。下面是效果展示: TIM截图20180509095517.png 废话不多说了上代码:
using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using Newtonsoft.Json;

    public class DataManager : MonoSingletions<DataManager>

    {

        private Dictionary<string, Task> taskAllDic = new Dictionary<string, Task>();

        private TextAsset mTextAsset;

        private void Awake()

        {

            if (mTextAsset == null)

            {

                mTextAsset = Resources.Load("Txt/Task", typeof(TextAsset)) as TextAsset;

            }

             taskAllDic = JsonConvert.DeserializeObject<Dictionary<string, Task>>(mTextAsset.text);

           // taskAllDic = UnityEngine.JsonUtility.FromJson <Dictionary<string, Task>> (mTextAsset.text);

            foreach (var item in taskAllDic)

            {

                string tempName=item.Value.taskName;

                Debug.Log(tempName);

            }

        }

        public Task GetTaskByID(string Id)

        {

            Task value;

            if (taskAllDic.TryGetValue(Id, out value)) return value;

            else Debug.LogError("不存在这个字典");

            return null;

    }

}

这个类主要是来读取Json文本解析数据,也不需要多去解释了MonoSingletions是Mono的单例

public class Task
    {
        public string taskID;
        public string taskName;
        public string description;
        public List<TaskConditions> taskConditions = new List<TaskConditions>();
        public TaskRewards[] taskRewards = new TaskRewards[2];//最好是用数组比链表要节省空间
        public Task(string _taskId,string _taskName,string _description, TaskRewards[] _taskRewards,List<TaskConditions> _taskConditions)
        {
            taskID = _taskId;
            taskName=_taskName;
            description = _description;
            taskRewards = _taskRewards;
            taskConditions=_taskConditions;

        }
    }
Task类就是一个JSon数据实例化的载体类,就是根据你的Json文本来写的,记住一点的就是:属性名称一定要和json的属性名称一致。
public class TaskManager :MonoSingletions<TaskManager>
    {
        TransferEvent transfer = new TransferEvent();
        private Dictionary<string, Task> currentTaskDic = new Dictionary<string, Task>();
        public void AcceptTask(string taskID)
        {
            if (currentTaskDic.ContainsKey(taskID))
            {
                print(string.Format("{0},任务已经接受过",taskID));
                return;
            }
            else
            {
                Task t = DataManager.Instance.GetTaskByID(taskID);
                if (t == null) return;
                currentTaskDic.Add(taskID, t);
                TaskArgs args = new TaskArgs();
                args.taskId = taskID;
                TransferEvent.Instance.InvokeEventListen((System.Int16)EventType.OnGetEvent, args);
            }
        }
        /// <summary>
        /// 更新任务进度
        /// </summary>
        /// <param name="args"></param>
        public void CheackTask(TaskArgs args)
        {
            foreach (var item in currentTaskDic)
            {
                UdateUIData(item, args);
                CheackFinishTask(item, args);
            }
        }
        //更新数据
        private void UdateUIData(KeyValuePair<string,Task> item,TaskArgs args)
        {
            TaskConditions tc;
            for (int i = 0; i < item.Value.taskConditions.Count; i++)
            {
                tc = item.Value.taskConditions;
                if (tc.id == args.id)
                {
                    if (tc.nowAmount >= tc.targetAmount) return;
                    tc.nowAmount += args.amount;
                    args.taskId = item.Value.taskID;
                    args.amount = tc.nowAmount;
                    if (tc.nowAmount < 0) tc.nowAmount = 0;
                    if (tc.nowAmount >= tc.targetAmount)
                    {
                        tc.nowAmount = tc.targetAmount;
                        tc.isFinish = true;
                    }
                    else tc.isFinish = false;
                    //更新UI数据
                    TransferEvent.Instance.InvokeEventListen((System.Int16)EventType.OnCheackEvent, args);
                }
            }
        }
        private void CheackFinishTask(KeyValuePair<string, Task> item,TaskArgs args)
        {
            TaskConditions tc;
            for (int i = 0; i < item.Value.taskConditions.Count; i++)
            {
                tc = item.Value.taskConditions;
                if (!tc.isFinish) return;//只要是没有完成就返回
            }
            FinishTask(args);

        }
        private void FinishTask(TaskArgs args)
        {
            //调用任务完成事件
            TransferEvent.Instance.InvokeEventListen((System.Int16)EventType.OnFinishEvent, args);
        }
        /// <summary>
        /// 获取任务奖励
        /// </summary>
        /// <param name="args"></param>
        public void GetReward(TaskArgs args)
        {
            if (currentTaskDic.ContainsKey(args.taskId))//当任务存在
            {
                Task t = currentTaskDic[args.taskId];
                for (int i = 0; i < t.taskRewards.Length; i++)
                {
                    TaskArgs a = new TaskArgs();
                    a.id=t.taskRewards.id;
                    a.amount = t.taskRewards.amount;
                    a.taskId = args.taskId;
                    TransferEvent.Instance.InvokeEventListen((System.Int16)EventType.OnRewardEvent, args);
                    currentTaskDic.Remove(args.taskId);
                }
            }
        }
        public void CancelTask(TaskArgs args)
        {
            if (currentTaskDic.ContainsKey(args.taskId))
            {
                TransferEvent.Instance.InvokeEventListen((System.Int16)EventType.OnCancelEvent, args);
                currentTaskDic.Remove(args.taskId);
            }
        }
    }
TaskManager是管理类,简单的说就是连接任务数据和相关任务操作(UI文本提示,事件的触发等)这里的CheackTask(TaskArgs args是检查任务是否完成和更新UI提示,主要通过对当前任务字典的中的任务内容进行相关赋值实现。其它函数都是比较简单看几眼就知道了就不多说了。
   public enum EventType
    {
        OnGetEvent=0,
        OnCheackEvent=1,
        OnFinishEvent=2,
        OnRewardEvent=3,
        OnCancelEvent=4
    }
    public class TransferEvent
    {
        private List<MesTransfer> mListTransfer ;
        private List<MesTransfer> mAddListener;
        private event MesTransfer OnGetEvent;//接受任务时,更新任务到任务面板等操作
        private event MesTransfer OnCheackEvent;//更新任务信息
        private event MesTransfer OnFinishEvent;//完成任务时,提示完成任务等操作
        private event MesTransfer OnRewardEvent;//得到奖励时,显示获取的物品等操作
        private event MesTransfer OnCancelEvent;//取消任务时,显示提示信息等操作
        private static TransferEvent mInstance;
        public TransferEvent()
        {
            mListTransfer = new List<MesTransfer>();
            mListTransfer.Add(OnGetEvent);
            mListTransfer.Add(OnCheackEvent);
            mListTransfer.Add(OnFinishEvent);
            mListTransfer.Add(OnRewardEvent);
            mListTransfer.Add(OnCancelEvent);

        }
        public static TransferEvent Instance
        {
            get
            {
                if (mInstance == null)
                    mInstance = new TransferEvent();
                return mInstance;
            }
        }
        public bool isCheackNull(System.Int16 index)
        {
            return mListTransfer[index] == null ? true:false ;
        }
        //添加事件
        public void AddEventListen(MesTransfer temp,System.Int16 index)
        {
            if (mListTransfer[index]!=null) return;
            mListTransfer[index] += temp;
        }
        //回调事件
        public void InvokeEventListen(System.Int16 index,TaskArgs args)
        {
            if (index > mListTransfer.Count - 1)
            {
                Debug.Log("链表索引越界");
                return;
            }
            MesTransfer mes = mListTransfer[index];
            if (mListTransfer[index]!=null)
            {
                if (!isCheackNull(index)) mes(args);
            }
        }
        //清空所有的监听事件
        public void ClearListTransfer()
        {
            int i = 0;
            IEnumerator listEnumerartor=mListTransfer.GetEnumerator();
            while(listEnumerartor.MoveNext())
            {
                MesTransfer mes = (MesTransfer)listEnumerartor.Current ;
                mes -= mAddListener;
                i++;
            }
            mListTransfer.Clear();
        }
           }

这是一个事件委托的管理类网上的模板很多,大概都是这个样子了,只要是对事件的增加监听,或者事件回调,和观察者模式很像,主要是为了降低代码之间的耦合性的,如果对委托不是很了解建议自己网上去查,或者照着我这个敲一遍练练手还是可以的。
  public class SMSNotifiler :MonoSingletions<SMSNotifiler>
    {
        private void Start()
        {
            TransferEvent.Instance.AddEventListen(GetPrintInfo, (System.Int16)EventType.OnGetEvent);
            TransferEvent.Instance.AddEventListen(finishPrintInfo, (System.Int16)EventType.OnFinishEvent);
            TransferEvent.Instance.AddEventListen(rewardPrintInfo, (System.Int16)EventType.OnRewardEvent);
            TransferEvent.Instance.AddEventListen(cancelPrintInfo, (System.Int16)EventType.OnCancelEvent);
            TransferEvent.Instance.AddEventListen(cheackPrintInfo, (System.Int16)EventType.OnCheackEvent);
        }
        public void GetPrintInfo(TaskArgs e)
        {
            print("接受任务" + e.taskId);
        }

        public void finishPrintInfo(TaskArgs e)
        {
            print("完成任务" + e.taskId);
        }

        public void rewardPrintInfo(TaskArgs e)
        {
            print("奖励物品" + e.id + "数量" + e.amount);
        }

        public void cancelPrintInfo(TaskArgs e)
        {
            print("取消任务" + e.taskId);
        }
        public void cheackPrintInfo(TaskArgs e)
        {
            print(string.Format("任务是{0},{1}完成了{2}",e.taskId,e.id,e.amount));
        }
就像类名一样这个就是相关提示信息,由TaskManager中的去发布信息,然后Notifiler去执行相关细节而已,也是非常简单的脚本。

    public class ControllerTest : MonoBehaviour
    {
        private SMSNotifiler mSMSNotifiler;
        private TaskManager mTaskManager;
        void Start()
        {
            if(mSMSNotifiler==null)
            mSMSNotifiler = SMSNotifiler.Instance;

            if (mTaskManager == null)
                mTaskManager = TaskManager.Instance;
        }
        private void OnGUI()
        {
            if (GUILayout.Button("接受任务Task1"))
            {
                mTaskManager.AcceptTask("T001");
            }
            if (GUILayout.Button("接受任务Task2"))
            {
                mTaskManager.AcceptTask("T002");
            }
            if (GUILayout.Button("接受任务T003"))
            {
                mTaskManager.AcceptTask("T003");
            }
            if (GUILayout.Button("打怪Enemy1"))
            {
                TaskArgs e = new TaskArgs();
                e.id = "Enemy1";
                e.amount = 1;
                mTaskManager.CheackTask(e);

            }
            if (GUILayout.Button("打怪Enemy2"))
            {
                TaskArgs e = new TaskArgs();
                e.id = "Enemy2";
                e.amount = 1;
                mTaskManager.CheackTask(e);
            }
        }
    }
这个ControllerTest挂在unity的主场景中会自动添加相关的调用代码比如:TaskManager,主要是一个你游戏任务的相关操作都可以写这里,这个类只是一个简单的示例,比如添加不同的任务参数种类等等。
好了这个任务相对比较简单,不过我自己觉得也算是五脏俱全了吧,欢迎给我大佬指正不足的地方。






回复

使用道具 举报

7日久生情
1530/5000
排名
8260
昨日变化
78

9

主题

999

帖子

1530

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
173503
好友
2
蛮牛币
933
威望
0
注册时间
2016-10-5
在线时间
386 小时
最后登录
2018-8-14
发表于 2018-5-10 12:23:36 | 显示全部楼层
不懂!  感觉好累!!!

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1387/1500
排名
2852
昨日变化
9

12

主题

655

帖子

1387

积分

Rank: 6Rank: 6Rank: 6

UID
218409
好友
3
蛮牛币
4951
威望
0
注册时间
2017-4-19
在线时间
265 小时
最后登录
2018-8-14
发表于 2018-5-10 16:51:02 | 显示全部楼层
感谢楼主分享!!!

回复

使用道具 举报

7日久生情
3136/5000
排名
2243
昨日变化
15

0

主题

2098

帖子

3136

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
219676
好友
1
蛮牛币
2437
威望
0
注册时间
2017-7-12
在线时间
462 小时
最后登录
2018-8-14

活力之星

发表于 2018-5-10 16:54:05 | 显示全部楼层
谢谢分享

回复

使用道具 举报

7日久生情
2515/5000
排名
3107
昨日变化
5

0

主题

1764

帖子

2515

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
258739
好友
0
蛮牛币
4935
威望
0
注册时间
2017-12-9
在线时间
317 小时
最后登录
2018-8-14
发表于 2018-5-11 10:40:54 | 显示全部楼层
看起来很不错,感谢楼主分享!!!

回复 支持 反对

使用道具 举报

5熟悉之中
953/1000
排名
3314
昨日变化
17

3

主题

275

帖子

953

积分

Rank: 5Rank: 5

UID
54335
好友
1
蛮牛币
1541
威望
0
注册时间
2014-11-9
在线时间
265 小时
最后登录
2018-8-14
发表于 2018-5-11 16:55:57 | 显示全部楼层
值得学习

回复

使用道具 举报

5熟悉之中
976/1000
排名
6529
昨日变化
4

0

主题

642

帖子

976

积分

Rank: 5Rank: 5

UID
21411
好友
1
蛮牛币
1072
威望
0
注册时间
2014-4-15
在线时间
150 小时
最后登录
2018-7-24
发表于 2018-5-15 18:48:02 | 显示全部楼层
谢谢分享

回复

使用道具 举报

4四处流浪
334/500
排名
7270
昨日变化
43

0

主题

83

帖子

334

积分

Rank: 4

UID
276244
好友
0
蛮牛币
177
威望
0
注册时间
2018-4-9
在线时间
93 小时
最后登录
2018-8-13
发表于 2018-5-22 09:06:55 | 显示全部楼层
感谢分享

回复

使用道具 举报

7日久生情
2337/5000
排名
1279
昨日变化
6

4

主题

592

帖子

2337

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
112674
好友
4
蛮牛币
1360
威望
0
注册时间
2015-7-8
在线时间
867 小时
最后登录
2018-8-14
QQ
发表于 2018-5-25 10:34:57 | 显示全部楼层
值得学习,谢谢分享!!!!

回复 支持 反对

使用道具 举报

7日久生情
1602/5000
排名
3124
昨日变化
2

3

主题

862

帖子

1602

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
246489
好友
1
蛮牛币
2659
威望
0
注册时间
2017-9-28
在线时间
305 小时
最后登录
2018-8-14

活力之星

发表于 2018-5-25 13:53:18 | 显示全部楼层
谢谢谢谢分享

回复

使用道具 举报

排名
27137
昨日变化
15

0

主题

31

帖子

52

积分

Rank: 2Rank: 2

UID
279098
好友
0
蛮牛币
7
威望
0
注册时间
2018-4-27
在线时间
9 小时
最后登录
2018-7-16
发表于 2018-5-26 13:44:32 | 显示全部楼层
感谢分享

回复

使用道具 举报

2初来乍到
113/150
排名
16283
昨日变化
3

0

主题

36

帖子

113

积分

Rank: 2Rank: 2

UID
209518
好友
0
蛮牛币
1
威望
0
注册时间
2017-3-2
在线时间
39 小时
最后登录
2018-8-11
发表于 2018-5-30 17:04:41 | 显示全部楼层
谢谢分享

回复

使用道具 举报

排名
19289
昨日变化
10

0

主题

9

帖子

44

积分

Rank: 1

UID
249404
好友
0
蛮牛币
380
威望
0
注册时间
2017-10-18
在线时间
9 小时
最后登录
2018-7-10
发表于 2018-6-6 09:45:40 | 显示全部楼层
感谢分享!!!

回复

使用道具 举报

4四处流浪
311/500
排名
9067
昨日变化
93

0

主题

132

帖子

311

积分

Rank: 4

UID
261722
好友
0
蛮牛币
191
威望
0
注册时间
2017-12-29
在线时间
63 小时
最后登录
2018-8-14
发表于 2018-7-5 10:30:47 | 显示全部楼层
感谢楼主分享~~大赞!

回复 支持 反对

使用道具 举报

4四处流浪
311/500
排名
9067
昨日变化
93

0

主题

132

帖子

311

积分

Rank: 4

UID
261722
好友
0
蛮牛币
191
威望
0
注册时间
2017-12-29
在线时间
63 小时
最后登录
2018-8-14
发表于 2018-7-5 10:35:38 | 显示全部楼层

不懂!  感觉好累!!!

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表