美文网首页
2020-09-23【BT】Behavior Designer学

2020-09-23【BT】Behavior Designer学

作者: 持刀的要迟到了 | 来源:发表于2020-09-23 16:46 被阅读0次

修饰节点

生命周期

1.先执行父节点的 CanExecute

如果返回成功,那么直接会在本帧,执行子节点。
子节点执行到Running,又会在本帧再次执行 CanExecute

2.然后会执行OverrideStatus
此方法,会传参一个,子节点当前执行状态。
如果子节点未执行,会一直提供一个Inactive。

Log证明:


Test:

现在有一个这样的需求:

  • 在一秒钟之内,持续调用该节点。(需要一个计时器,超时,不允许执行,且返回执行成功)
  • 如果子节点不在执行,那么不断的执行本节点逻辑;如果子节点在执行,不执行本节点逻辑。
  • 如果该节点满足某个条件(testBool == true),那么就执行一次子节点,子节点执行结束后,还原该条件(testBool = false)

思路:
由上面的测试可以知道

  • CanExecute的执行顺序是最先的,子节点的执行顺序第二,OverrideStatus的执行顺序最后。
  • 当CanExecute返回false的时候,子节点不会执行。OverrideStatus会照常执行。
  • 当CanExecute返回true的时候,子节点执行一次后,会立刻再次调用CanExecute。
  • 子节点开始执行,会调用OnChildStarted()
  • 子节点执行完一次,会调用OnChildExecuted(TaskStatus childStatus)

1.由于CanExecute是第一个执行的。因此本节点逻辑应写在此间。
但是当子节点执行后,会再次调用此方法。因此,当子节点未开始执行时,才能执行本节点逻辑。
本节点逻辑,有几率修改testBool条件。本处,会根据按键向列表中加项。
执行完本节点逻辑后,会判断列表中是否有项,有项,则可执行子节点。
2.子节点执行完毕后,需要知道子节点当前是否都已经完成。如果子节点全部执行结束,那么还原条件(testBool = false)

    public override bool CanExecute()
    {
        // 子节点未执行,可执行本节点逻辑
        if(!childExecuting)
        {
            DLogic();
        }

        return DCanExec();
    }

    public override void OnChildStarted()
    {
        childExecuting = true;
    }

    public override void OnEnd()
    {
        childExecuting = false;
    }

    public override void OnChildExecuted(TaskStatus childStatus)
    {
        // 子节点执行成功,还原条件
        if(childStatus == TaskStatus.Success)
        {
            DReset();
        }

        base.OnChildExecuted(childStatus);
    }

    // 本节点逻辑,当子节点未执行时,每帧都先执行此逻辑,然后判定子节点是否可以执行。
    private void DLogic()
    {
        if (Input.GetKeyDown(KeyCode.P))
        {
            dmgList.Add(1);
            dmgList.Add(2);
        }
    }
    // 子节点执行条件重置
    private void DReset()
    {
        dmgList.Clear();
    }
    // 判定子节点是否可以执行
    private bool DCanExec()
    {
        // 列表中有项,就可以执行子节点
        return dmgList.Count > 0;
    }

3.需要满足一个条件,子节点未执行时,本节点一直在running。
子节点执行时,本节点还是需要running。当超时后,才返回success。
当子节点执行结束,本节点需要重置数据,以便子节点可以再次执行。(上面已经做了,OnChildExecuted)

完整代码:

using BehaviorDesigner.Runtime;
using BehaviorDesigner.Runtime.Tasks;
using System.Collections.Generic;
using UnityEngine;

public class BTMeleeCasting : Decorator
{
    public SharedFloat waitTime = 1;
    private float waitDuration;
    private float startTime;

    private bool childExecuting = false;
    public List<int> dmgList = new List<int>();


    public override int MaxChildren()
    {
        return 1;
    }


    public override void OnStart()
    {
        startTime = Time.time;
        waitDuration = waitTime.Value;
    }

    public override bool CanExecute()
    {
        // 子节点未执行,可执行本节点逻辑
        if(!childExecuting)
        {
            DLogic();
        }

        return DCanExec();
    }

    public override void OnChildStarted()
    {
        childExecuting = true;
    }

    public override void OnEnd()
    {
        childExecuting = false;
    }

    public override void OnChildExecuted(TaskStatus childStatus)
    {
        // 子节点执行成功,还原条件
        if(childStatus == TaskStatus.Success)
        {
            DReset();
        }

        base.OnChildExecuted(childStatus);
    }

    // 本节点逻辑,当子节点未执行时,每帧都先执行此逻辑,然后判定子节点是否可以执行。
    private void DLogic()
    {
        if (Input.GetKeyDown(KeyCode.P))
        {
            dmgList.Add(1);
            dmgList.Add(2);
        }
    }
    // 子节点执行条件重置
    private void DReset()
    {
        dmgList.Clear();
    }
    // 判定子节点是否可以执行
    private bool DCanExec()
    {
        // 超时,不可执行子节点
        if (startTime + waitDuration < Time.time)
        {
            return false;
        }
        // 列表中有项,就可以执行子节点
        return dmgList.Count > 0;
    }


    public override TaskStatus OverrideStatus(TaskStatus status)
    {
        // 超时,返回成功
        if (startTime + waitDuration < Time.time)
        {
            return TaskStatus.Success;
        }
        // 否则就一直跑,或者子节点失败,返回失败。
        else
        {
            if(status == TaskStatus.Failure)
            {
                return TaskStatus.Failure;
            }
            return TaskStatus.Running;
        }
    }
}

测试方式及预测:
按压P键位,会执行一次子节点,再按压P,再次执行子节点。
当超时,全部返回。

相关文章

网友评论

      本文标题:2020-09-23【BT】Behavior Designer学

      本文链接:https://www.haomeiwen.com/subject/qfroyktx.html