java.lang.Object
cn.wjybxx.btree.Task<T>
cn.wjybxx.btree.TaskEntry<T>
- 所有已实现的接口:
ICancelTokenListener
任务入口(可联想程序的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
-
字段概要
-
构造器概要
构造器 -
方法概要
修饰符和类型方法说明protected final intaddChildImpl(Task<T> task) booleancanHandleEvent(Object event) 该方法用于测试自己的状态和事件数据 如果通过条件Task来实现事件过滤,那么通常的写法如下:该接口主要用于测试,该接口有一定的开销protected voidexecute()Task的心跳方法,在Task进入完成状态之前会反复执行。getChild(int index) 获取指定索引的childfinal int子节点的数量(仅包括普通意义上的child,不包括钩子任务)final int获取当前的帧号final Object获取行为树绑定的实体 -- 最好让Entity也在黑板中getName()final StateMachineTask<T> 获取根状态机 状态机太重要了,值得我们为其提供各种快捷方法intgetType()final intindexChild(Task<?> task) protected voidonChildCompleted(Task<T> child) 子节点进入完成状态 1.避免方法数太多,实现类测试task的status即可 2.Task.getNormalizedStatus()有助于switch测试 3.task可能是取消状态,甚至可能没运行过直接失败(前置条件失败) 4.钩子任务和guard不会调用该方法 5.Task.isExecuting()有助于检测冲突,减少调用栈深度 6.同一子节点连续通知的情况下,completed的逻辑应当覆盖Task.onChildRunning(Task)的影响。protected voidonChildRunning(Task<T> child) 子节点还需要继续运行 1.child在运行期间只会通知一次 2.该方法不应该触发状态迁移,即不应该使自己进入完成状态protected voidonEventImpl(Object event) 对于控制节点,通常将事件派发给约定的子节点或钩子节点。removeChildImpl(int index) void重置任务以便重新启动(清理运行产生的所有临时数据)setChildImpl(int index, Task<T> task) voidvoidsetHandler(TaskEntryHandler<T> handler) voidvoidsetRootTask(Task<T> rootTask) final voidsetTreeLoader(TreeLoader treeLoader) voidsetType(int type) voidupdate(int curFrame) 用户需要在每一帧调用该方法以驱动心跳逻辑从类继承的方法 cn.wjybxx.btree.Task
addChild, beforeEnter, checkCancel, enter, exit, getBlackboard, getCancelToken, getControl, getControlData, getEnterFrame, getEntryBlackboard, getExitFrame, getFlags, getGuard, getNormalizedStatus, getPrevStatus, getReentryId, getRunFrames, getSharedProps, getStatus, getTaskEntry, isAutoCheckCancel, isAutoListenCancel, isAutoResetChildren, isCancelled, isCompleted, isDisableDelayNotify, isExecuteTriggeredByEnter, isExecuting, isExited, isExitTriggeredByStop, isFailed, isFailedOrCancelled, isLocked, isNotified, isReentered, isRunning, isSlowStart, isStillborn, isSucceeded, lock, onCancelRequested, onEvent, removeAllChild, removeChild, removeChild, resetChildrenForRestart, resetForRestart, setAutoCheckCancel, setAutoListenCancel, setAutoResetChildren, setBlackboard, setCancelled, setCancelToken, setChild, setCompleted, setControl, setControlData, setDisableDelayNotify, setEnterFrame, setExitFrame, setFailed, setFlags, setGuard, setGuardFailed, setPrevStatus, setSharedProps, setSlowStart, setSuccess, stop, stop, stopRunningChildren, template_checkGuard, template_execute, template_runChild, template_runChildDirectly, template_runHook, template_runHookDirectly, tryLock, unlock, unsetControl
-
构造器详细资料
-
TaskEntry
public TaskEntry() -
TaskEntry
-
-
方法详细资料
-
getName
-
setName
-
getRootTask
-
setRootTask
-
getType
public int getType() -
setType
public void setType(int type) -
setEntity
-
getTreeLoader
-
getHandler
-
setHandler
-
setTreeLoader
-
getEntity
从类复制的说明:Task获取行为树绑定的实体 -- 最好让Entity也在黑板中 -
getCurFrame
public final int getCurFrame()从类复制的说明:Task获取当前的帧号- 覆盖:
getCurFrame在类中Task<T>
-
getRootStateMachine
获取根状态机 状态机太重要了,值得我们为其提供各种快捷方法 -
update
public void update(int curFrame) 用户需要在每一帧调用该方法以驱动心跳逻辑 -
execute
protected void execute()从类复制的说明:TaskTask的心跳方法,在Task进入完成状态之前会反复执行。 1.可以根据Task.isExecuteTriggeredByEnter()判断是否是与Task.enter(int)连续执行的。 2.运行中可通过Task.setSuccess()、Task.setFailed(int)()}、Task.setCancelled()将自己更新为完成状态。 3.不建议直接调用该方法,而是通过模板方法运行。 -
onChildRunning
从类复制的说明:Task子节点还需要继续运行 1.child在运行期间只会通知一次 2.该方法不应该触发状态迁移,即不应该使自己进入完成状态- 指定者:
onChildRunning在类中Task<T>
-
onChildCompleted
从类复制的说明: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
从类复制的说明:Task该方法用于测试自己的状态和事件数据 如果通过条件Task来实现事件过滤,那么通常的写法如下:blackboard.set("event", event); // task通过黑板获取事件对象 try { return template_checkGuard(eventFilter); } finally { blackboard.remove("event"); }ps: 如果想支持编辑器中测试事件属性,event通常需要实现为KV结构。- 覆盖:
canHandleEvent在类中Task<T>
-
onEventImpl
从类复制的说明: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
- 覆盖:
indexChild在类中Task<T>- 返回:
- index or -1
-
childStream
从类复制的说明:Task该接口主要用于测试,该接口有一定的开销- 指定者:
childStream在类中Task<T>
-
getChildCount
public final int getChildCount()从类复制的说明:Task子节点的数量(仅包括普通意义上的child,不包括钩子任务)- 指定者:
getChildCount在类中Task<T>
-
getChild
从类复制的说明:Task获取指定索引的child -
addChildImpl
- 指定者:
addChildImpl在类中Task<T>- 返回:
- 为child分配的index
-
setChildImpl
- 指定者:
setChildImpl在类中Task<T>- 返回:
- 索引位置旧的child
-
removeChildImpl
- 指定者:
removeChildImpl在类中Task<T>- 返回:
- index对应的child
-