行为树新增StepSequence
Posted: 2024/09/04 11:20
希望行为树新增StepSequence,如图例可以实现输出"a" "b1" "a" "b2" "a" "b1"
Support Forum
https://logictoolkit-forum.caitsithware.com/
https://logictoolkit-forum.caitsithware.com/viewtopic.php?t=23
StepSequence似乎并不需要“自己节点的父节点”来确定如何执行“自己节点的子节点”,StepSequence只需要记录一个Index,就可以判断需要执行哪一个子节点。caitsithware wrote: ↑2024/09/04 11:55 该提案将取决于“自己节点的父节点”来确定如何执行“自己节点的子节点”,从而使行为树不那么通用。
首先请重新考虑一下是否有必要使用行为树。
Code: Select all
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using LogicToolkit;
[System.Serializable]
public class StepTask : TaskComponent, IPauseReceiver
{
[SerializeField]
[FieldPlacement(FieldPlacement.Top)]
private List<OutputExecutePort> _Steps;
private int _Index;
private OutputExecutePort _Current;
private TaskStatus _TaskStatus;
protected override void OnActivated()
{
_Current = _Steps[_Index];
_TaskStatus = TaskStatus.Running;
if (_Current == null || !_Current.Play(OnExit))
{
_TaskStatus = TaskStatus.Failure;
}
}
bool OnExit(OutputExecutePort execute, FlowExitNode exitNode)
{
_Index = (_Index + 1) % _Steps.Count;
if (exitNode == null
|| exitNode is ExitNode)
{
_TaskStatus = TaskStatus.Success;
return true;
}
return false;
}
protected override TaskStatus OnExecute()
{
_Current?.Update();
return _TaskStatus;
}
void IPauseReceiver.OnPause(bool pause)
{
if (pause)
{
_Current?.Pause();
}
else
{
_Current?.Resume();
}
}
}
自己写一个StepTask可能是不错的方式,如果父节点是一个行为树节点,似乎只需要再加一个ExecuteTask就可以了
收起Steps列表,关闭Logic编辑器再打开Logic编辑器,会显示连线错误caitsithware wrote: ↑2024/09/04 13:54 您可以使用 OutputExecutePort 创建一个 TaskComponent。
例如,创建如下所示的脚本。
StepTask.pngCode: Select all
using System.Collections; using System.Collections.Generic; using UnityEngine; using LogicToolkit; [System.Serializable] public class StepTask : TaskComponent, IPauseReceiver { [SerializeField] [FieldPlacement(FieldPlacement.Top)] private List<OutputExecutePort> _Steps; private int _Index; private OutputExecutePort _Current; private TaskStatus _TaskStatus; protected override void OnActivated() { _Current = _Steps[_Index]; _TaskStatus = TaskStatus.Running; if (_Current == null || !_Current.Play(OnExit)) { _TaskStatus = TaskStatus.Failure; } } bool OnExit(OutputExecutePort execute, FlowExitNode exitNode) { _Index = (_Index + 1) % _Steps.Count; if (exitNode == null || exitNode is ExitNode) { _TaskStatus = TaskStatus.Success; return true; } return false; } protected override TaskStatus OnExecute() { _Current?.Update(); return _TaskStatus; } void IPauseReceiver.OnPause(bool pause) { if (pause) { _Current?.Pause(); } else { _Current?.Resume(); } } }
Code: Select all
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using LogicToolkit;
[System.Serializable]
public class StepTask : TaskComponent, IPauseReceiver
{
[SerializeField]
[FieldPlacement(FieldPlacement.Top)]
private List<OutputExecutePort> _Steps;
private int _Index;
private OutputExecutePort _Current;
private TaskStatus _TaskStatus;
protected override void OnActivated()
{
_Current = _Steps[_Index];
_TaskStatus = TaskStatus.Running;
if (_Current == null || !_Current.Play(OnExit))
{
_TaskStatus = TaskStatus.Failure;
}
}
bool OnExit(OutputExecutePort execute, FlowExitNode exitNode)
{
_Index = (_Index + 1) % _Steps.Count;
if (exitNode == null
|| exitNode is ExitNode)
{
_TaskStatus = TaskStatus.Success;
return true;
}
return false;
}
protected override TaskStatus OnExecute()
{
_Current?.Update();
return _TaskStatus;
}
protected override void OnDeactivated()
{
base.OnDeactivated();
_Current?.Stop();
}
void IPauseReceiver.OnPause(bool pause)
{
if (pause)
{
_Current?.Pause();
}
else
{
_Current?.Resume();
}
}
}