- 1.png (76.09 KiB) Viewed 16304 times
行为树新增StepSequence
行为树新增StepSequence
希望行为树新增StepSequence,如图例可以实现输出"a" "b1" "a" "b2" "a" "b1"
- caitsithware
- 管理人
- Posts: 90
- Joined: 2024/03/26 01:56
Re: 行为树新增StepSequence
该提案将取决于“自己节点的父节点”来确定如何执行“自己节点的子节点”,从而使行为树不那么通用。
首先请重新考虑一下是否有必要使用行为树。
首先请重新考虑一下是否有必要使用行为树。
Re: 行为树新增StepSequence
StepSequence似乎并不需要“自己节点的父节点”来确定如何执行“自己节点的子节点”,StepSequence只需要记录一个Index,就可以判断需要执行哪一个子节点。caitsithware wrote: ↑2024/09/04 11:55 该提案将取决于“自己节点的父节点”来确定如何执行“自己节点的子节点”,从而使行为树不那么通用。
首先请重新考虑一下是否有必要使用行为树。
如图上的方式来实现,节点会比较多。StepSequence确实没有Sequence和Selector那么常用,最初我准备自己实现StepSequence,但是发现CompositeComponent是internal。
- caitsithware
- 管理人
- Posts: 90
- Joined: 2024/03/26 01:56
Re: 行为树新增StepSequence
您可以使用 OutputExecutePort 创建一个 TaskComponent。
例如,创建如下所示的脚本。
例如,创建如下所示的脚本。
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();
}
}
}
- caitsithware
- 管理人
- Posts: 90
- Joined: 2024/03/26 01:56
Re: 行为树新增StepSequence
主要问题是该图没有显示该组件维护其子节点的执行索引。
组件的复杂性也会根据是否中途重置而增加。
目前,请创建您自己的脚本来处理该问题。
组件的复杂性也会根据是否中途重置而增加。
目前,请创建您自己的脚本来处理该问题。
Re: 行为树新增StepSequence
自己写一个StepTask可能是不错的方式,如果父节点是一个行为树节点,似乎只需要再加一个ExecuteTask就可以了
Re: 行为树新增StepSequence
收起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(); } } }
- caitsithware
- 管理人
- Posts: 90
- Joined: 2024/03/26 01:56
Re: 行为树新增StepSequence
这是由于 Unity 内部规范造成的问题。
“当 Foldout 关闭时,不会构建内部 UI,因此你不知道 Foldout 内部的电线连接在哪里。”
如果展开它,将显示端口,您可以确认它已连接。
我创建了一个编辑器扩展,以便 Foldout 不用于 If 节点等内容。
我们还将考虑将此编辑器扩展用于用户脚本。
“当 Foldout 关闭时,不会构建内部 UI,因此你不知道 Foldout 内部的电线连接在哪里。”
如果展开它,将显示端口,您可以确认它已连接。
我创建了一个编辑器扩展,以便 Foldout 不用于 If 节点等内容。
我们还将考虑将此编辑器扩展用于用户脚本。
- caitsithware
- 管理人
- Posts: 90
- Joined: 2024/03/26 01:56
Re: 行为树新增StepSequence
我忘记用 OnDeactivated 停止执行。
修改后的脚本如下。
修改后的脚本如下。
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();
}
}
}