成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

游戲AI(三)—行為樹優(yōu)化之基于事件的行為樹

vvpvvp / 1553人閱讀

摘要:上一篇我們講到了關于行為樹的內(nèi)存優(yōu)化,這一篇我們將講述行為樹的另一種優(yōu)化方法基于事件的行為樹。而函數(shù)負責將行為壓入隊列首端,節(jié)點則負責設置行為執(zhí)行狀態(tài)并顯示調(diào)用監(jiān)察函數(shù)。

上一篇我們講到了關于行為樹的內(nèi)存優(yōu)化,這一篇我們將講述行為樹的另一種優(yōu)化方法——基于事件的行為樹。

問題

在之前的行為樹中,我們每幀都要從根節(jié)點開始遍歷行為樹,而目的僅僅是為了得到最近激活的節(jié)點,既然如此,為什么我們不多帶帶維護一個保存這些行為的列表,以方便快速訪問呢。我們可以把這個列表叫做調(diào)度器,用來保存已經(jīng)激活的行為,并在必要時更新他們。

解決辦法

我們不再每幀都從根節(jié)點去遍歷行為樹,而是維護一個調(diào)度器負責保存已激活的節(jié)點,當正在執(zhí)行的行為終止時,由其父節(jié)點決定接下來的行為。

監(jiān)察函數(shù)

為了實現(xiàn)基于事件的驅動,我們必須要有一個監(jiān)察函數(shù),當行為終止時,我們通過執(zhí)行監(jiān)察函數(shù)通知父節(jié)點并讓父節(jié)點做出相應處理,這里我們通過C++標準庫中的std::funcion實現(xiàn)監(jiān)察函數(shù)
using BehaviorObserver = std::function;

行為調(diào)度器

調(diào)度器負責管理基于事件的行為樹的核心代碼,負責對所有需要更新的行為進行集中式管理,不允許復合行為自主管理和運行自己的子節(jié)點。。。這里我們將調(diào)度器整合進了BehvaiorTree類。當然也可以弄個多帶帶的類進行管理。

class BehaviorTree
{
public:
        BehaviorTree(Behavior* InRoot) :Root(InRoot) {}
        void Tick();
        bool Step();
        void Start(Behavior* Bh,BehaviorObserver* Observe);
        void Stop(Behavior* Bh,EStatus Result);
private:
        //已激活行為列表
        std::deque Behaviors;
        Behavior* Root;
};

void BehaviorTree::Tick()
{
    //將更新結束標記插入任務列表
    Behaviors.push_back(nullptr);
    while (Step())
    {
    }
}

bool BehaviorTree :: Step()
{
    Behavior* Current = Behaviors.front();
    Behaviors.pop_front();
    //如果遇到更新結束標記則停止
    if (Current == nullptr)
        return false;
    //執(zhí)行行為更新
    Current->Tick();
    //如果該任務被終止則執(zhí)行監(jiān)察函數(shù)
    if (Current->IsTerminate() && Current->Observer)
    {
        Current->Observer(Current->GetStatus());
    }
    //否則將其插入隊列等待下次tick處理
    else
    {
        Behaviors.push_back(Current);
    }
}

void BehaviorTree::Start(Behavior* Bh, BehaviorObserver* Observe)
{
    if (Observe)
    {
        Bh->Observer = *Observe;
    }
    Behaviors.push_front(Bh);
}
void BehaviorTree::Stop(Behavior* Bh, EStatus Result)
{
    assert(Result != EStatus::Running);
    Bh->SetStatus(Result);
    if (Bh->Observer)
    {
        Bh->Observer(Result);
    }
}

我們通過一個雙端隊列保存已激活行為,在更新時從首端去走哦偶行為,再將需要更新的行為壓入隊列尾端。當發(fā)現(xiàn)任務終止時,執(zhí)行其監(jiān)察函數(shù)。
而Start()函數(shù)負責將行為壓入隊列首端,Stop()節(jié)點則負責設置行為執(zhí)行狀態(tài)并顯示調(diào)用監(jiān)察函數(shù)。

事件驅動的復合節(jié)點

大部分動作和條件代碼并不受事件驅動方式的影響。而復合節(jié)點則是受事件驅動影響最明顯的節(jié)點。復合節(jié)點不再自己更新和管理子節(jié)點,而是通過向調(diào)度器提出請求以更新子節(jié)點。這里我們以Sequence節(jié)點為例。
/順序器:依次執(zhí)行所有節(jié)點直到其中一個失敗或者全部成功位置

class Sequence :public Composite
    {
    public:
        virtual std::string Name() override { return "Sequence"; }
        static Behavior* Create() { return new Sequence(); }
        void OnChildComplete(EStatus Status);
    protected:
        virtual void OnInitialize() override;
    protected:
        Behaviors::iterator CurrChild;
        BehaviorTree* m_pBehaviorTree;
    };
    
    
void Sequence::OnInitialize()
{
    CurrChild = Children.begin();
    BehaviorObserver observer = std::bind(&Sequence::OnChildComplete, this, std::placeholders::_1);
    Tree->Start(*CurrChild, &observer);
}


void Sequence::OnChildComplete(EStatus Status)
{
    Behavior* child = *CurrChild;
    //當當前子節(jié)點執(zhí)行失敗時,順序器失敗
    if (child->IsFailuer())
    {
        m_pBehaviorTree->Stop(this, EStatus::Failure);
        return;
    }
    
    assert(child->GetStatus() == EStatus::Success);
    //當前子節(jié)點執(zhí)行成功時,判斷是否執(zhí)行到數(shù)組尾部
    if (++CurrChild == Children.end())
    {
        Tree->Stop(this, EStatus::Success);
    }
    //調(diào)度下一個子節(jié)點
    else
    {
        BehaviorObserver observer = std::bind(&Sequence::OnChildComplete, this, std::placeholders::_1);
        Tree->Start(*CurrChild, &observer);
    }
}

因為現(xiàn)在各節(jié)點由調(diào)度器統(tǒng)一管理,所以Update函數(shù)不再需要。我們在OnIntialize()函數(shù)中設置需要更新的首個節(jié)點,并將OnChildComplete作為其監(jiān)察函數(shù)。在OnchildComplete函數(shù)中實現(xiàn)后續(xù)子節(jié)點的更新。

總結

通過基于事件的方式,我們可以在行為樹執(zhí)行時節(jié)省大量的函數(shù)調(diào)用,對其性能無疑是一次巨大的提升。
github連接

文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://systransis.cn/yun/19684.html

相關文章

  • 游戲人工智能 讀書筆記 (四) AI算法簡介——Ad-Hoc 行為編程

    摘要:原文鏈接本文內(nèi)容包含以下章節(jié)本書英文版這個章節(jié)主要討論了在游戲中經(jīng)常用到的一些基礎的人工智能算法。行為樹是把的圖轉變成為一顆樹結構。根據(jù)當前游戲的環(huán)境狀態(tài)得到某一個行為的效用值。 作者:蘇博覽商業(yè)轉載請聯(lián)系騰訊WeTest獲得授權,非商業(yè)轉載請注明出處。原文鏈接:https://wetest.qq.com/lab/view/427.html 本文內(nèi)容包含以下章節(jié): Chapter 2 ...

    xinhaip 評論0 收藏0
  • 游戲AI行為研究及實現(xiàn)

    摘要:另外,當并行器滿足條件提前退出時,所有正在執(zhí)行的子行為也應該立即被終止,我們在函數(shù)中調(diào)用每個子節(jié)點的終止方法監(jiān)視器監(jiān)視器是并行器的應用之一,通過在行為運行過程中不斷檢查是否滿足某條件,如果不滿足則立刻退出。將條件放在并行器的尾部即可。 從上古卷軸中形形色色的人物,到NBA2K中揮灑汗水的球員,從使命召喚中詭計多端的敵人,到刺客信條中栩栩如生的人群。游戲AI幾乎存在于游戲中的每個角落,默...

    Harriet666 評論0 收藏0
  • 游戲人工智能 讀書筆記 (游戲和人工智能相互影響

    摘要:從游戲界的角度來說人工智能技術的發(fā)展可以為游戲帶來什么改變和收益。使用人工智能技術可以給游戲帶來更多更好的內(nèi)容,也可以減輕游戲開發(fā)的成本。 作者:蘇博覽,騰訊互動娛樂高級研究員商業(yè)轉載請聯(lián)系騰訊WeTest獲得授權,非商業(yè)轉載請注明出處。原文鏈接:https://wetest.qq.com/lab/view/412.html 本文內(nèi)容包含以下章節(jié): Chapter 1.3 Why Ga...

    CrazyCodes 評論0 收藏0
  • 深入了解機器學習

    摘要:監(jiān)督大多數(shù)情況下,機器學習依賴于被標記為真或假的數(shù)據(jù)。回歸學習回歸學習是最重要和廣泛使用的機器學習和統(tǒng)計工具之一。風險規(guī)避機器學習給企業(yè)提供了防止詐騙者陷入困境并減輕潛在貨幣和監(jiān)管復雜化的能力。 摘要: 了解機器學習發(fā)展史、機器學習是什么?機器學習有什么?看看本文就夠了。 如今機器學習已經(jīng)成為了這個時代的熱門話題。機器學習已經(jīng)存在了幾十年,但直到最近我們才得以利用這項技術。 接下來,讓...

    caikeal 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<