程序包 cn.wjybxx.btree

类 TaskEntry<T>

java.lang.Object
cn.wjybxx.btree.Task<T>
cn.wjybxx.btree.TaskEntry<T>
所有已实现的接口:
ICancelTokenListener

public class TaskEntry<T> extends Task<T>
任务入口(可联想程序的Main)

1. 该实现并不是典型的行为树实现,而是更加通用的任务树,因此命名TaskEntry。 2. 该类允许继承,以提供一些额外的方法,但核心方法是禁止重写的。 3. Entry的数据尽量也保存在黑板中,尤其是绑定的实体(Entity),尽可能使业务逻辑仅依赖黑板即可完成。 4. Entry默认不检查Task.getGuard(),如果需要由用户(逻辑上的control)检查。 5. 如果要复用行为树,应当以树为单位整体复用,万莫以Task为单位复用 -- 节点之间的引用千丝万缕,容易内存泄漏。 6. 该行为树虽然是事件驱动的,但心跳不是事件,仍需要每一帧调用update(int)方法。 7. 避免直接使用外部的ICancelToken,可将Entry的Token注册为外部的Child。

作者:
wjybxx date - 2023/11/25
  • 构造器详细资料

    • TaskEntry

      public TaskEntry()
    • TaskEntry

      public TaskEntry(String name, Task<T> rootTask, T blackboard, Object entity, TreeLoader treeLoader)
  • 方法详细资料

    • getName

      public String getName()
    • setName

      public void setName(String name)
    • getRootTask

      public Task<T> getRootTask()
    • setRootTask

      public void setRootTask(Task<T> rootTask)
    • getType

      public int getType()
    • setType

      public void setType(int type)
    • setEntity

      public void setEntity(Object entity)
    • getTreeLoader

      public TreeLoader getTreeLoader()
    • getHandler

      public TaskEntryHandler<T> getHandler()
    • setHandler

      public void setHandler(TaskEntryHandler<T> handler)
    • setTreeLoader

      public final void setTreeLoader(TreeLoader treeLoader)
    • getEntity

      public final Object getEntity()
      从类复制的说明: Task
      获取行为树绑定的实体 -- 最好让Entity也在黑板中
      覆盖:
      getEntity 在类中 Task<T>
    • getCurFrame

      public final int getCurFrame()
      从类复制的说明: Task
      获取当前的帧号
      覆盖:
      getCurFrame 在类中 Task<T>
    • getRootStateMachine

      public final StateMachineTask<T> getRootStateMachine()
      获取根状态机 状态机太重要了,值得我们为其提供各种快捷方法
    • update

      public void update(int curFrame)
      用户需要在每一帧调用该方法以驱动心跳逻辑
    • execute

      protected void execute()
      从类复制的说明: Task
      Task的心跳方法,在Task进入完成状态之前会反复执行。 1.可以根据Task.isExecuteTriggeredByEnter()判断是否是与Task.enter(int)连续执行的。 2.运行中可通过Task.setSuccess()Task.setFailed(int) ()}、Task.setCancelled()将自己更新为完成状态。 3.不建议直接调用该方法,而是通过模板方法运行。
      指定者:
      execute 在类中 Task<T>
    • onChildRunning

      protected void onChildRunning(Task<T> child)
      从类复制的说明: Task
      子节点还需要继续运行 1.child在运行期间只会通知一次 2.该方法不应该触发状态迁移,即不应该使自己进入完成状态
      指定者:
      onChildRunning 在类中 Task<T>
    • onChildCompleted

      protected void onChildCompleted(Task<T> child)
      从类复制的说明: Task
      子节点进入完成状态 1.避免方法数太多,实现类测试task的status即可 2.Task.getNormalizedStatus()有助于switch测试 3.task可能是取消状态,甚至可能没运行过直接失败(前置条件失败) 4.钩子任务和guard不会调用该方法 5.Task.isExecuting()有助于检测冲突,减少调用栈深度 6.同一子节点连续通知的情况下,completed的逻辑应当覆盖Task.onChildRunning(Task)的影响。 7.任何的回调和事件方法中都由用户自身检测取消信号
      指定者:
      onChildCompleted 在类中 Task<T>
    • canHandleEvent

      public boolean canHandleEvent(@Nonnull Object event)
      从类复制的说明: Task
      该方法用于测试自己的状态和事件数据 如果通过条件Task来实现事件过滤,那么通常的写法如下:
           blackboard.set("event", event); // task通过黑板获取事件对象
           try {
               return template_checkGuard(eventFilter);
           } finally {
               blackboard.remove("event");
           }
       
      ps: 如果想支持编辑器中测试事件属性,event通常需要实现为KV结构。
      覆盖:
      canHandleEvent 在类中 Task<T>
    • onEventImpl

      protected void onEventImpl(@Nonnull Object event)
      从类复制的说明: Task
      对于控制节点,通常将事件派发给约定的子节点或钩子节点。 对于叶子节点,通常自身处理事件。 注意: 1.转发事件时应该调用子节点的Task.onEvent(Object)方法 2.在AI这样的领域中,建议将事件转化为信息存储在Task或黑板中,而不是尝试立即做出反应。 3.Task.isExecuting()方法很重要
      指定者:
      onEventImpl 在类中 Task<T>
    • resetForRestart

      public void resetForRestart()
      从类复制的说明: Task
      重置任务以便重新启动(清理运行产生的所有临时数据)

      1. 和exit一样,清理的是运行时产生的临时数据,而不是所有数据;不过该方法是比exit更彻底的清理。 2. 钩子任务也应当被重置。 3. 与Task.beforeEnter()相同,重写方法时,应先执行父类逻辑,再重置自身属性。 4. 有临时数据的Task都应该重写该方法,行为树通常是需要反复执行的。

      覆盖:
      resetForRestart 在类中 Task<T>
    • indexChild

      public final int indexChild(Task<?> task)
      覆盖:
      indexChild 在类中 Task<T>
      返回:
      index or -1
    • childStream

      public final Stream<Task<T>> childStream()
      从类复制的说明: Task
      该接口主要用于测试,该接口有一定的开销
      指定者:
      childStream 在类中 Task<T>
    • getChildCount

      public final int getChildCount()
      从类复制的说明: Task
      子节点的数量(仅包括普通意义上的child,不包括钩子任务)
      指定者:
      getChildCount 在类中 Task<T>
    • getChild

      public final Task<T> getChild(int index)
      从类复制的说明: Task
      获取指定索引的child
      指定者:
      getChild 在类中 Task<T>
    • addChildImpl

      protected final int addChildImpl(Task<T> task)
      指定者:
      addChildImpl 在类中 Task<T>
      返回:
      为child分配的index
    • setChildImpl

      protected final Task<T> setChildImpl(int index, Task<T> task)
      指定者:
      setChildImpl 在类中 Task<T>
      返回:
      索引位置旧的child
    • removeChildImpl

      protected final Task<T> removeChildImpl(int index)
      指定者:
      removeChildImpl 在类中 Task<T>
      返回:
      index对应的child