Estou tentando entender as árvores de comportamento, então estou criando um código de teste. Uma coisa com a qual estou lutando é como antecipar um nó em execução no momento quando surgir algo de maior prioridade.
Considere a seguinte árvore de comportamento simples e fictícia para um soldado:
Suponha que um número de tiques tenha passado e que não havia nenhum inimigo por perto, o soldado estava de pé na grama, portanto o nó Sentar-se é selecionado para execução:
Agora, a ação Sentar leva tempo para ser executada porque há uma animação a ser reproduzida; portanto, ela retorna Running
como seu status. Um carrapato ou dois passam, a animação ainda está em execução, mas o Inimigo está próximo? disparos do nó de condição. Agora, precisamos antecipar o nó Sentar o mais rápido possível, para que possamos executar o nó Ataque . Idealmente, o soldado nem terminaria de sentar - ele poderia reverter sua direção de animação se apenas começasse a sentar. Para aumentar o realismo, se ele passou de algum ponto crítico na animação, poderíamos optar por deixá-lo terminar de sentar e ficar de pé novamente, ou talvez fazê-lo tropeçar na pressa de reagir à ameaça.
Por mais que eu tente, não consegui encontrar orientações sobre como lidar com esse tipo de situação. Toda a literatura e vídeos que eu consumi nos últimos dias (e tem sido muito) parecem contornar esse problema. A coisa mais próxima que pude encontrar foi esse conceito de redefinir nós em execução, mas isso não dá a nós como o Sit a chance de dizer "ei, ainda não terminei!"
Pensei em talvez definindo um Preempt()
ou Interrupt()
método em minha base de Node
classe. Nós diferentes podem lidar com isso da maneira que acharem melhor, mas, neste caso, tentaríamos colocar o soldado de pé o mais rápido possível e depois voltar Success
. Eu acho que essa abordagem também exigiria que minha base Node
tenha o conceito de condições separadamente para outras ações. Dessa forma, o mecanismo pode verificar apenas as condições e, se elas passarem, antecipar qualquer nó em execução no momento antes de iniciar a execução das ações. Se essa diferenciação não fosse estabelecida, o mecanismo precisaria executar nós indiscriminadamente e, portanto, poderia disparar uma nova ação antes de antecipar a execução.
Para referência, abaixo estão minhas classes base atuais. Novamente, este é um pico, por isso tentei manter as coisas o mais simples possível e adicionar complexidade apenas quando eu precisar e quando eu entender, e é com isso que estou lutando agora.
public enum ExecuteResult
{
// node needs more time to run on next tick
Running,
// node completed successfully
Succeeded,
// node failed to complete
Failed
}
public abstract class Node<TAgent>
{
public abstract ExecuteResult Execute(TimeSpan elapsed, TAgent agent, Blackboard blackboard);
}
public abstract class DecoratorNode<TAgent> : Node<TAgent>
{
private readonly Node<TAgent> child;
protected DecoratorNode(Node<TAgent> child)
{
this.child = child;
}
protected Node<TAgent> Child
{
get { return this.child; }
}
}
public abstract class CompositeNode<TAgent> : Node<TAgent>
{
private readonly Node<TAgent>[] children;
protected CompositeNode(IEnumerable<Node<TAgent>> children)
{
this.children = children.ToArray();
}
protected Node<TAgent>[] Children
{
get { return this.children; }
}
}
public abstract class ConditionNode<TAgent> : Node<TAgent>
{
private readonly bool invert;
protected ConditionNode()
: this(false)
{
}
protected ConditionNode(bool invert)
{
this.invert = invert;
}
public sealed override ExecuteResult Execute(TimeSpan elapsed, TAgent agent, Blackboard blackboard)
{
var result = this.CheckCondition(agent, blackboard);
if (this.invert)
{
result = !result;
}
return result ? ExecuteResult.Succeeded : ExecuteResult.Failed;
}
protected abstract bool CheckCondition(TAgent agent, Blackboard blackboard);
}
public abstract class ActionNode<TAgent> : Node<TAgent>
{
}
Alguém tem alguma idéia que possa me orientar na direção certa? O meu pensamento está na linha certa, ou é tão ingênuo quanto eu temo?
Stop()
retorno de chamada antes de sair dos nós ativos)