99精品久久精品一区二区-亚洲熟妇无码?v在线播放-日本国产精品无码字幕在线观看-久久久亚洲永夜AV-亚洲一级无码一区二区一-免费国产成高清人在线视频-中文字幕乱码免费观看-国产毛片精品妇女久久久

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營的一線實(shí)戰(zhàn)洞察。

Lua實(shí)現(xiàn)可擴(kuò)展行為樹:游戲AI模塊化與熱更新實(shí)戰(zhàn)

Lua實(shí)現(xiàn)可擴(kuò)展行為樹:游戲AI模塊化與熱更新實(shí)戰(zhàn) 1. 項(xiàng)目概述為什么游戲AI需要可擴(kuò)展的行為樹在游戲開發(fā)尤其是獨(dú)立游戲或中小型團(tuán)隊(duì)項(xiàng)目中我們常常面臨一個(gè)矛盾既希望AI邏輯足夠復(fù)雜、智能能夠應(yīng)對(duì)多樣的游戲場景又受限于緊張的開發(fā)周期和有限的人力。傳統(tǒng)的狀態(tài)機(jī)FSM在邏輯簡單時(shí)很好用但當(dāng)AI行為超過十幾個(gè)狀態(tài)狀態(tài)間的轉(zhuǎn)換關(guān)系就會(huì)變得像一團(tuán)亂麻難以維護(hù)和擴(kuò)展。這時(shí)行為樹Behavior Tree就成了一個(gè)更優(yōu)雅的解決方案。行為樹將AI決策過程抽象為一棵樹形結(jié)構(gòu)通過節(jié)點(diǎn)Node的組合來定義行為邏輯。其核心優(yōu)勢在于模塊化和可讀性。每個(gè)節(jié)點(diǎn)如條件節(jié)點(diǎn)、動(dòng)作節(jié)點(diǎn)、序列節(jié)點(diǎn)、選擇節(jié)點(diǎn)職責(zé)單一通過樹的結(jié)構(gòu)清晰地表達(dá)了“在什么條件下按什么順序執(zhí)行什么動(dòng)作”的邏輯。這對(duì)于團(tuán)隊(duì)協(xié)作和后期迭代至關(guān)重要。然而很多開發(fā)者尤其是初次接觸行為樹的同學(xué)在興奮地搭建起第一個(gè)AI后很快就會(huì)遇到新的瓶頸當(dāng)游戲需求快速變化需要頻繁添加新行為、調(diào)整優(yōu)先級(jí)或者需要讓AI具備學(xué)習(xí)、記憶等更高級(jí)能力時(shí)最初設(shè)計(jì)的行為樹框架往往變得僵化難以擴(kuò)展。代碼里開始出現(xiàn)大量的“硬編碼”添加一個(gè)新怪物類型可能意味著要復(fù)制粘貼一整棵樹并手動(dòng)修改幾十個(gè)地方這顯然是不可持續(xù)的。這正是“可擴(kuò)展性”要解決的問題。一個(gè)可擴(kuò)展的行為樹框架應(yīng)該能讓開發(fā)者像搭積木一樣快速組合出新的AI行為并且能方便地注入游戲特有的上下文如玩家位置、自身血量、道具信息等甚至支持運(yùn)行時(shí)動(dòng)態(tài)修改樹的結(jié)構(gòu)。而Lua憑借其輕量、嵌入容易、熱更新靈活的特性成為實(shí)現(xiàn)這一目標(biāo)的絕佳語言。它允許我們將行為樹的邏輯定義從C等底層引擎中解耦出來用腳本快速迭代AI邏輯無需重啟游戲。接下來我將結(jié)合自己在一個(gè)橫版動(dòng)作游戲項(xiàng)目中重構(gòu)AI系統(tǒng)的實(shí)戰(zhàn)經(jīng)驗(yàn)分享三種用Lua實(shí)現(xiàn)高度可擴(kuò)展行為樹的高級(jí)技巧。這些技巧不僅關(guān)乎代碼怎么寫更關(guān)乎如何設(shè)計(jì)框架讓你在面對(duì)策劃頻繁的需求變更時(shí)依然能從容不迫。2. 技巧一基于數(shù)據(jù)驅(qū)動(dòng)的行為樹構(gòu)建與動(dòng)態(tài)加載第一個(gè)技巧也是實(shí)現(xiàn)可擴(kuò)展性的基石就是將行為樹的結(jié)構(gòu)定義數(shù)據(jù)化并與邏輯執(zhí)行分離。最糟糕的做法是把樹的結(jié)構(gòu)和節(jié)點(diǎn)的執(zhí)行邏輯全部寫死在Lua代碼里混雜在一起。2.1 設(shè)計(jì)可序列化的節(jié)點(diǎn)與樹結(jié)構(gòu)我們首先要定義一套描述行為樹的數(shù)據(jù)結(jié)構(gòu)。一個(gè)常見的做法是使用Lua表Table來定義整棵樹。每個(gè)節(jié)點(diǎn)都是一個(gè)表包含其類型、參數(shù)、子節(jié)點(diǎn)等信息。-- 行為樹節(jié)點(diǎn)數(shù)據(jù)結(jié)構(gòu)的定義示例 local node_definitions { -- 一個(gè)選擇節(jié)點(diǎn)Selector從左到右執(zhí)行子節(jié)點(diǎn)直到一個(gè)成功。 { id root_selector, type selector, children { { id seq_attack, type sequence, children { ... } }, { id seq_patrol, type sequence, children { ... } }, { id action_idle, type action, task idle } } } } -- 一個(gè)更具體的攻擊序列節(jié)點(diǎn) local attack_sequence { id seq_attack, type sequence, -- 順序節(jié)點(diǎn)所有子節(jié)點(diǎn)成功才算成功任一失敗則中斷。 children { { type condition, evaluator isPlayerInRange, -- 條件評(píng)估函數(shù)名 args { radius 5.0 } }, { type action, task chargeAttack, -- 動(dòng)作執(zhí)行函數(shù)名 args { speed 2.0, damage 10 } } } }這里的關(guān)鍵是type、evaluator、task這些字段都是字符串。它們不是直接指向Lua函數(shù)而是函數(shù)在某個(gè)注冊(cè)表中的鍵Key。這樣做的好處是這整棵樹的結(jié)構(gòu)可以被輕易地序列化成JSON、Lua文件甚至存儲(chǔ)在數(shù)據(jù)庫中。策劃或設(shè)計(jì)師可以在不接觸代碼的情況下通過編輯JSON文件來調(diào)整AI的行為邏輯。實(shí)操心得在項(xiàng)目初期我就吃過虧。最初我把函數(shù)直接寫在節(jié)點(diǎn)定義里如action function(blackboard) ... end。這確實(shí)直觀但導(dǎo)致樹結(jié)構(gòu)無法序列化保存也無法實(shí)現(xiàn)熱重載。后來重構(gòu)為“函數(shù)名注冊(cè)”模式靈活性大增。記得為每個(gè)節(jié)點(diǎn)設(shè)計(jì)一個(gè)唯一的id字段這在調(diào)試和動(dòng)態(tài)修改時(shí)會(huì)非常有用。2.2 實(shí)現(xiàn)樹的加載器與節(jié)點(diǎn)工廠有了數(shù)據(jù)結(jié)構(gòu)我們需要一個(gè)“加載器”Loader和“節(jié)點(diǎn)工廠”Node Factory來將數(shù)據(jù)變成可執(zhí)行的行為樹對(duì)象。-- 節(jié)點(diǎn)工廠根據(jù)類型字符串創(chuàng)建對(duì)應(yīng)的節(jié)點(diǎn)對(duì)象 local NodeFactory {} NodeFactory.registry {} -- 注冊(cè)表存放類型名到節(jié)點(diǎn)類的映射 function NodeFactory.register(nodeType, nodeClass) NodeFactory.registry[nodeType] nodeClass end function NodeFactory.create(nodeData, parent) local nodeClass NodeFactory.registry[nodeData.type] if not nodeClass then error(Unknown node type: .. tostring(nodeData.type)) end -- 傳入節(jié)點(diǎn)數(shù)據(jù)和父節(jié)點(diǎn)引用創(chuàng)建實(shí)例 local node nodeClass.new(nodeData, parent) -- 遞歸創(chuàng)建子節(jié)點(diǎn) if nodeData.children then for _, childData in ipairs(nodeData.children) do local childNode NodeFactory.create(childData, node) node:addChild(childNode) end end return node end -- 示例注冊(cè)一個(gè)動(dòng)作節(jié)點(diǎn)類 local ActionNode {} ActionNode.__index ActionNode function ActionNode.new(data, parent) local self setmetatable({}, ActionNode) self.id data.id self.taskName data.task -- 任務(wù)名如 chargeAttack self.args data.args or {} self.parent parent self.status fresh -- fresh, running, success, failure return self end function ActionNode:execute(blackboard) self.status running -- 從全局任務(wù)注冊(cè)表中查找并執(zhí)行函數(shù) local taskFunc TaskRegistry.get(self.taskName) if taskFunc then local result taskFunc(blackboard, self.args) self.status result and success or failure else print(Warning: Task not found - .. self.taskName) self.status failure end return self.status end -- 注冊(cè)到工廠 NodeFactory.register(action, ActionNode)加載器的工作就是讀取JSON/Lua數(shù)據(jù)文件調(diào)用NodeFactory.create生成整棵樹的根節(jié)點(diǎn)。這樣當(dāng)我們需要為一種新的敵人配置AI時(shí)只需要新增一個(gè)數(shù)據(jù)文件然后在游戲初始化時(shí)加載它即可。2.3 支持動(dòng)態(tài)加載與熱更新基于數(shù)據(jù)驅(qū)動(dòng)的最大優(yōu)勢——熱更新。由于樹結(jié)構(gòu)是數(shù)據(jù)節(jié)點(diǎn)邏輯函數(shù)是通過名字從注冊(cè)表動(dòng)態(tài)查找的我們可以在游戲運(yùn)行時(shí)替換這些函數(shù)。-- 假設(shè)我們有一個(gè)管理所有行為樹的BrainManager function BrainManager:loadTree(entityId, treeConfigPath) local treeData loadJsonFile(treeConfigPath) -- 加載數(shù)據(jù) local rootNode NodeFactory.create(treeData) self.trees[entityId] { root rootNode, blackboard Blackboard.new() -- 每個(gè)AI獨(dú)立的黑板數(shù)據(jù) } end -- 熱更新當(dāng)檢測到行為樹數(shù)據(jù)文件變化時(shí) function BrainManager:hotReloadTree(entityId, treeConfigPath) local oldBrain self.trees[entityId] if oldBrain then -- 保留原有的黑板數(shù)據(jù)維持AI的運(yùn)行狀態(tài)記憶 local oldBlackboard oldBrain.blackboard -- 重新加載樹結(jié)構(gòu) local newTreeData loadJsonFile(treeConfigPath) local newRootNode NodeFactory.create(newTreeData) self.trees[entityId] { root newRootNode, blackboard oldBlackboard -- 關(guān)鍵復(fù)用黑板 } print(Behavior tree hot-reloaded for entity: .. entityId) end end這意味著策劃調(diào)整了Boss的攻擊頻率或巡邏路徑你只需要讓他修改JSON文件并保存游戲內(nèi)無需重啟Boss的AI行為立刻就會(huì)改變。這對(duì)于調(diào)試和迭代的效率提升是巨大的。3. 技巧二利用“黑板”Blackboard實(shí)現(xiàn)節(jié)點(diǎn)間高效數(shù)據(jù)共享與解耦行為樹中的節(jié)點(diǎn)需要根據(jù)游戲世界的信息做決策比如“玩家是否在視野內(nèi)”、“自身血量是否低于20%”。同時(shí)一個(gè)節(jié)點(diǎn)產(chǎn)生的數(shù)據(jù)如“計(jì)算出的逃跑目標(biāo)點(diǎn)”可能需要被另一個(gè)節(jié)點(diǎn)使用。如果讓節(jié)點(diǎn)之間直接互相引用或訪問全局變量會(huì)造成嚴(yán)重的耦合難以維護(hù)?!昂诎濉盉lackboard模式是解決這個(gè)問題的標(biāo)準(zhǔn)答案。你可以把它想象成一個(gè)AI實(shí)體私有的、鍵值對(duì)形式的共享內(nèi)存區(qū)域。所有節(jié)點(diǎn)都通過同一個(gè)黑板對(duì)象來讀寫數(shù)據(jù)彼此不知道對(duì)方的存在實(shí)現(xiàn)了完全解耦。3.1 設(shè)計(jì)一個(gè)靈活的Lua黑板系統(tǒng)一個(gè)基礎(chǔ)的黑板實(shí)現(xiàn)很簡單就是一個(gè)Lua表。但我們需要考慮線程安全如果在多線程環(huán)境下、數(shù)據(jù)類型和訪問控制。local Blackboard {} Blackboard.__index Blackboard function Blackboard.new() local self setmetatable({}, Blackboard) self.data {} -- 存儲(chǔ)所有數(shù)據(jù) self.listeners {} -- 監(jiān)聽器用于數(shù)據(jù)變化時(shí)觸發(fā)回調(diào) return self end -- 設(shè)置數(shù)據(jù)可觸發(fā)監(jiān)聽器 function Blackboard:set(key, value, forceNotify) local oldValue self.data[key] self.data[key] value -- 如果值發(fā)生變化或者強(qiáng)制通知?jiǎng)t觸發(fā)監(jiān)聽 if forceNotify or oldValue ~ value then self:notifyChange(key, value, oldValue) end end function Blackboard:get(key, defaultValue) local value self.data[key] if value nil then return defaultValue end return value end -- 監(jiān)聽數(shù)據(jù)變化可用于調(diào)試或觸發(fā)復(fù)雜邏輯 function Blackboard:watch(key, callback) if not self.listeners[key] then self.listeners[key] {} end table.insert(self.listeners[key], callback) end function Blackboard:notifyChange(key, newValue, oldValue) local listeners self.listeners[key] if listeners then for _, cb in ipairs(listeners) do cb(newValue, oldValue) end end end3.2 在條件與動(dòng)作節(jié)點(diǎn)中應(yīng)用黑板現(xiàn)在我們的條件評(píng)估函數(shù)和動(dòng)作執(zhí)行函數(shù)都可以接收黑板作為參數(shù)。-- 在任務(wù)注冊(cè)表中注冊(cè)函數(shù) TaskRegistry.register(isPlayerInRange, function(blackboard, args) local selfPos blackboard:get(self.position) local playerPos blackboard:get(world.player.position) if not selfPos or not playerPos then return false end local radius args.radius or 10.0 local distance calculateDistance(selfPos, playerPos) return distance radius end) TaskRegistry.register(chargeAttack, function(blackboard, args) local entity blackboard:get(self.entity) -- 獲取關(guān)聯(lián)的游戲?qū)嶓w對(duì)象 local targetPos blackboard:get(attack.targetPosition) if not entity or not targetPos then return false -- 動(dòng)作失敗 end -- 執(zhí)行沖鋒邏輯... local speed args.speed or 1.0 chargeTowards(entity, targetPos, speed) -- 動(dòng)作完成后可以在黑板上設(shè)置狀態(tài) blackboard:set(lastAction, chargeAttack) blackboard:set(isCooldown.charge, true) -- 假設(shè)沖鋒總是成功實(shí)際應(yīng)根據(jù)游戲邏輯判斷 return true end)關(guān)鍵點(diǎn)在于是誰在更新黑板上的world.player.position或self.position這些原始數(shù)據(jù)這通常由一個(gè)獨(dú)立的“感知系統(tǒng)”Perception System來完成。這個(gè)系統(tǒng)每幀或每隔幾幀收集游戲世界的信息并更新到每個(gè)AI實(shí)體的黑板上。這樣行為樹節(jié)點(diǎn)只需要關(guān)心從黑板上消費(fèi)數(shù)據(jù)完全不知道數(shù)據(jù)來源實(shí)現(xiàn)了感知與決策的分離。3.3 實(shí)現(xiàn)帶作用域的分層黑板對(duì)于復(fù)雜AI比如一個(gè)包含多個(gè)子任務(wù)如“戰(zhàn)斗”-“尋找掩體”-“射擊”的復(fù)合行為我們可能希望某些數(shù)據(jù)只在特定子樹內(nèi)共享而不是全局可見。這就需要分層黑板。我們可以設(shè)計(jì)一個(gè)支持作用域鏈的黑板。當(dāng)在一個(gè)子樹中查找某個(gè)鍵時(shí)先在自己的局部作用域找找不到再向上級(jí)父作用域查找直到根黑板。local ScopedBlackboard {} ScopedBlackboard.__index ScopedBlackboard function ScopedBlackboard.new(parentBlackboard) local self setmetatable({}, ScopedBlackboard) self.localData {} self.parent parentBlackboard -- 父級(jí)黑板形成鏈 return self end function ScopedBlackboard:setLocal(key, value) self.localData[key] value end function ScopedBlackboard:get(key, defaultValue) -- 先在本地查找 local value self.localData[key] if value ~ nil then return value end -- 本地沒有且存在父級(jí)則向父級(jí)查找 if self.parent then return self.parent:get(key, defaultValue) end -- 鏈上都沒有返回默認(rèn)值 return defaultValue end在創(chuàng)建行為樹節(jié)點(diǎn)時(shí)可以為某些復(fù)合節(jié)點(diǎn)如SequenceSelector創(chuàng)建一個(gè)新的ScopedBlackboard并將其傳遞給子節(jié)點(diǎn)。這樣子節(jié)點(diǎn)之間可以共享一些臨時(shí)數(shù)據(jù)而不會(huì)污染全局黑板空間。例如一個(gè)“尋找路徑”的節(jié)點(diǎn)可以將計(jì)算出的路徑點(diǎn)列表存儲(chǔ)在局部黑板上供后續(xù)的“沿路徑移動(dòng)”節(jié)點(diǎn)使用其他不相關(guān)的節(jié)點(diǎn)則看不到這個(gè)數(shù)據(jù)。注意事項(xiàng)黑板雖然強(qiáng)大但也要避免濫用。不要把所有數(shù)據(jù)都塞進(jìn)黑板只存放節(jié)點(diǎn)間需要共享的決策狀態(tài)和上下文信息。像敵人的基礎(chǔ)屬性攻擊力、血量上限這類靜態(tài)數(shù)據(jù)更適合直接從游戲?qū)嶓w組件中讀取。同時(shí)要為黑板鍵名制定清晰的命名規(guī)范如使用點(diǎn)分隔的命名空間perception.playerVisible,navigation.targetPoint防止鍵名沖突。4. 技巧三通過裝飾器與自定義組合節(jié)點(diǎn)應(yīng)對(duì)復(fù)雜邏輯標(biāo)準(zhǔn)的行為樹節(jié)點(diǎn)類型Sequence, Selector, Condition, Action有時(shí)不足以優(yōu)雅地表達(dá)一些復(fù)雜邏輯。比如“在5秒內(nèi)嘗試攻擊最多3次”或者“只有當(dāng)某個(gè)全局事件發(fā)生時(shí)才執(zhí)行某個(gè)子樹”。這時(shí)我們就需要用到裝飾器Decorator和自定義組合節(jié)點(diǎn)。4.1 裝飾器節(jié)點(diǎn)的威力裝飾器是一種特殊節(jié)點(diǎn)它只有一個(gè)子節(jié)點(diǎn)。它的作用是修改或增強(qiáng)這個(gè)子節(jié)點(diǎn)的行為。常見的裝飾器有重復(fù)Repeat重復(fù)執(zhí)行子節(jié)點(diǎn)N次或直到失敗。取反Inverter將子節(jié)點(diǎn)的執(zhí)行結(jié)果取反成功變失敗失敗變成功。強(qiáng)制返回Force Success/Failure無論子節(jié)點(diǎn)結(jié)果如何都返回成功或失敗。冷卻Cooldown子節(jié)點(diǎn)執(zhí)行后在一段時(shí)間內(nèi)不能再被執(zhí)行。條件中斷Conditional Abort在子節(jié)點(diǎn)運(yùn)行期間持續(xù)監(jiān)控某個(gè)條件若條件變化則中斷子節(jié)點(diǎn)。用Lua實(shí)現(xiàn)一個(gè)通用的裝飾器基類很容易關(guān)鍵在于設(shè)計(jì)好它的execute方法使其能夠包裝子節(jié)點(diǎn)的執(zhí)行。local DecoratorNode {} DecoratorNode.__index DecoratorNode function DecoratorNode.new(data, parent) local self setmetatable({}, DecoratorNode) self.id data.id self.child nil -- 裝飾器只有一個(gè)子節(jié)點(diǎn) self.parent parent self.status fresh self.decoratorType data.decoratorType self.args data.args or {} return self end function DecoratorNode:addChild(node) if self.child then error(Decorator node can only have one child!) end self.child node end -- 具體裝飾器重復(fù)節(jié)點(diǎn) local RepeatDecorator setmetatable({}, {__index DecoratorNode}) RepeatDecorator.__index RepeatDecorator function RepeatDecorator.new(data, parent) local self DecoratorNode.new(data, parent) setmetatable(self, RepeatDecorator) self.currentCount 0 self.maxCount data.args.times or 1 -- 默認(rèn)重復(fù)1次即無效果 return self end function RepeatDecorator:execute(blackboard) self.status running while self.currentCount self.maxCount do local childStatus self.child:execute(blackboard) if childStatus running then return running -- 子節(jié)點(diǎn)還在運(yùn)行直接返回 elseif childStatus failure then self.status failure return failure -- 子節(jié)點(diǎn)失敗中斷重復(fù) end -- 子節(jié)點(diǎn)成功繼續(xù)下一次循環(huán) self.currentCount self.currentCount 1 end self.status success return success end function RepeatDecorator:reset() self.currentCount 0 self.status fresh if self.child then self.child:reset() end end -- 注冊(cè)到工廠 NodeFactory.register(decorator_repeat, RepeatDecorator)在數(shù)據(jù)定義中我們可以這樣使用{ id: try_attack_three_times, type: decorator_repeat, args: { times: 3 }, children: [ { type: sequence, children: [ { type: condition, evaluator: canAttack }, { type: action, task: performAttack } ] } ] }4.2 構(gòu)建自定義組合節(jié)點(diǎn)應(yīng)對(duì)特定場景除了裝飾器我們還可以創(chuàng)造全新的組合節(jié)點(diǎn)類型。標(biāo)準(zhǔn)行為樹庫可能不提供但你的游戲特定需要的節(jié)點(diǎn)。例如一個(gè)“并行節(jié)點(diǎn)Parallel”它同時(shí)執(zhí)行所有子節(jié)點(diǎn)并根據(jù)成功/失敗的數(shù)量來決定自己的返回狀態(tài)常用于“一邊移動(dòng)一邊播放動(dòng)畫”。local ParallelNode {} ParallelNode.__index ParallelNode -- 假設(shè)繼承自某個(gè)基礎(chǔ)節(jié)點(diǎn)類 function ParallelNode.new(data, parent) local self setmetatable({}, ParallelNode) self.id data.id self.children {} self.parent parent self.status fresh self.policy data.args.policy or requireAll -- requireAll, requireOne return self end function ParallelNode:execute(blackboard) self.status running local successCount 0 local failureCount 0 for _, child in ipairs(self.children) do if child.status fresh or child.status running then local childStatus child:execute(blackboard) if childStatus success then successCount successCount 1 elseif childStatus failure then failureCount failureCount 1 end -- 如果子節(jié)點(diǎn)是running則繼續(xù)留在running狀態(tài) else -- 子節(jié)點(diǎn)已經(jīng)結(jié)束計(jì)入結(jié)果 if child.status success then successCount successCount 1 elseif child.status failure then failureCount failureCount 1 end end end -- 根據(jù)策略判斷并行節(jié)點(diǎn)自身狀態(tài) local total #self.children if self.policy requireAll then if successCount total then self.status success return success elseif failureCount 0 then self.status failure return failure end elseif self.policy requireOne then if successCount 0 then self.status success return success elseif failureCount total then self.status failure return failure end end -- 否則繼續(xù)運(yùn)行 return running end另一個(gè)有用的自定義節(jié)點(diǎn)是“動(dòng)態(tài)選擇器Dynamic Selector”。普通選擇器Selector是按固定順序評(píng)估子節(jié)點(diǎn)。而動(dòng)態(tài)選擇器可以在每次執(zhí)行前根據(jù)黑板上的動(dòng)態(tài)權(quán)重或優(yōu)先級(jí)對(duì)子節(jié)點(diǎn)進(jìn)行重新排序讓AI的行為選擇更具適應(yīng)性和變化。4.3 將游戲事件作為觸發(fā)器集成到行為樹中有時(shí)AI需要響應(yīng)外部事件比如“被擊中時(shí)觸發(fā)格擋”、“聽到聲音后轉(zhuǎn)向”。我們可以設(shè)計(jì)一種“事件監(jiān)聽裝飾器”或一個(gè)特殊的“事件條件節(jié)點(diǎn)”。思路是在游戲的事件系統(tǒng)中允許行為樹節(jié)點(diǎn)注冊(cè)監(jiān)聽。當(dāng)特定事件發(fā)生時(shí)事件系統(tǒng)會(huì)通知所有監(jiān)聽該事件的AI實(shí)體并在其黑板上設(shè)置一個(gè)標(biāo)志或數(shù)據(jù)。-- 事件條件節(jié)點(diǎn) local EventConditionNode {} EventConditionNode.__index EventConditionNode function EventConditionNode.new(data, parent) local self setmetatable({}, EventConditionNode) self.id data.id self.eventType data.args.eventType -- 如 onDamaged, onSoundHeard self.status fresh return self end function EventConditionNode:execute(blackboard) -- 檢查黑板上是否有該事件觸發(fā)的標(biāo)記 local eventFlag blackboard:get(event. .. self.eventType, false) if eventFlag then -- 消費(fèi)掉這個(gè)事件標(biāo)記防止同一事件重復(fù)觸發(fā) blackboard:set(event. .. self.eventType, false) return success end return failure end -- 在游戲的事件派發(fā)器中 function GameEventDispatcher:onEntityDamaged(entityId, damageInfo) -- ... 處理傷害邏輯 ... -- 通知該實(shí)體的行為樹 local brain BrainManager:getBrain(entityId) if brain then brain.blackboard:set(event.onDamaged, true) brain.blackboard:set(event.lastDamageSource, damageInfo.source) end end這樣我們就可以在行為樹中創(chuàng)建這樣的分支“當(dāng)‘被攻擊’事件觸發(fā)時(shí)執(zhí)行‘格擋’或‘逃跑’序列”。這極大地增強(qiáng)了AI與游戲世界的交互能力。常見問題過度使用裝飾器和自定義節(jié)點(diǎn)會(huì)讓行為樹變得難以理解。我的經(jīng)驗(yàn)法則是優(yōu)先使用標(biāo)準(zhǔn)的Sequence和Selector進(jìn)行組合。只有當(dāng)標(biāo)準(zhǔn)節(jié)點(diǎn)組合出的邏輯非?;逎虻托r(shí)才考慮引入裝飾器或自定義節(jié)點(diǎn)。并且一定要為這些非標(biāo)節(jié)點(diǎn)編寫清晰的注釋說明其用途和行為。5. 實(shí)戰(zhàn)構(gòu)建一個(gè)可擴(kuò)展的怪物AI并處理常見問題讓我們綜合運(yùn)用以上三種技巧為一個(gè)簡單的游戲怪物構(gòu)建AI。假設(shè)怪物有“閑逛”、“追擊玩家”、“攻擊”三種主要行為優(yōu)先級(jí)從高到低是攻擊 追擊 閑逛。5.1 AI行為樹結(jié)構(gòu)設(shè)計(jì)首先我們用數(shù)據(jù)定義這棵樹local monsterAITree { id monster_root, type selector, -- 根節(jié)點(diǎn)是選擇器按優(yōu)先級(jí)選擇分支 children { { -- 攻擊分支 (最高優(yōu)先級(jí)) id attack_branch, type sequence, children { { type condition, evaluator isPlayerInAttackRange, args { range 1.5 } }, { type decorator_cooldown, -- 添加攻擊冷卻裝飾器 args { cooldownKey attackCD, duration 2.0 }, children { { type action, task meleeAttack, args { damage 15 } } } } } }, { -- 追擊分支 id chase_branch, type sequence, children { { type condition, evaluator isPlayerInSight, args { sightRange 10.0 } }, { type action, task moveToPlayer, args { speed 3.0 } } } }, { -- 閑逛分支 (最低優(yōu)先級(jí)兜底行為) id wander_branch, type action, task wanderRandomly, args { radius 5.0, interval 3.0 } } } }5.2 關(guān)鍵節(jié)點(diǎn)的Lua實(shí)現(xiàn)與黑板交互我們需要實(shí)現(xiàn)上述用到的條件評(píng)估器和動(dòng)作任務(wù)并展示它們?nèi)绾闻c黑板交互。-- 感知系統(tǒng)每幀更新黑板數(shù)據(jù)簡化示例 function PerceptionSystem:updateEntity(entityId, blackboard) local entity World:getEntity(entityId) local player World:getPlayer() -- 更新自身位置 blackboard:set(self.position, entity:getPosition()) -- 更新玩家位置 blackboard:set(world.player.position, player:getPosition()) -- 計(jì)算并更新玩家是否在視野內(nèi) local distance vector.distance(entity:getPosition(), player:getPosition()) blackboard:set(perception.playerDistance, distance) blackboard:set(perception.playerInSight, distance 10.0 and hasLineOfSight(entity, player)) -- 更新血量狀態(tài) blackboard:set(self.health, entity.health) blackboard:set(self.isLowHealth, entity.health entity.maxHealth * 0.3) end -- 條件評(píng)估函數(shù) TaskRegistry.register(isPlayerInAttackRange, function(blackboard, args) local distance blackboard:get(perception.playerDistance, math.huge) return distance (args.range or 1.0) end) TaskRegistry.register(isPlayerInSight, function(blackboard, args) return blackboard:get(perception.playerInSight, false) end) -- 動(dòng)作任務(wù)函數(shù) TaskRegistry.register(meleeAttack, function(blackboard, args) local entity blackboard:get(self.entity) local player World:getPlayer() if not entity or not player then return false end -- 執(zhí)行攻擊動(dòng)畫、傷害計(jì)算等 entity:playAnimation(attack) player:takeDamage(args.damage) -- 在黑板記錄上次攻擊時(shí)間用于冷卻判斷 blackboard:set(lastAttackTime, os.clock()) return true end) TaskRegistry.register(moveToPlayer, function(blackboard, args) local entity blackboard:get(self.entity) local targetPos blackboard:get(world.player.position) if not entity or not targetPos then return false end local currentPos entity:getPosition() local direction vector.normalize(vector.sub(targetPos, currentPos)) local velocity vector.mul(direction, args.speed or 2.0) entity:setVelocity(velocity) -- 這是一個(gè)“持續(xù)”動(dòng)作需要返回running直到到達(dá)目標(biāo) local distance vector.distance(currentPos, targetPos) if distance 0.5 then -- 到達(dá)閾值 entity:setVelocity({x0, y0}) return true -- 成功到達(dá) end return running -- 仍在移動(dòng)中 end)注意moveToPlayer動(dòng)作返回的是running。行為樹每幀或每個(gè)更新周期都會(huì)從根節(jié)點(diǎn)重新執(zhí)行Tick對(duì)于返回running的節(jié)點(diǎn)下一幀會(huì)直接繼續(xù)執(zhí)行它而不是重新評(píng)估。這保證了動(dòng)作的連續(xù)性。5.3 調(diào)試與性能優(yōu)化技巧一個(gè)復(fù)雜的行為樹系統(tǒng)調(diào)試是必不可少的。1. 可視化調(diào)試在游戲中繪制當(dāng)前AI的行為樹狀態(tài)是終極調(diào)試手段??梢詾槊總€(gè)節(jié)點(diǎn)在execute方法中記錄其本次執(zhí)行的結(jié)果成功、失敗、運(yùn)行中并將這些狀態(tài)信息與節(jié)點(diǎn)ID關(guān)聯(lián)。然后在游戲調(diào)試界面上根據(jù)ID將樹繪制出來并用不同顏色如綠/紅/黃高亮節(jié)點(diǎn)狀態(tài)。這能讓你一眼看出AI當(dāng)前卡在哪一步。2. 黑板數(shù)據(jù)監(jiān)視為黑板提供一個(gè)調(diào)試查看接口。在游戲內(nèi)按某個(gè)鍵可以顯示當(dāng)前選中AI的黑板所有鍵值對(duì)。這對(duì)于驗(yàn)證感知系統(tǒng)是否正確更新數(shù)據(jù)、動(dòng)作節(jié)點(diǎn)是否設(shè)置了正確的狀態(tài)標(biāo)志至關(guān)重要。3. 性能優(yōu)化條件節(jié)點(diǎn)優(yōu)化行為樹每幀都從根節(jié)點(diǎn)執(zhí)行高頻率的條件檢查如距離計(jì)算可能成為性能瓶頸??梢圆捎谩胺謱痈隆辈呗詫l件分為“高頻”每幀和“低頻”每0.5秒或更長。對(duì)于低頻條件可以在節(jié)點(diǎn)內(nèi)記錄上次檢查時(shí)間未到時(shí)間則直接返回緩存結(jié)果。避免過深的樹過于復(fù)雜龐大的樹會(huì)增加遍歷開銷。盡量保持樹的扁平化將復(fù)雜的子樹封裝成“宏”或“子行為樹”通過一個(gè)特殊的“子樹節(jié)點(diǎn)”來引用。這樣主樹結(jié)構(gòu)清晰也便于復(fù)用。節(jié)點(diǎn)狀態(tài)緩存標(biāo)準(zhǔn)行為樹每次Tick都會(huì)重新遍歷。對(duì)于已經(jīng)完成成功/失敗且其前提條件未改變的子樹可以緩存其結(jié)果在本幀內(nèi)跳過執(zhí)行。這需要更精細(xì)的狀態(tài)管理和臟標(biāo)記機(jī)制實(shí)現(xiàn)復(fù)雜但對(duì)性能提升顯著。4. 一個(gè)常見的坑狀態(tài)重置行為樹節(jié)點(diǎn)在返回success或failure后其狀態(tài)會(huì)保持。下一幀如果從根節(jié)點(diǎn)重新執(zhí)行需要將非running的節(jié)點(diǎn)狀態(tài)重置為fresh否則它們將不會(huì)被執(zhí)行。重置的時(shí)機(jī)通常是在父節(jié)點(diǎn)開始執(zhí)行時(shí)或者整棵樹每幀Tick開始時(shí)。務(wù)必在你的框架中處理好狀態(tài)重置邏輯否則會(huì)出現(xiàn)AI“卡住”不動(dòng)的情況。6. 擴(kuò)展思路從行為樹到實(shí)用工具鏈當(dāng)你擁有一個(gè)穩(wěn)定可擴(kuò)展的Lua行為樹框架后可以圍繞它構(gòu)建一系列提升生產(chǎn)力的工具。1. 可視化編輯器這是最大的生產(chǎn)力倍增器。你可以使用諸如L?VE、Defold甚至網(wǎng)頁技術(shù)配合Lua解釋器開發(fā)一個(gè)簡單的編輯器。讓策劃或設(shè)計(jì)師通過拖拽節(jié)點(diǎn)、連線的方式來構(gòu)建行為樹編輯器負(fù)責(zé)生成我們定義好的JSON或Lua表數(shù)據(jù)文件。這能極大降低行為樹的使用門檻。2. 行為樹片段庫將一些經(jīng)過驗(yàn)證的、通用的行為模式如“巡邏-警戒-追擊”循環(huán)、“遠(yuǎn)程攻擊-尋找掩體”策略封裝成行為樹片段保存到庫中。在設(shè)計(jì)新AI時(shí)可以直接從庫中拖拽這些片段進(jìn)行組合快速搭建原型。3. 與技能系統(tǒng)、對(duì)話系統(tǒng)集成行為樹不僅可以控制移動(dòng)和戰(zhàn)斗也可以用來驅(qū)動(dòng)NPC的對(duì)話流程、觸發(fā)場景交互、管理BOSS的階段技能。將技能釋放、對(duì)話選項(xiàng)也抽象為行為樹上的動(dòng)作節(jié)點(diǎn)可以讓游戲的所有邏輯驅(qū)動(dòng)統(tǒng)一到行為樹框架下保持架構(gòu)的一致性。4. 機(jī)器學(xué)習(xí)實(shí)驗(yàn)接口雖然本文不涉及復(fù)雜的AI但可擴(kuò)展的行為樹框架為未來集成機(jī)器學(xué)習(xí)如強(qiáng)化學(xué)習(xí)提供了可能。你可以將行為樹中的某些決策節(jié)點(diǎn)如選擇攻擊方式暴露為一個(gè)可學(xué)習(xí)的“策略”讓機(jī)器學(xué)習(xí)模型來輸出決策結(jié)果而行為樹負(fù)責(zé)執(zhí)行。黑板則成為機(jī)器學(xué)習(xí)Agent觀察環(huán)境State的窗口。實(shí)現(xiàn)一個(gè)健壯、可擴(kuò)展的Lua行為樹系統(tǒng)前期需要一定的設(shè)計(jì)和開發(fā)投入但一旦建成它將為你的游戲AI開發(fā)帶來持久的敏捷性和強(qiáng)大的表現(xiàn)力。記住框架的目標(biāo)不是追求理論上最完美的AI而是用可維護(hù)的代碼快速實(shí)現(xiàn)符合游戲設(shè)計(jì)需求的、有趣的AI行為。從一個(gè)小而核心的版本開始逐步迭代讓它隨著你的項(xiàng)目一起成長。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
色综合色| 九九视频精品在线免费 | 91在线日| 色综合综合网| 五月天色五月天| 五月丁香偷拍| 激情五月影院| 99热这里只有精品国产首页| 丁香五月宝贝激情网| 久久九九国产| 在线视频激情网站| 超碰免费观看| 久久99久久99精品,久国产,久久精品免费,99久在线,久久久久国产精品免费网站,9 | 色99在线| 婷婷五月激情图片| 激情五月天视频| 亚洲人妻五月丁香婷婷| 亚洲婷婷成人五月天| 亚洲综合1024| 人妻人人操| 国产探花一片区| 日韩性爱AV| 99精品在这里| 这里只有精品视频在线| 天天插天天干| 99国产精品白浆在线观看免费| 日韩精品一区二区亚洲AV观看| 五月丁香欧美在线| 深爱激情网综合| 秋霞网在线观看理论91| 天天日夜夜夜操操操操| 五月四色婷婷| 天天天日天天天干| 中文网av| 一级性爱视频| 亚洲成人在线综合| 99热这里是精品| 97色女人在线| 91久久久久久| 99热免费观看| 国产肥白大熟妇BBBB视频| 九九av| 欧洲色| 日日综合网| 丁香五月婷婷俺也要去| 天天爱天天做天天操| 婷激情五月| 婷婷丁香人妻| 五月婷婷综合在线视频小说| 国产日韩欧美性爱| 精品人人操| 婷婷五月色综合| 开心激情婷婷| 小视频久久久aaa| 欧美99| 六月激情婷婷| www,黄色在线,con| 五月天伊人久久| 欧美婷婷色五月网| 中文字幕av久久爽一区| 五月天开心成人网| 日日夜夜婷婷| 玖玖热视频| 这里只有精品久久| 日本在线播放97| 久久久高清| 婷婷丁香五月天激情四射| 激情五月黄色| 久久香蕉福利| 狠狠肏综合网| 99热只有| 婷婷丁香六月天| 男女啪啪做爰高潮无遮挡| 97在线观视频免费观看| 狠狠色综合网站久久久久| 亚洲 欧洲 国产 伦综合| 99热在线网站| 五月丁香六月色婷婷综合五月天| A网在线欧洲| 亚州色色色| 色老久久| 久久性爱99国产| 色五月综合网站| 伊人综合色干| 欧美另类五月激情| 五月婷婷在线观看黄| 啪啪激情综合| 婷婷五月天成人视频| 久久九九婷婷| 管管補管管紱| 99色干| 在线另类| www.射伊蕉婷婷| 九九热a| 日日操,日日爽| 亚洲精品激情| 精品无码久久久久久久久| 色婷婷很很十八禁| 99在线精品视频免费| 五月婷婷深爱六月| 五月天色图| 大色鬼综合| 婷婷综合在线视频| 激情图片婷婷| 另类在线| 97色天堂| 99热这里只有精品3| 色噜噜狠狠色综合日日| 婷婷久久精品| 天天干夜夜想| 婷婷99视频在线| 婷婷色操| 婷婷综合爱| 精品久热| pom538精品视频| 婷婷五月丁香高清无码| 99热都是精品| 香蕉久久国产av一区二区| 激情com| 天天久久狠狠色综合| 99re思思| 婷婷五月激情欧美| 人人爽欧美婷婷久久久五月丁香 | 色色六月| 思思精品久久艹 | 婷婷五月18永久免费网站| 九九热这里只有精品556| 色五狠狠| 亚洲9久久精品| 国内婷婷丁香社区在线播放| 久久这里有精品| 色九月国产| 欧美97p| 婷婷性爱| 国产综合色婷婷精品久久| 色偷偷狠狠| 色色色色色色网| 97在线日本| 亚洲日韩26uuu| 四色99久久| 色婷婷瘦婷婷日韩| 国产精品久久..4399| 伊人婷婷五月| 极品人妻VIDEOSSS人妻| 午夜九九电影| 色狠狠色噜噜AV天堂五区| 大香蕉网站,大香蕉综合| 久久激情五月婷婷| 久久大香蕉视频| 五月天综合在线观看| 欧洲电影在线观看免费版英语版| 亚洲熟妇AV综合网五月丁香伊人| 久草五月| WWW.开心五月天.COM| 婷婷五月天AV| 天天在线久久综合| 精品一二三区久久AAA片| 五月婷婷开心深| 婷婷激情五月| 二人电影免费版在线观看| 五月丁香六月激情综合| 国产成人在线精品| 丁香六月婷婷色XXXXX| 日本WWW九九九| 无套内射极品大美女| 狠狠色婷| 人人人操| 天天舔夜夜操www com| 91五月天| 久久av电影| 色婷婷99| 五月综合婷婷久久在线| 婷婷五月天丁香综合网| 日本天天操| 九热久| 五月丁香综合| 99久久精彩视频。| 中文字幕日产A片在线看| 成人久久天天x资源站| 综合网色| 婷婷激情五月天小说校园| 九月停停| 粉嫩av蜜桃av蜜臀av| 丁香五月婷婷亚洲综合精品| 亚洲色啪| 久久这里有| 五月丁香天堂| 日本91在线| 激情涩涩网| 99年操人人爽| 激情亚洲婷婷| 五月丁香六月婷婷综合免| 亚洲精品一区无码A片| 九九热在线观看视频网站| 思思re最新视频| 色婷婷a三区麻| 91国产精品视频播放| 99这里只有精| 六月婷婷深深爱| 五月天电影网| 9l视频自拍九色9l视频在线观看| 亚洲婷婷月丁香五月| 国产精品第一国产精品| 碰97久久| 六月丁香婷婷色69| 97久久草草超级碰碰碰| 人人爽网| 99日韩| 丁香五月婷婷性爱| 人人妻人人澡人人爽| 99在线热| 婷婷情色激情| 婷婷激情小说网| 在线看的免费网站| 99九九精品视频| 2025最新亚洲激情在线| 五月婷婷婷综合网| 久久99最新地址| 另类综合色| 综合婷婷| 中文字幕亚洲-区久久99婷婷| 操91| 久热这里只有精品6| www激情| 欧美精品XXXXBBBB| 国产精品成人AV在线| 亚洲激情网站无码| 99亚洲视频| 天天爽天天| 五月婷婷片| 色综合网上班开心婷婷久久| 五月色丁香婷婷综合| 人妻操逼视频| 五月丁香六月婷| 五月情婷婷五月| 97碰碰视频| 国产做爰视频免费播放| 伊人91| 六月色丁香中文字幕| 99色热视频| 日韩精品视频中文字幕| 女人天堂AV| 天天舔天天操| 99热99热不卡| 五月婷婷影视| ss五月天激情| 丁香色五月 97干| 色色色丁香| 激情丁香五月| 五月亭亭开心网| 夜夜干天天操| 五月天天天色| www99热| 五月天色综合服务平台| 国产av一区二区三区| 国产亚洲在线观看| 亚洲综合视频在线| 色爽九九| 99狠狠色| 99热国产精品| 成人在线精品| 色色色国产| 欧美色婷婷| 思思热再线视频| 激情影院内射| 丁香香五月激情免费视频| 亚洲无码成人| 影视av久久久噜噜噜噜噜三级| 日本久久九| 婷婷五月天影院| 色五月人妻| 99免费热视频在线| 成人国产综合| 五月丁香久久| 亚洲噜色| 亚洲综合视频一下| 第四色婷婷五月| 色五月aV| 一本综合丁香日日狠狠色| 再次出发二| 99久久丝| 欧洲日韩一区二区三区| 亚洲久久婷婷丁香五月天| 亚洲久久视频| 26uuuavcom| 五月婷六月综合在线观看| 久久综合爱| 991国产精选视频在线播放下载| 婷婷中文字暮| 激情综合色婷婷啪啪六月天| 久久久性爱网| 日本老女人黄页在线播放| 色婷婷五月综合在线| 51XX嘿嘿午夜无码| 欧美啪啪9| 秋霞成人毛片一级A片| 婷婷五月大香蕉| 在线视频99| 激情爱爱网站超大免费| av中文在线| 婷婷丁香色五月亚洲| 久久综合婷婷| 婷婷永久在线| 九九热99热| 激情欧美五月丁香| 五月丁香无码| 大学生高潮无套内谢视频| 久久久久久人妻| 激情六月天| 国产AV一区二区三区日韩| 日欧一片内射VA在线影院| 天天日夜夜| 丁香8月手机综合| 中文婷婷狠狠| 丁香五月婷婷亚洲色图| 欧美精品99久久久| 就去涩涩丁香五月天| 天天激情| 开心激情网在线| 婷婷久久久| 在线中文AV| 欧美高潮9| 婷婷射图| 亚洲精品性色| 天天噜日日噜综合无码| 色婷青青| 香蕉综合在线| 五月天中文网| 激情丁香婷婷| 九九成人电影婷婷| 久久婷五月综合| 欧美婷婷| 欧美婷婷五月天| 五月婷色色| 香蕉AV777XXX色综合一区| 国产精品色色| av国产精品| 亚洲啪啪自拍| 热的国产99热| 这里只有精品视频免费在线观看| 99在线观看| 1级欧美日韩| 婷婷欧美综合| 国产婷婷五月天| 自拍偷窥99热| av人人操| 久久五月婷综合网| 伊人久久婷| 国产精品天天狠天天看| 激情五婷网| 天天干天天干天天干天天干天天干天天| 五月花免费视频| 六月婷婷激情| 一本久道综合99| 噜噜噜色噜噜| 99热在线播放| 日本久久视频| 很很干天天干| 五月婷婷丁香日韩在线| 五月丁香日本片| 欧美婷婷精品激情| http:色情日本com| 激情丁香五月天综合| 亚洲第79页| 日本色婷婷| 五月婷婷六月丁香玖玖玫瑰91| 色色婷五月天| 狠狠干无码| 伊人久热91| 五月丁香久久激情网| 日韩精品999| 国产黄色大片| 激情小说之五月| 深爱激情五月婷婷| 99操久久| 婷婷九九| 五月停停色| 人人视频色| 久热只有精品| 日韩综合网络男女香蕉a片| 天天爽天天干天天| 伊人喵咪a V| 六月婷婷无码| 免费视频99| 一本久道综合99| 夜夜干天天干| 久久丁香网| 先锋男人99资源| 99热这里只有精品3| 99热高清在线| 丁香五月天堂网| 91制片厂久久久国产电影| 天天摸,天天爽| 五月天婷婷色综合| 色色五月天婷婷| 99九九精品视频| 午夜免费高清AV片| 五月婷婷亚洲色视频| 丁香八月综合激情| 人人爱国产| 果冻传媒A片一二三区| 五月婷婷香蕉| 久久婷婷五月丁香蜜桃网| 亚洲avjiujiur91| 五月婷视频| 激情综合久久| 亚洲天堂99| 97成人丁香婷婷| 97色色色色色| 99re99热| 午夜天天精品视频| 色五月丁香伊人| 日韩久久日| 日日爽日日爽| 七七九色| 婷婷丁香五月天激情| 五月丁香亚洲校园欧美| 五月综合激情婷婷六月色窝| 欧美日本一区二区三区| 久久中国毛毛片爱久久| 991精品在线视频| 九九久久99精品免费观看www| 五月婷婷偷拍| 婷婷五月天xxx| 开心激情播播五月天| 国产五月视频| 色婷婷基地| 日韩一级网站| 99视频在线精品| 另类五月婷婷| 色播激情| 97人人干人人操| 丁香色五月婷婷17C| 99熟女| 五月丁香狠狠爱婷婷综合| 亚洲网在线观看| 狠狠干五月丁香综合网| 色v综合网| 99精品网| 色99网| 色色色婷婷五月天| 亚洲精品字幕在线观看| se99视频| 都市激情久久| 超级碰91| 丁香五月天综合| 狠狠操狠狠狠| 久久婷婷综合基地| 办公室少妇激情呻吟A片在线观看| 婷婷五月天熟妇| 国产婷婷五月| 色99在线| 99爱爱网| 亚洲久久婷婷丁香五月天| 欧美123区免| 五月天啪啪视频| 五月婷色丁香| 9久热免费视频99| 99热在线观看| 伊人色综合网| 婷婷五月天xxx| 九九热99精品| 狠狠穞A片一區二區三區| 欧美成人精品一区二区| 婷婷丁香97| 97亚洲视频在线| 亚洲艹网| 91日精品| 69超碰在线| 五月天天综合| 思思热热久久| 婷婷月五天在线在线看| 亚洲AV电影美洲AV电影| 精品无码久久久久久久久| 五月婷婷免费在线视频| 五月婷婷色丁香| 狠狠爱婷婷丁香| 丰满少妇乱A片无码| 激情五月天视频| 久久国产精品乱子伦_靑青草…| 日本 色综合| 五月丁香在线| 欧美色色色色色| 色五月丁香六月婷婷| 五月久久婷婷| 亚洲爱婷婷| 中文字幕有多少字| 五月丁香黄色视频| 99热这里是精品| 97婷婷丁香五月天激情图片| 丁香成人五月天| 91大神在线免费看视频全集男男一起操| 天天插天天干| 国产91视频| 啪啪小说五月天| 欧美操我| 五月婷婷先锋| 97超碰婷婷五月天| 日韩婷婷| 婷婷五月天电影网| 五月天婷婷网站888| 亚洲A色| 激情q青青草在线婷婷| 五月婷婷九九热| 西西4r午夜剧场| 99久久综合网| 色999亚洲人成色| 色五月亚洲| 丁香婷婷久久综合在线| 婷婷美女精品视频| 六月丁香啪| 成人国产综合| 黄色精品五月婷婷| 激情99| 丁香五月黄色| 色涩影院六月丁香| 91pornav在线| 日都一级A片| 色五月婷婷91在线| 婷婷五月天天激情| 婷婷97C| 婷婷丁香成人色综合| 大香蕉婷婷| 99无码视频| 九九色色| 任你爽视频| 26uuu精品一区二区| 亚洲超碰在线| 五月天啪啪啪| 噜噜色婷婷| 久久久精品色色色| 26uuu| 六月色播| 婷婷成人AV| 婷婷99狠狠躁天天躁中| 五月婷婷激情综合| 思思热在线视频精品| 婷婷九月| 最近中文字幕在线中文视频| 99re热视频这里只精品| wwwav大香蕉| 欧美三级视频| 五月婷婷六月丁香玖玖玫瑰91| 日日噜噜久久婷婷五月天| a毛片二逼wwwwwwwwww| 玖玖九九9999在线观看视频精品| 久久中国毛毛片爱久久| 9福利性视频欧美| 九热...av| AAA久久| 99热网站| 丁香激情六月天婷婷| 婷婷五月天成人影片| 亚洲AV成人无码久久精品老人法拉利| AV人人操| 久久综合丁香激情五月| 日本少妇裸体做爰高潮片 | 日本99视频| 亚洲综合久| 精热在线综合网| 天堂五月婷婷| 亚洲操B| 26uuu精品一区二区| 激情五月六月婷婷| 午夜无码熟熟妇丰满人妻| 亚洲色图五月丁香五月婷婷| 久久丁香五月| 爱草视频在线观看| 激情五月天影院| 色婷婷久久综合| 六月天婷婷| 日碰日| 97电影99热| 丁香五月天天哦| 色婷婷a三区麻| 五月天丁香久久| 五月综合久久| 任你搞在线观看视频| 婷婷丁香97| 开心五月丁香啪| 久操97| 99色色网| 免费97碰碰| 色欲婷婷夜夜| 天天日 天天草| 五月天大香蕉| 五月天停停日日| 琪琪理论片| 亚洲成人五月| 4399无码视频| 4399亚洲视频| 久久色五月天综合网| 97干视频| 一区=区操屄高清大全av| 99热亚洲| 婷婷丁香综合成人| 婷婷亚洲综合| 九色 在线| 丁香激情六月天婷婷| 综激情网| 4399精品一区二区| 五月天激情小说电影| 九九热精品| 国产FREESEXVIDEOS性中国 | 99色精品| 亚洲黄网AV| 婷婷色网站| 狠狠干综合网| 99ER热精品视频| 丁香婷婷色色| 丁香桃色网| 日本人妻伦在线中文字幕| 日本97久久久精品| 青草激情在线| 国产日韩欧美| 五月天丁香六月综合| 思思热视频在线| 亚洲激情四谢| 六月丁婷婷| 色播婷婷五月天| 99在线综合视频| 激情综合网亚洲色图| 天天色天天日| 丝袜大香蕉| 精品人妻在线| 欧美日韩中国| 99热这里只有精品在线播放| 五月婷婷爽爽爽| 激情五月图| 1024日韩| 久操热线| 啪啪激情综合| 亚洲 视频 导航 一区| 五月丁香六月综合激情无码软件亮点| 九九婷婷激情综合网| WWW丁香五月| 婷婷伊人网| 黄色AV日韩| 久热超碰91| 欧美久人人| 丁香五月天在线观看| 婷婷亚洲在线| 人人做天天爱| 深夜婷婷 丁香| 丁香婷婷五月天色播| 天天综合精品| 国产99精品免费视频| 亚洲激情久久| 九九视频这里只有精品在线播放| 日本色色色| 久久综合激情五月天| 99热亚洲精品| 依人大香蕉| 中文字幕成人| 亚洲丁香婷婷五月天综合色| www.久久99| 国产伊人五月天| 九久9精品| Av性爱网站| 国产人妻人伦精品一区二区| 久久99热 这里有精品| 日本强伦片中文字幕免费看| 在线A色| 丁香婷婷影院| 天天色视频| 先锋资源91| AV在线中文| 啪啪一区| 老师的粉嫩小又紧水又多A片视频| 五月婷婷激情色情网| 中文字幕在线aⅴ免费观看| 久久婷婷五月草视频| 91呦呦呦| 26uuu欧美| 大香蕉婷婷丁香天堂AV| 色五月婷婷网| 色婷婷丁香五月综合| 婷婷国产五月天17c| 色色A| 婷婷六月啪啪| 国产亚洲精品久久久久久牛牛| 天天操夜夜玩!| 激情婷婷22月间| 久re热视频| 五月天婷婷综合久久| 人妻丰满精品一区二区A片| 97五月天婷婷| 伊人色综合影院视频| 五月天激情小说网| 99热这里只有在线| WWW.99视频| 涩五月婷婷| 天天综合影院| 日本九九九九| 国产精品91抖高| 激情五月六月| 久久五月视频| 9久操| 丁香五月天激情视频| 久久这里只有精品16| 国产综合81p| 婷婷五月综合在线| 婷婷丁香成人五月天| 91婷婷色五月| 婷婷在线中文字幕| 五月婷婷狠狠干| 九色视频这里只有精品| 六月撸婷婷| 少妇搡BBBB搡BBB搡毛茸茸| 99热一区| 五月色丁香婷婷中文字幕| 亚洲免费在线观看岛国| 丁香六月婷婷综合| 超碰不卡在线| 日韩av干| 五月色婷| www.九月婷婷丁香.com| 99热精品在这里| 亚洲欧美一区二区三区四区爱爱动图| 婷婷色婷婷亚洲成人| 奇米影视777在线_在线观看午夜_h小视频在线观看_岛国大片 | 婷婷日| 超碰在线中文字幕| 欧美午夜乱妇午夜福利| 久热91| 久久99热久久99精品| 婷婷伊人无码| 色色狼人综合| 91精品久| 日本少妇裸体做爰高潮片 | 99热6精品| 翔田千里aV中文字幕| 亚洲AV免费国产电影| 人妻丰满精品一区二区A片| 久久婷婷内射| 亚洲成人噜噜| 四虎婷婷五月天| 激情九月婷婷| 久9视频免费播放| 182.t午在线观看| 六月丁香网| 97九色| 亚洲综合激情五月久久| 操操操操操电影网| 婷婷五月成人有| AV在线观看网站| 丁香婷婷久久综合在线| 国产伦亲子伦亲子视频观看| 丁香婷婷视频一区二区| 性色播| 日韩在线视频中文字幕| 99婷婷五月天激情| 激情婷婷护士激情| 97操操网| 成人午夜天| 五月综合色| 91五月天| 天天插天天插天天插天天插| 97人人做| 综合网啪啪| 五月婷婷色播| 性色五月天| 九九精品视频在线6| 天天综合天天玩夜夜玩天天玩夜夜玩 | 激情五月天在线视频| 91日视频| 亚洲AV中文在线| 2020日日干| 日本久久人| h亚洲| 色色色婷婷| 涩婷婷五月天在线精品视频| 色婷婷狠狠| 亚洲色99| 久久久久久久人妻| 五月天伊人久久久久| 婷婷中文字幕| 婷婷色操| 五月婷婷欧美| 五月天丁香网| 99精品热| 五月天激情小说| 中文中文在线| 激情综合丁香六| 五月婷婷玖玖综合玖玖爱| 97爱艹婷婷开心丁香激情综合| 国产真实乱了老女人视频| 丁香婷婷综合激情五月色| 国产精品99久久久久久久女警| www.婷婷五月天| 欧美成人AAA片一区国产精品| 色色无码| 亚洲一区二区色图-亚洲精品国产精品乱码-成人AV | 激情丁香五月| 亚洲激情四射色| 日本三级第一页| 成人片在线免费看| 激情综合网五月| 综合天天综合| 99在线视频精品| 99精品22| 猫咪伊人久久| 五月天精品| 日本二级毛片二级毛片| 激情碰碰碰| 久大香蕉| 丁香婷婷五月天校园春色| 黄涩毛片| 丁香五月天成人网站| 日韩精品999| 综合网色| 色操综合| 丁香五月中文字幕| 丁香婷婷综合五月天| 开心五月色婷婷综合开心网| 99热成人精品网站| 99热激情| 久久九九99视频| 婷婷五月色情| 五月婷婷在线丁香| 九九热这里只有精品31| 丁香五月婷婷激情尤物| 操碰97| 亚洲天堂AV综合网| 99在线视频色版| 桃色激情婷婷伊人网| 欧美激情综合五月色丁香| 狠狠人妻色综合| 99国产精品白浆在线观看免费 | 亚洲网视屏| 五月丁香啪啪激情| 天天操天天操天天操天天操天天操 | 777.色色| 婷婷九月丁香| 激情五月婷婷| 国产肏屄大片| 深爱婷婷色| www.婷婷六月天| 2018国产大陆天天弄| 激情丁香久久| 五月天合网| 婷婷五月激情丁香| 亚洲人人操| 97伊人综合婷婷| 婷婷五六月丁香| 六月婷婷中文字幕| 欧美S码亚洲码精品M码| 婷婷玖玖五月天| 国产五月天激情小说| 日婷婷久久开心| 色五月婷婷久久| 色五月婷婷五月天激情综合| 天天操夜夜夜拍拍拍| www.久久综合| 综合色在线| 人妻久久久久| 色婷婷久久综合久色综| 亚洲亚洲人成综合网络| 五月天天堂久久| 五月婷AV| 中文字幕永久在线| 色欲五月婷婷| 综合五月丁香六月婷婷| 国产精品久久久久久久久久| 欧美久久网| 国产VA亚洲VA96| 99这里只有精品| 婷婷丁香97| 五月婷婷免费在线视频| 欧美成人在线观看| 六月丁香婷婷拍拍| 碰97久久| 操日本色| 丁香五月婷婷激情中文| 无码免费人妻A片AAA毛片西瓜| 综合激情在线| 丁香五月在线播放| 五月天久久婷| 五月婷婷视频啪啪美女| 婷婷伊人五月天| 97影院一级片| 日日噜噜夜夜狠狠久久丁香五月| 天天色中文字幕女优AV| 天天天天天色| av九九| 色婷婷五月天激情| 亚洲视频五区| 久艹大香蕉| 久狠狠| 亚洲第一影院高清无码网站| 性天天中文网| 思思干精品| 色五月天激情| 99热99艹在线观看| 综合狠狠干| 色五月婷婷五月天| 爱之国产色情综合| 亚洲激情另类| 激情五月黄色小说| 欧美色五月| 好好干Av| 六月丁香久久| 梁铮版蜘蛛女在线观看| 大香蕉综合在线| 少妇丁香婷婷 | 99热天堂| 婷婷五月色影视先锋| 久久人妻视频| 色偷偷色婷婷| 久久狠狠干| 另类专区在线| 欧美在线视频99| 婷婷色婷婷亚洲成人| 色色日本| 最新午夜理论片| 疯狂做受XXXX高潮A片| 夜夜骑操AV| 青柠影视免费高清电视剧| 激情校园 亚洲| 久久无码成人| 婷婷丁香五月综合网上 | 九九热黄色| 激情五月婷婷网| eeuus五月婷| 精品成人无码A片观看香草视频| 婷婷涩涩网| a免费在线| 亚洲国产精品VA在线看黑人| 欧美色九| 亚洲精品99| 婷婷五月情色| 婷婷干| 我去色色网五雨天| 噜噜干日本| 五月婷婷六月色| 26uuu欧美亚洲日韩| 刘玥精品一区| 天堂久久性| 91欧美| 国产99久久久国产精品免费看 | 在线视频九色97| www.色婷婷.com| 亚洲综合九九| 成人国产欧美大片一区| 欧美激情凹凸丁香网| 日本97久久久精品| 99在线精品观看99| 亚洲色婷婷网站| 久久激情婷婷| 99精品久久| 婷婷深爱五月亚洲综合| 色yeye色综合| www.激情| 天天开心AV色综合婷婷五月天| 婷婷影院欧美| 五月丁香亚洲综合| 天天日人人爽| 91九色国产熟女| 久操操| 情久久综合五月天| 九九香蕉网| 性爱激情综合网| www.久久爱.com| 五月丁香少妇A| 超碰色天堂| 九九色精品| 激情五月天激情小说| 婷婷99| 成人久碰| 五月天久久久| 丁香五月婷婷激情中文| 激情四射五月天| 99精品视频播放| 激情综合久久| 新伍月婷婷| 99亚洲精品视频在线观看| 男同91| 99日韩| 五月花婷婷丁香| 久久婷婷热| 国产精品A片在线| 99精品色| 亚洲激情综合| 婷婷五月天伊人网在线观看视频| 亚洲啪啪网| 九九综合影音先锋| 99精品自拍| 婷婷五月天狠狠| 日本女va| 久久久婷丁香五月天激情综合| 色色色色欧美| 97色婷| 夜夜干 夜夜操| 丁香婷婷人妻综合网| 色偷偷色婷婷| 久久成人亚洲欧美电影| 99日韩| 成人丁香色| 99视频热| 婷婷五月丁香狠狠| 91大神操美女| 日韩久久欧亚| 久久人妻超碰一区| 99热这里只有精品青草| 激情五月丁香亭亭 | 五月婷婷综合激情小说| 99在线精品视频在线观看| 人妻久久人妻久久第一区| 五月天影院婷婷在线观看| 人妻人人操| 免费看成人747474九号视频在线观看| 五月婷A V在线| 思思热在线视频精品| 玖玖在线视| 四月丁香五月婷婷久久| 激情婷婷六月| 六月婷婷狠狠| 《诡秘之主》在线观看| 五月丁香欧美综合| 久婷视频| 亚洲无码影片| 9久久狠狠的| 五月婷婷丁香| 五月天精品| 99热超碰在线| 五月婷婷啪| 操逼六区| 丁香五月激情综合| 五月天伊人网| 中文在线视频久1| 婷婷五月天综合色| 99精品在线下载| 五月丁香狠狠爱婷婷综合| 精品在线| 人人爽人人射-美女久久久久久久久久-成人AV | 丁香色情五月综合网站| 婷婷六月丁香久| 视频综合网| 日韩色色色99| 国产激情久久| 色色五月婷婷| 丁香六月激| 激情图片亚洲| 人妻久久做| 九九视频网| 丁香五月婷婷久久久| 婷婷丁香五月av| WWW色综合| 青青操绿aaa一区日v| 婷婷五月中文在线| 色狠狠五月天| 欧美大奶熟女噜噜噜噜| 久久久久久草黄色片AV在线观看| 亚洲艹网| 久久婷出差欧美色两性综合网| 丁香五月色综合色播五月| 久久99激情| 激情五月综合ì香亚洲| 六月婷婷色宗合| www久热com| 99热免| 玖玖五月丁香| 婷婷综合亚洲| 九月综合| 婷婷操逼| 情婷婷五月天在线| 亚洲瑟瑟精品在线| 色操b| 久久久这里有精品| 天天人人人人人人人人人人人| 区美毛片子| 五月丁香亚洲综合| 五月丁香综合激情| 日韩性爱AV| 伊人大香久久| 五月丁香激情综合啪啪| 97色色色| 玖玖资源部在线播放| 婷婷五月天99| 五月天最新网| 99热播放| 国产69久久久欧美黑人A片| 婷婷丁香红五月91C| 人妻激情网| 五月丁香激情四射综合| 色八月婷婷| 五月丁香另类网| 九九热这里只有精品6| 久久久WWW| 嫩草AV久久伊人妇女超级A | 99福利视频| 99在线免费观看| 五月天久久婷婷| 草了bav视频在线观看| 操婷婷久久| 思思99热这里只有精品| 久久婷婷五月综合色播| www夜夜操com| www.99色| 99九九这里有免费视频| 激情久久 婷婷| eeuss人妻| 色婷婷久久综合丁香五月| 婷婷99狠狠躁天天躁中| 国精产品一区一区三区免费视频 | 无码人妻一区| 亚洲色网络| 99在线资源视频| 久草性爱| 天天日,夜夜爽| 狠狠99| 青青久在线视频免费观看| 综合玖玖偷拍| 99热久久这里只有精品| 天天做天天爱天天要| 婷婷天天色| 婷婷94s| 久热这里只有精品6官网亚洲| 乱色色色| AV操操操| 婷婷五月天首页激情| 欧美黑人大吊| 99精品在这里| 五月天激情小说| 婷丁香五月天| 日日夜夜噜噜爽爽| 新97人人上人人| 热日韩欧美| 国产 亚洲 在线| 激情五月天激情综合网| 六月丁香五月婷婷| 99色在线免费观看视频| 激情婷婷五六月天| 九九热大香蕉| 丁香五月天91| 色婷婷色五月另类综合| 天天日天天色| 亚洲中文字幕AV在线| 久久婷婷五月天懂色| 丁香五月a| 99热综合| 丁香九月婷婷综合| 五月丁六月香| 色久九| 色色热日| 五月婷婷内射网| 91无码高清| 九九婷婷热| 欧美日韩大黄| www.婷婷五月| www.99热这里精品| 噜噜噜色噜噜| 久久xxxx| 五月婷婷色色色| 精品色色| 精品无码片| 亚洲精品五月| 久久精品国产一区二区三区四区| 另类图片色五月| 日亚二欧美| 日韩精品一区二区刘| 五月婷婷无码专区| 狠狠狠狠狠狠| 五月丁香亚洲校园欧美| 色婷婷天堂| 色青五月天| 丁香婷婷视频| 20253AV| 深爱激情久久| 青柠影视免费高清电视剧| 六月丁香婷婷色狠狠久久| 激情久久肏屄视频| 五月开心久久| 婷婷五月激情小说| av一区二区电影免费在线观看| 婷婷五月天激情综合深爱| 国产精品99久久久久久久女警 | 99免费在线视频| www久久久久久久| 婷婷香五月综合激情| 欧美三级巜人妻互换| 九九99视频精品| 天天日天天插| 99热只有精品在线播放| 色婷婷小说| 天天久久狠狠色综合| 亚洲99综合| 中文字幕av久久爽一区| 伊久久婷婷| 久热中文字幕| 色综合激情| 99久久9| se99视频| 另类的婷婷| 欧洲色| 婷婷丁香五月久久| 欧美性猛交AAAA片黑人 | 丁香婷婷五月天色播| 国产精产国品一二三在观看| 一二三区视频韩国| 久在线88综合| 99热的无码| 99caobi| 婷婷刺激综合| 人人操人人操919999| 久久久久9| 五月婷五月婷伊人伊人五月婷| 色色99| 青草视频在线蜜臀| 97caop| www激情com| 99热高清在线| 国产婷婷五月天| 欧亚洲在线高清视频| 99re在线观看| 国产精品色色色色| av免费在线观看0| 久久久性爱视频| www久久久久久久97| 久久丁香| 777丁香六月青青草婷婷综合久月| 婷婷中文字幕网站| 色五月天综合网| 久久 婷婷 五月天| 婷婷五月天开心网| 日本精品。999| 影音先锋AV资源男人站| 激情综合网五月| 九久9精品| 九九热AV| 激情网五月婷婷| 五月婷婷综合社区| 超碰人人色| 五月婷婷熟女| 久久久香港| 中文字幕在线观看视频www| 亚洲精品五十一区| 丁香五月婷婷综合激情哟哟哟| 日日杆天天| 午夜丁香丁香婷婷| 欧美 色婷婷| 激情图片婷婷丁香五月| 五月婷婷激情刺激| 这里只有精品96| 伊人狠狠操| 一级性爱视频| 成人五月天在线视频在线观看| 色在线免费观看| 五月婷婷色影院| 99er国产| 色97啪啪| 99视频这里有精品| 激情小说 五月天| 99热免费精品| 亚洲精品国产A久久久久久| 狠狠插狠狠操| 色欲Av五月天| 99热www| 色婷婷五月天在线观看| 这里只有精品在线免费视频| 亚洲午夜电影| www.97视频| 色五月成人| 色五月婷婷久久大| 人妻av在线| 久久久久九九九九视屏小说88|