Einfache Implementierung des Einheitsverhaltensbaums

Vorwort

Behavior Tree , auf Englisch Behavior Tree, kurz BT, ist eine Baumstruktur, die hierarchische Knoten enthält, die zur Steuerung des KI-Entscheidungsverhaltens verwendet werden. Wenn wir entscheiden möchten, welches Verhalten der aktuelle Soldat ausführen wird, durchsuchen wir den Baum von oben nach unten nach einigen Bedingungen und bestimmen schließlich das Verhalten (Blattknoten), das ausgeführt werden muss, und führen es aus. Dies ist das Grundprinzip des Verhaltensbaums.

Text
Ohne weitere Umschweife gehen Sie direkt zum Code, unten ist das erste Skript.

using UnityEngine;

namespace MDD.AI {
    
    

    //声明一个枚举

    public enum NodeState
    {
    
    
        Successufully,
        Failure,
        Running
    }

    // 创建一个 抽象函数 供子类调用
    public abstract class BTNode 
    {
    
    
        public abstract NodeState Tick();
    }

    //

    public  abstract class BTBifurcate : BTNode
    {
    
    
        protected List<BTNode> ChildNode = new List<BTNode>();

        protected int currentChild = 0;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="chlidNode">BTNode类型的任意多个参数</param>
        /// <returns></returns>
        public virtual BTBifurcate open(params BTNode [] chlidNode) 
        {
    
    
            for (int i = 0; i < chlidNode.Length; ++i)
            {
    
    
                ChildNode.Add(chlidNode[i]);
            }
            
            return this;
            
        }
    }


    /// <summary>
    ///  顺序节点,依次执行所有的子节点,当有一个子节点主执行失败的时候就不会继续执行后面的节点
    /// </summary>
    public class BTSequential : BTBifurcate
    {
    
    
        public override NodeState Tick()
        {
    
    
            var childNode = ChildNode[currentChild].Tick();

            switch (childNode) 
            {
    
    
                case NodeState.Successufully:
                    currentChild++;
                    if (currentChild == ChildNode.Count) {
    
    
                        currentChild = 0;
                    }
                    return NodeState.Successufully;
                case NodeState.Failure:
                    currentChild = 0;
                    return NodeState.Failure;
                case NodeState.Running:
                    return NodeState.Running;
            }
            return NodeState.Successufully;
        }
    }

    /// <summary>
    /// 选择节点,依次执行所有的节点, 只要有一个节点执行成功就不执行后续的节点了
    /// </summary>
    public class BTSelect : BTBifurcate
    {
    
    
        public override NodeState Tick()
        {
    
    
            var childNode = ChildNode[currentChild].Tick();

            switch (childNode)
            {
    
    
                case NodeState.Successufully:
                    currentChild = 0;
                    return NodeState.Successufully;
                case NodeState.Failure:
                    currentChild++;
                    if (currentChild == ChildNode.Count)
                    {
    
    
                        currentChild = 0;
                    }
                    return NodeState.Failure;
                case NodeState.Running:
                    return NodeState.Running;
            }
            return NodeState.Failure;
        }
    }
    //循环一直进行循环可以一直执行某一个行为知道条件改变
    public class BTLoopNode : BTBifurcate
    {
    
    
        public override NodeState Tick()
        {
    
    
            var childNode = ChildNode[currentChild].Tick();
            while (true) 
            {
    
    
                switch (childNode)
                {
    
    
                    case NodeState.Running:
                        return NodeState.Running;
                    default:
                        currentChild++;
                        if (currentChild == ChildNode.Count)
                        {
    
    
                            currentChild = 0;
                            return NodeState.Successufully;
                        }
                   continue;
                }
            }

        }
    }

// 条件
    public abstract class BTconditionNode : BTNode {
    
     }
//动作/行为
    public abstract class BTActionNode : BTNode {
    
     }
}

Als nächstes folgt das zweite Skript

using UnityEngine;
using MDD.AI;

public class BehaviourTree : MonoBehaviour
{
    
    
    protected BTLoopNode m_Root;

    protected virtual void Start()
    {
    
    
        m_Root = new BTLoopNode();
    }

    protected virtual void Update()
    {
    
    
        m_Root.Tick();
    }

    protected void AddNode(params BTNode[] child) 
    {
    
    
        m_Root.open(child);
    }
}

Zu diesem Zeitpunkt ist der Verhaltensbaum ungefähr fertig und der nächste Schritt ist das Testskript.
Hier habe ich zwei Verhaltensskripte und ein bedingtes Skript vorbereitet.

using System;
using UnityEngine;
using MDD.AI;
public class BTAction_01 : BTActionNode
{
    
    
//行为脚本
   /// <summary>
    /// 把这个函数当作mono的一个动作
    /// </summary>
    /// <returns></returns>
    public override NodeState Tick()
    {
    
    
        OnAction();
        return NodeState.Successufully;
    }

    private void OnAction() 
    {
    
    
        Debug.Log("动作11");
    }
}
using System;
using UnityEngine;
using MDD.AI;


public class BTAction_02 : BTActionNode
{
    
    
 //行为脚本
    /// <summary>
    /// 把这个函数当作mono的一个动作
    /// </summary>
    /// <returns></returns>
    public override NodeState Tick()
    {
    
    
        OnAction();
        return NodeState.Successufully;
    }
    private void OnAction()
    {
    
    
        Debug.Log("动作22");
    }
}
using System;
using UnityEngine;
using MDD.AI;
public class BTconNode : BTconditionNode
{
    
    
//声明一个委托
    private Func<bool> func;

    public BTconNode(Func<bool> _func)
    {
    
    
        func = _func;
    }
    public override NodeState Tick()
    {
    
    
        if (func != null)
        {
    
    
            return (func.Invoke()) ? NodeState.Successufully : NodeState.Failure;
        }
        return NodeState.Failure;
    }
}

Als nächstes folgt das genaue Testskript

using System;
using MDD.AI;
using UnityEngine;

public class TestBT : BehaviourTree
{
    
    

    public bool b;
    protected override void Start()
    {
    
    
        base.Start();

        AddNode(new BTSelect().open(new BTSequential().open(new BTconNode(testBool),new BTAction_01()),new BTAction_02()));
    }

    public bool testBool() 
    {
    
    
        Debug.Log("我是test");
        return b;
    }
}

Sie können den Wert von b im Inspektor ändern, um die gedruckten Werte zu beobachten und den einfachen Verhaltensbaum oben besser zu verstehen.

おすすめ

転載: blog.csdn.net/m0_52021450/article/details/129220051