91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C#/基于Unity 行為樹的實現步驟

發布時間:2020-10-23 16:16:19 來源:億速云 閱讀:119 作者:小新 欄目:編程語言

這篇文章主要介紹了C#/基于Unity 行為樹的實現步驟,具有一定借鑒價值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。

using BTAI;
using UnityEngine;

public class TestBT : MonoBehaviour, BTAI.IBTDebugable
{
    Root aiRoot = BT.Root();


    private void OnEnable()
    {
        aiRoot.OpenBranch(
                BT.If(TestVisibleTarget).OpenBranch(
                BT.Call(Aim),
                BT.Call(Shoot)
                 ),
                BT.Sequence().OpenBranch(
                BT.Call(Walk),
                BT.Wait(5.0f),
                BT.Call(Turn),
                BT.Wait(1.0f),
                BT.Call(Turn)
             )
        );
    }

    private void Turn()
    {
        Debug.Log("執行了 Turn");
    }

    private void Walk()
    {
        Debug.Log("執行了 Walk");
    }

    private void Shoot()
    {
        Debug.Log("執行了 Shoot");
    }

    private void Aim()
    {
        Debug.Log("執行了 Aim");
    }

    private bool TestVisibleTarget()
    {
        var isSuccess = UnityEngine.Random.Range(0, 2) == 1;
        Debug.Log("執行了 TestVisibleTarget    Result:" + isSuccess);

        return isSuccess;
    }

    private void Update()
    {
        aiRoot.Tick();
    }

    public Root GetAIRoot()
    {
        return aiRoot;
    }
}

C#/基于Unity 行為樹的實現步驟

using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 這只是腳本系統
/// 行為樹會從Root節點開始遍歷子節點。Update中執行
/// 每個節點都有相關的操作,但是基本上就是返回三種狀態
/// ● Success: 節點成功完成任務
/// ● Failure: 節點未通過任務
/// ● Continue:節點尚未完成任務。
/// 但是每個節點的父節點對子節點的結果處理方式還不同。  例如
/// ● Test 節點: 測試節點將調用其子節點并在測試為真時返回子節點狀態,如果測試為假,則返回Failure而不調用其子節點。
/// 行為樹的一種構造方式如下:
/// Root aiRoot = BT.Root(); 
/// aiRoot.Do(  
/// BT.If(TestVisibleTarget).Do(
///  BT.Call(Aim),
///  BT.Call(Shoot)
///  ),
///  BT.Sequence().Do(
///  BT.Call(Walk),
///  BT.Wait(5.0f),
///  BT.Call(Turn),
///  BT.Wait(1.0f),
///  BT.Call(Turn)
///  )
/// ); 
///然后在Update中 調用   aiRoot.Tick() 。  剛剛構造的行為樹是怎么樣的檢查過程呢?  
///1、首先檢查TestVisibleTarget是否返回Ture,如果是繼續執行子節點執行Aim函數和Shoot函數
///2、TestVisibleTarget是否返回false,if節點將返回Failure, 然后Root 將轉向下一個子節點。這是個Sequence節點,它從執行第一個子節點開始。
///   1)將調用Walk函數,直接返回 Success,以便Sequence將下一個子節點激活并執行它。
///   2)執行Wait 節點,只是要等待5秒,還是第一次調用,所以肯定返回Running狀態, 當Sequence從子節點上得到Running狀態時,不會更改激活的子節點索引,下次Update的時候還是從這個節點開始執行
///3、Update的執行,當Wait節點等待的時間到了的時候,將會返回Success, 以便序列將轉到下一個孩子。
///腳本中的Node列表 
/// Sequence:
//一個接一個地執行子節點。如果子節點返回:
//●Success:Sequence將選擇下一幀的下一個孩子開始。
//●Failure:Sequence將返回到下一幀的第一個子節點(從頭開始)。
//●Continue:Sequence將在下一幀再次調用該節點。
//RandomSequence:
// 每次調用時,從子列表中執行一個隨機子節點。您可以在構造函數中指定要應用于每個子項的權重列表作為int數組,以使某些子項更有可能被選中。
//Selector :
//按順序執行所有子項,直到一個返回Success,然后退出而不執行其余子節點。如果沒有返回Success,則此節點將返回Failure。

// Condition :
// 如果給定函數返回true,則此節點返回Success;如果為false,則返回Failure。
// 與其他依賴于子節點結果的節點鏈接時很有用(例如,Sequence,Selector等)
// If :
//調用給定的函數。
// ●如果返回true,則調用當前活動的子級并返回其狀態。
// ●否則,它將在不調用其子項的情況下返回Failure
// While:
//只要給定函數返回true,就返回Continue(因此,下一幀將再次從該節點開始,而不會評估所有先前的節點)。
//子節點們將陸續被執行。
//當函數返回false并且循環中斷時,將返回Failure。
// Call 
//調用給定的函數,它將始終返回Success。是動作節點!
//Repeat 
//將連續執行給定次數的所有子節點。
//始終返回Continue,直到達到計數,并返回Success。
//Wait
//將返回Continue,直到達到給定時間(首次調用時開始),然后返回Success。
//Trigger 
//允許在給定的動畫師animator中設置Trigger參數(如果最后一個參數設置為false,則取消設置觸發器)。始終返回成功。
//SetBool
//允許在給定的animator中設置布爾參數的值。始終返回成功
//SetActive 
//設置給定GameObject的活動/非活動狀態。始終返回成功。
/// </summary>
namespace BTAI
{
    public enum BTState
    {
        Failure,
        Success,
        Continue,
        Abort
    }

    /// <summary>
    /// 節點 對象工廠
    /// </summary>
    public static class BT
    {
        public static Root Root() { return new Root(); }
        public static Sequence Sequence() { return new Sequence(); }
        public static Selector Selector(bool shuffle = false) { return new Selector(shuffle); }
        public static Action RunCoroutine(System.Func<IEnumerator<BTState>> coroutine) { return new Action(coroutine); }
        public static Action Call(System.Action fn) { return new Action(fn); }
        public static ConditionalBranch If(System.Func<bool> fn) { return new ConditionalBranch(fn); }
        public static While While(System.Func<bool> fn) { return new While(fn); }
        public static Condition Condition(System.Func<bool> fn) { return new Condition(fn); }
        public static Repeat Repeat(int count) { return new Repeat(count); }
        public static Wait Wait(float seconds) { return new Wait(seconds); }
        public static Trigger Trigger(Animator animator, string name, bool set = true) { return new Trigger(animator, name, set); }
        public static WaitForAnimatorState WaitForAnimatorState(Animator animator, string name, int layer = 0) { return new WaitForAnimatorState(animator, name, layer); }
        public static SetBool SetBool(Animator animator, string name, bool value) { return new SetBool(animator, name, value); }
        public static SetActive SetActive(GameObject gameObject, bool active) { return new SetActive(gameObject, active); }
        public static WaitForAnimatorSignal WaitForAnimatorSignal(Animator animator, string name, string state, int layer = 0) { return new WaitForAnimatorSignal(animator, name, state, layer); }
        public static Terminate Terminate() { return new Terminate(); }
        public static Log Log(string msg) { return new Log(msg); }
        public static RandomSequence RandomSequence(int[] weights = null) { return new BTAI.RandomSequence(weights); }

    }

    /// <summary>
    /// 節點抽象類
    /// </summary>
    public abstract class BTNode
    {
        public abstract BTState Tick();
    }

    /// <summary>
    /// 包含子節點的組合 節點基類
    /// </summary>
    public abstract class Branch : BTNode
    {
        protected int activeChild;
        protected List<BTNode> children = new List<BTNode>();
        public virtual Branch OpenBranch(params BTNode[] children)
        {
            for (var i = 0; i < children.Length; i++)
                this.children.Add(children[i]);
            return this;
        }

        public List<BTNode> Children()
        {
            return children;
        }

        public int ActiveChild()
        {
            return activeChild;
        }

        public virtual void ResetChildren()
        {
            activeChild = 0;
            for (var i = 0; i < children.Count; i++)
            {
                Branch b = children[i] as Branch;
                if (b != null)
                {
                    b.ResetChildren();
                }
            }
        }
    }

    /// <summary>
    /// 裝飾節點    只包含一個子節點,用于某種方式改變這個節點的行為
    /// 比如過濾器(用于決定是否允許子節點運行的,如:Until Success, Until Fail等),這種節點的子節點應該是條件節點,條件節點一直檢測“視線中是否有敵人”,知道發現敵人為止。
    /// 或者 Limit 節點,用于指定某個子節點的最大運行次數
    /// 或者 Timer節點,設置了一個計時器,不會立即執行子節點,而是等一段時間,時間到了開始執行子節點
    /// 或者 TimerLimit節點,用于指定某個子節點的最長運行時間。
    /// 或者 用于產生某個返回狀態,
    /// </summary>
    public abstract class Decorator : BTNode
    {
        protected BTNode child;
        public Decorator Do(BTNode child)
        {
            this.child = child;
            return this;
        }
    }

    /// <summary>
    /// 順序節點 (從左到右依次執行所有子節點,只要子節點返回Success就繼續執行后續子節點,直到遇到Failure或者Runing, 
    /// 停止后續執行,并把這個節點返回給父節點,只有它的所有子節點都是Success他才會向父節點返回Success)
    /// </summary>
    public class Sequence : Branch
    {
        public override BTState Tick()
        {
            var childState = children[activeChild].Tick();
            switch (childState)
            {
                case BTState.Success:
                    activeChild++;
                    if (activeChild == children.Count)
                    {
                        activeChild = 0;
                        return BTState.Success;
                    }
                    else
                        return BTState.Continue;
                case BTState.Failure:
                    activeChild = 0;
                    return BTState.Failure;
                case BTState.Continue:
                    return BTState.Continue;
                case BTState.Abort:
                    activeChild = 0;
                    return BTState.Abort;
            }
            throw new System.Exception("This should never happen, but clearly it has.");
        }
    }

    /// <summary>
    /// 選擇節點從左到右依次執行所有子節點 ,只要遇到failure就繼續執行后續子節點,直到遇到一個節點返回Success或Running為止。向父節點返回Success或Running
    /// 所有子節點都是Fail, 那么向父節點凡湖Fail
    /// 選擇節點 用來在可能的行為集合中選擇第一個成功的。 比如一個試圖躲避槍擊的AI角色, 它可以通過尋找隱蔽點, 或離開危險區域, 或尋找援助等多種方式實現目標。
    /// 利用選擇節點,他會嘗試尋找Cover,失敗后在試圖逃離危險區域。
    /// </summary>
    public class Selector : Branch
    {
        public Selector(bool shuffle)
        {
            if (shuffle)
            {
                var n = children.Count;
                while (n > 1)
                {
                    n--;
                    var k = Mathf.FloorToInt(Random.value * (n + 1));
                    var value = children[k];
                    children[k] = children[n];
                    children[n] = value;
                }
            }
        }

        public override BTState Tick()
        {
            var childState = children[activeChild].Tick();
            switch (childState)
            {
                case BTState.Success:
                    activeChild = 0;
                    return BTState.Success;
                case BTState.Failure:
                    activeChild++;
                    if (activeChild == children.Count)
                    {
                        activeChild = 0;
                        return BTState.Failure;
                    }
                    else
                        return BTState.Continue;
                case BTState.Continue:
                    return BTState.Continue;
                case BTState.Abort:
                    activeChild = 0;
                    return BTState.Abort;
            }
            throw new System.Exception("This should never happen, but clearly it has.");
        }
    }

    /// <summary>
    /// 行為節點  調用方法,或運行協程。完成實際工作, 例如播放動畫,讓角色移動位置,感知敵人,更換武器,播放聲音,增加生命值等。
    /// </summary>
    public class Action : BTNode
    {
        System.Action fn;
        System.Func<IEnumerator<BTState>> coroutineFactory;
        IEnumerator<BTState> coroutine;
        public Action(System.Action fn)
        {
            this.fn = fn;
        }
        public Action(System.Func<IEnumerator<BTState>> coroutineFactory)
        {
            this.coroutineFactory = coroutineFactory;
        }
        public override BTState Tick()
        {
            if (fn != null)
            {
                fn();
                return BTState.Success;
            }
            else
            {
                if (coroutine == null)
                    coroutine = coroutineFactory();
                if (!coroutine.MoveNext())
                {
                    coroutine = null;
                    return BTState.Success;
                }
                var result = coroutine.Current;
                if (result == BTState.Continue)
                    return BTState.Continue;
                else
                {
                    coroutine = null;
                    return result;
                }
            }
        }

        public override string ToString()
        {
            return "Action : " + fn.Method.ToString();
        }
    }

    /// <summary>
    /// 條件節點   調用方法,如果方法返回true則返回成功,否則返回失敗。
    /// 用來測試當前是否滿足某些性質或條件,例如“玩家是否在20米之內?”“是否能看到玩家?”“生命值是否大于50?”“彈藥是否足夠?”等
    /// </summary>
    public class Condition : BTNode
    {
        public System.Func<bool> fn;

        public Condition(System.Func<bool> fn)
        {
            this.fn = fn;
        }
        public override BTState Tick()
        {
            return fn() ? BTState.Success : BTState.Failure;
        }

        public override string ToString()
        {
            return "Condition : " + fn.Method.ToString();
        }
    }

    /// <summary>
    /// 當方法為True的時候 嘗試執行當前  子節點
    /// </summary>
    public class ConditionalBranch : Block
    {
        public System.Func<bool> fn;
        bool tested = false;
        public ConditionalBranch(System.Func<bool> fn)
        {
            this.fn = fn;
        }
        public override BTState Tick()
        {
            if (!tested)
            {
                tested = fn();
            }
            if (tested)
            {
                // 當前子節點執行完就進入下一個節點(超上限就返回到第一個)
                var result = base.Tick();
                // 沒執行完
                if (result == BTState.Continue)
                    return BTState.Continue;
                else
                {
                    tested = false;
                    // 最后一個子節點執行完,才會為Ture
                    return result;
                }
            }
            else
            {
                return BTState.Failure;
            }
        }

        public override string ToString()
        {
            return "ConditionalBranch : " + fn.Method.ToString();
        }
    }

    /// <summary>
    /// While節點   只要方法  返回True 就執行所有子節點, 否則返回 Failure
    /// </summary>
    public class While : Block
    {
        public System.Func<bool> fn;

        public While(System.Func<bool> fn)
        {
            this.fn = fn;
        }

        public override BTState Tick()
        {
            if (fn())
                base.Tick();
            else
            {
                //if we exit the loop
                ResetChildren();
                return BTState.Failure;
            }

            return BTState.Continue;
        }

        public override string ToString()
        {
            return "While : " + fn.Method.ToString();
        }
    }

    /// <summary>
    /// 阻塞節點  如果當前子節點是Continue 說明沒有執行完,阻塞著,執行完之后在繼續它后面的兄弟節點 不管成功失敗。
    /// 如果當前結點是最后一個節點并執行完畢,說明成功!否則就是處于Continue狀態。 
    /// 幾個基本上是抽象節點, 像是讓所有子節點都執行一遍, 當前子節點執行完就進入下一個節點(超上限就返回到第一個)
    /// </summary>
    public abstract class Block : Branch
    {
        public override BTState Tick()
        {
            switch (children[activeChild].Tick())
            {
                case BTState.Continue:
                    return BTState.Continue;
                default:
                    activeChild++;
                    if (activeChild == children.Count)
                    {
                        activeChild = 0;
                        return BTState.Success;
                    }
                    return BTState.Continue;
            }
        }
    }

    public class Root : Block
    {
        public bool isTerminated = false;

        public override BTState Tick()
        {
            if (isTerminated) return BTState.Abort;
            while (true)
            {
                switch (children[activeChild].Tick())
                {
                    case BTState.Continue:
                        return BTState.Continue;
                    case BTState.Abort:
                        isTerminated = true;
                        return BTState.Abort;
                    default:
                        activeChild++;
                        if (activeChild == children.Count)
                        {
                            activeChild = 0;
                            return BTState.Success;
                        }
                        continue;
                }
            }
        }
    }

    /// <summary>
    /// 多次運行子節點(一個子節點執行一次就算一次)
    /// </summary>
    public class Repeat : Block
    {
        public int count = 1;
        int currentCount = 0;
        public Repeat(int count)
        {
            this.count = count;
        }
        public override BTState Tick()
        {
            if (count > 0 && currentCount < count)
            {
                var result = base.Tick();
                switch (result)
                {
                    case BTState.Continue:
                        return BTState.Continue;
                    default:
                        currentCount++;
                        if (currentCount == count)
                        {
                            currentCount = 0;
                            return BTState.Success;
                        }
                        return BTState.Continue;
                }
            }
            return BTState.Success;
        }

        public override string ToString()
        {
            return "Repeat Until : " + currentCount + " / " + count;
        }
    }


    /// <summary>
    /// 隨機的順序  執行子節點 
    /// </summary>
    public class RandomSequence : Block
    {
        int[] m_Weight = null;
        int[] m_AddedWeight = null;

        /// <summary>
        /// 每次再次觸發時,將選擇一個隨機子節點
        /// </summary>
        /// <param name="weight">保留null,以便所有子節點具有相同的權重。
        /// 如果權重低于子節點, 則后續子節點的權重都為1</param>
        public RandomSequence(int[] weight = null)
        {
            activeChild = -1;

            m_Weight = weight;
        }

        public override Branch OpenBranch(params BTNode[] children)
        {
            m_AddedWeight = new int[children.Length];

            for (int i = 0; i < children.Length; ++i)
            {
                int weight = 0;
                int previousWeight = 0;

                if (m_Weight == null || m_Weight.Length <= i)
                {//如果沒有那個權重, 就將權重 設置為1
                    weight = 1;
                }
                else
                    weight = m_Weight[i];

                if (i > 0)
                    previousWeight = m_AddedWeight[i - 1];

                m_AddedWeight[i] = weight + previousWeight;
            }

            return base.OpenBranch(children);
        }

        public override BTState Tick()
        {
            if (activeChild == -1)
                PickNewChild();

            var result = children[activeChild].Tick();

            switch (result)
            {
                case BTState.Continue:
                    return BTState.Continue;
                default:
                    PickNewChild();
                    return result;
            }
        }

        void PickNewChild()
        {
            int choice = Random.Range(0, m_AddedWeight[m_AddedWeight.Length - 1]);

            for (int i = 0; i < m_AddedWeight.Length; ++i)
            {
                if (choice - m_AddedWeight[i] <= 0)
                {
                    activeChild = i;
                    break;
                }
            }
        }

        public override string ToString()
        {
            return "Random Sequence : " + activeChild + "/" + children.Count;
        }
    }


    /// <summary>
    /// 暫停執行幾秒鐘。
    /// </summary>
    public class Wait : BTNode
    {
        public float seconds = 0;
        float future = -1;
        public Wait(float seconds)
        {
            this.seconds = seconds;
        }

        public override BTState Tick()
        {
            if (future < 0)
                future = Time.time + seconds;

            if (Time.time >= future)
            {
                future = -1;
                return BTState.Success;
            }
            else
                return BTState.Continue;
        }

        public override string ToString()
        {
            return "Wait : " + (future - Time.time) + " / " + seconds;
        }
    }

    /// <summary>
    /// 設置動畫  trigger 參數
    /// </summary>
    public class Trigger : BTNode
    {
        Animator animator;
        int id;
        string triggerName;
        bool set = true;

        //如果 set == false, 則重置trigger而不是設置它。
        public Trigger(Animator animator, string name, bool set = true)
        {
            this.id = Animator.StringToHash(name);
            this.animator = animator;
            this.triggerName = name;
            this.set = set;
        }

        public override BTState Tick()
        {
            if (set)
                animator.SetTrigger(id);
            else
                animator.ResetTrigger(id);

            return BTState.Success;
        }

        public override string ToString()
        {
            return "Trigger : " + triggerName;
        }
    }

    /// <summary>
    /// 設置動畫 boolean 參數
    /// </summary>
    public class SetBool : BTNode
    {
        Animator animator;
        int id;
        bool value;
        string triggerName;

        public SetBool(Animator animator, string name, bool value)
        {
            this.id = Animator.StringToHash(name);
            this.animator = animator;
            this.value = value;
            this.triggerName = name;
        }

        public override BTState Tick()
        {
            animator.SetBool(id, value);
            return BTState.Success;
        }

        public override string ToString()
        {
            return "SetBool : " + triggerName + " = " + value.ToString();
        }
    }

    /// <summary>
    /// 等待animator達到一個狀態。
    /// </summary>
    public class WaitForAnimatorState : BTNode
    {
        Animator animator;
        int id;
        int layer;
        string stateName;

        public WaitForAnimatorState(Animator animator, string name, int layer = 0)
        {
            this.id = Animator.StringToHash(name);
            if (!animator.HasState(layer, this.id))
            {
                Debug.LogError("The animator does not have state: " + name);
            }
            this.animator = animator;
            this.layer = layer;
            this.stateName = name;
        }

        public override BTState Tick()
        {
            var state = animator.GetCurrentAnimatorStateInfo(layer);
            if (state.fullPathHash == this.id || state.shortNameHash == this.id)
                return BTState.Success;
            return BTState.Continue;
        }

        public override string ToString()
        {
            return "Wait For State : " + stateName;
        }
    }

    /// <summary>
    /// 設置 GameObject 的激活狀態
    /// </summary>
    public class SetActive : BTNode
    {

        GameObject gameObject;
        bool active;

        public SetActive(GameObject gameObject, bool active)
        {
            this.gameObject = gameObject;
            this.active = active;
        }

        public override BTState Tick()
        {
            gameObject.SetActive(this.active);
            return BTState.Success;
        }

        public override string ToString()
        {
            return "Set Active : " + gameObject.name + " = " + active;
        }
    }

    /// <summary>
    /// 等待animator從SendSignal狀態機行為 接收信號。   SendSignal : StateMachineBehaviour
    /// </summary>
    public class WaitForAnimatorSignal : BTNode
    {
        // 進入或退出動畫都為 False, 只有執行中為True
        internal bool isSet = false;
        string name;
        int id;

        public WaitForAnimatorSignal(Animator animator, string name, string state, int layer = 0)
        {
            this.name = name;
            this.id = Animator.StringToHash(name);
            if (!animator.HasState(layer, this.id))
            {
                Debug.LogError("The animator does not have state: " + name);
            }
            else
            {
                SendSignal.Register(animator, name, this);
            }
        }

        public override BTState Tick()
        {
            if (!isSet)
                return BTState.Continue;
            else
            {
                isSet = false;
                return BTState.Success;
            }

        }

        public override string ToString()
        {
            return "Wait For Animator Signal : " + name;
        }
    }

    /// <summary>
    /// 終止節點  切換到中止 狀態
    /// </summary>
    public class Terminate : BTNode
    {

        public override BTState Tick()
        {
            return BTState.Abort;
        }

    }

    /// <summary>
    /// Log  輸出Log 的節點
    /// </summary>
    public class Log : BTNode
    {
        string msg;

        public Log(string msg)
        {
            this.msg = msg;
        }

        public override BTState Tick()
        {
            Debug.Log(msg);
            return BTState.Success;
        }
    }

}

#if UNITY_EDITOR
namespace BTAI
{
    public interface IBTDebugable
    {
        Root GetAIRoot();
    }
}
#endif
using BTAI;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace Gamekit2D
{

    /// <summary>
    /// 運行是查看  行為樹中所有節點的狀態 
    /// </summary>
    public class BTDebug : EditorWindow
    {
        protected BTAI.Root _currentRoot = null;


        [MenuItem("Kit Tools/Behaviour Tree Debug")]
        static void OpenWindow()
        {
            BTDebug btdebug = GetWindow<BTDebug>();
            btdebug.Show();
        }

        private void OnGUI()
        {
            if (!Application.isPlaying)
            {
                EditorGUILayout.HelpBox("Only work during play mode.", MessageType.Info);
            }
            else
            {
                if (_currentRoot == null)
                    FindRoot();
                else
                {
                    RecursiveTreeParsing(_currentRoot, 0, true);
                }
            }
        }

        void Update()
        {
            Repaint();
        }

        void RecursiveTreeParsing(Branch branch, int indent, bool parentIsActive)
        {
            List<BTNode> nodes = branch.Children();

            for (int i = 0; i < nodes.Count; ++i)
            {
                EditorGUI.indentLevel = indent;

                bool isActiveChild = branch.ActiveChild() == i;
                GUI.color = (isActiveChild && parentIsActive) ? Color.green : Color.white;
                EditorGUILayout.LabelField(nodes[i].ToString());

                if (nodes[i] is Branch)
                    RecursiveTreeParsing(nodes[i] as Branch, indent + 1, isActiveChild);
            }
        }

        void FindRoot()
        {
            if (Selection.activeGameObject == null)
            {
                _currentRoot = null;
                return;
            }

            IBTDebugable debugable = Selection.activeGameObject.GetComponentInChildren<IBTDebugable>();

            if (debugable != null)
            {
                _currentRoot = debugable.GetAIRoot();
            }
        }

    }
}

就是在菜單“Kit Tools/Behaviour Tree Debug" 可以查看TestBT.cs 對象所在行為樹

C#/基于Unity 行為樹的實現步驟

感謝你能夠認真閱讀完這篇文章,希望小編分享C#/基于Unity 行為樹的實現步驟對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,遇到問題就找億速云,詳細的解決方法等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

un
AI

石渠县| 通道| 九龙坡区| 边坝县| 新平| 土默特右旗| 陕西省| 读书| 商南县| 彭山县| 巴塘县| 广丰县| 盈江县| 石屏县| 浮梁县| 通辽市| 高要市| 固阳县| 兴仁县| 开封县| 霍城县| 永新县| 万宁市| 石河子市| 虎林市| 博兴县| 乐亭县| 济南市| 汝南县| 兴安县| 屏东市| 高雄县| 和硕县| 庆安县| 永福县| 松潘县| 丘北县| 潮安县| 若羌县| 大城县| 淅川县|