把看完代码的部分思路记录在博客上,某种程度上来说真是一件枯燥的事情,因为看代码的速度有时候很快记录下来却要花费很多时间。

但我的心态过于浮躁了,对事物的掌握很容易因为浮躁而失去应有的水准,希望能通过坚持更新GF系列笔记,打磨一下自己的浮躁心态。

对GF任务的理解

GF的任务模块本质上是对各种任务池子的维护与轮询更新,至于任务本身是什么,我们拥有广阔的自定义空间。

任务有个大体的结构:1.任务行为代理(agent),2.任务内容(task)

E神在自己的框架中定义和使用了三种任务(下面给出代理类名):

1.DownloadAgent,2.LoadResourceAgent,3.WebRequestAgent

继续阅读框架我们会逐渐遇见这三种任务类型。

伪代码展示

TaskPool

TaskPool管理和维护着一个系列的任务的轮询更新,体现了任务池基本的运作方式

通过对数据定义的观察,可以看出此任务池的实现对内存的使用控制非常小心谨慎

class TaskPool<T> where T : TaskBase
{
    private readonly Stack<ITaskAgent<T>> m_FreeAgents;
    private readonly GameFrameworkLinkedList<ITaskAgent<T>> m_WorkingAgents;
    private readonly GameFrameworkLinkedList<T> m_WaitingTasks;

    public bool Paused;/// 获取或设置任务池是否被暂停。

    public int TotalAgentCount;/// 获取任务代理总数量。
    public int FreeAgentCount;/// 获取可用任务代理数量。
    public int WorkingAgentCount;/// 获取工作中任务代理数量。
    public int WaitingTaskCount;/// 获取等待任务数量。


    /// <summary>
    /// 任务池轮询。
    /// </summary>
    /// <param name="elapseSeconds">逻辑流逝时间,以秒为单位。</param>
    /// <param name="realElapseSeconds">真实流逝时间,以秒为单位。</param>
    public void Update(float elapseSeconds, float realElapseSeconds)
    {
        if (m_Paused)
        {
            return;
        }

        //轮询处理运行中任务
        ProcessRunningTasks(elapseSeconds, realElapseSeconds);
        //处理刚加入轮询还在等待状态中的任务
        ProcessWaitingTasks(elapseSeconds, realElapseSeconds);
    }
}

ITaskAgent

任务代理可以说标识着任务的行为

剩下一些细节就不做过多的展示,基本流程应该已经体现出来了,TaskBase也是在引用池的管理之下

interface ITaskAgent<T> where T : TaskBase
{
    /// <summary>
    /// 获取任务。
    /// </summary>
    T Task
    {
        get;
    }

    /// <summary>
    /// 初始化任务代理。
    /// </summary>
    void Initialize();

    /// <summary>
    /// 任务代理轮询。
    /// </summary>
    /// <param name="elapseSeconds">逻辑流逝时间,以秒为单位。</param>
    /// <param name="realElapseSeconds">真实流逝时间,以秒为单位。</param>
    void Update(float elapseSeconds, float realElapseSeconds);

    /// <summary>
    /// 关闭并清理任务代理。
    /// </summary>
    void Shutdown();

    /// <summary>
    /// 开始处理任务。
    /// </summary>
    /// <param name="task">要处理的任务。</param>
    /// <returns>开始处理任务的状态。</returns>
    StartTaskStatus Start(T task);

    /// <summary>
    /// 停止正在处理的任务并重置任务代理。
    /// </summary>
    void Reset();
}

使用实践

BuffTask 与 BuffAgent

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GameFramework;

public class BuffTask :TaskBase
{

    string bufTest;
    public float T_Timeout;
    public float F_Time;



    public static BuffTask Create(string buf,int ftimeout,int ttimeout,object userData)
    {
        BuffTask buffTask = ReferencePool.Acquire<BuffTask>();
        buffTask.Initialize(1,"",1, userData);
        buffTask.bufTest = buf;
        buffTask.F_Time = ftimeout;
        buffTask.T_Timeout = ttimeout;
        return buffTask;
    }

    /// <summary>
    /// 清理buff任务。
    /// </summary>
    public override void Clear()
    {
        base.Clear();
        bufTest = null;
    }
}

public class BuffAgent: ITaskAgent<BuffTask>
{
    private BuffTask m_Task;

    public BuffTask Task
    {
        get
        {
            return m_Task;
        }
    }

    public void Initialize()
    {
        Debug.LogError("Agent Initialize");
    }

    public void Reset()
    {
        m_Task.Clear();
    }

    public void Shutdown()
    {
        m_Task.Clear();
    }

    public StartTaskStatus Start(BuffTask task)
    {
        m_Task = task;

        return StartTaskStatus.CanResume;
    }

    public void Update(float elapseSeconds, float realElapseSeconds)
    {
        //Debug.LogError("buf over");

        m_Task.F_Time += realElapseSeconds;

        if (m_Task.T_Timeout <= m_Task.F_Time)
        {
            Debug.LogError("buf over");
            m_Task.Done = true;
        }
    }
}

runtime.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GameFramework;
using UnityGameFramework.Runtime;
using System;
using GameFramework.Event;

namespace StarForce
{
    public class TestNode : MonoBehaviour
    {
        TaskPool<BuffTask> taskPool;


        private void Awake()
        {
            taskPool = new TaskPool<BuffTask>();

            taskPool.AddAgent(new BuffAgent());
            taskPool.AddTask(BuffTask.Create("11",0,2,null));

            Debug.LogError($"FreeAgentCount{taskPool.FreeAgentCount}---TotalAgentCount{taskPool.TotalAgentCount}----WorkingAgentCount{taskPool.WorkingAgentCount}");

        }


        public void Update()
        {
            taskPool.Update(Time.deltaTime,Time.deltaTime);

            if (Input.GetKeyDown(KeyCode.G))
            {
                Debug.LogError($"FreeAgentCount{taskPool.FreeAgentCount}---TotalAgentCount{taskPool.TotalAgentCount}----WorkingAgentCount{taskPool.WorkingAgentCount}");
            }
        }
 
    }

}


运行结果

因为只是简单的使用范例,所以没有按照特别标准的方式来写,为了图快稍微改动了一下底层的密封条件(大晚上太困了= =)

小结

这两天我满脑子都是技能系统,GF的Task运行方式我认为非常切合buff系统的逻辑需求,到我动手写Buf系统的时候会考虑以此为参照。