品劃網(wǎng)絡(luò)做營(yíng)銷型網(wǎng)站如何在百度上營(yíng)銷
文章目錄
- 1 項(xiàng)目介紹
- 2 AI 代碼介紹
- 2.1 BTBaseNode / BTControlNode
- 2.2 動(dòng)作/條件節(jié)點(diǎn)
- 2.3 選擇 / 順序節(jié)點(diǎn)
- 3 怪物實(shí)現(xiàn)
- 4 其他功能
- 5 UML 類圖
項(xiàng)目借鑒 B 站唐老獅 2023年直播內(nèi)容。 點(diǎn)擊前往唐老獅 B 站主頁(yè)。
1 項(xiàng)目介紹
? 本項(xiàng)目使用 Unity 2022.3.32f1c1,實(shí)現(xiàn)基本的 AI 框架。其中,用 Cube(紅色)代替怪物模型,Cube(藍(lán)色)代替玩家,即 AI 目標(biāo)。

? 項(xiàng)目地址:https://github.com/zheliku/BehaviourTree_AI。
2 AI 代碼介紹
2.1 BTBaseNode / BTControlNode
? 所有結(jié)點(diǎn)都需要執(zhí)行各自的任務(wù),因此提取到基類節(jié)點(diǎn)中:
/// <summary>
/// 行為樹(shù)結(jié)點(diǎn)基類
/// </summary>
public abstract class BTBaseNode
{/// <summary>/// 執(zhí)行節(jié)點(diǎn)邏輯的抽象方法/// </summary>public abstract ENodeState Execute();
}
? 而控制節(jié)點(diǎn)需要知道其控制哪些節(jié)點(diǎn),因此相關(guān)內(nèi)容需要提取到控制節(jié)點(diǎn)的基類中:
using System.Collections.Generic;public abstract class BTControlNode : BTBaseNode
{// 存儲(chǔ)子節(jié)點(diǎn)的 Listprotected List<BTBaseNode> _childList = new List<BTBaseNode>();protected int _currentIndex = 0; // 當(dāng)前執(zhí)行到的子節(jié)點(diǎn)索引/// <summary>/// 添加子節(jié)點(diǎn)/// </summary>public virtual void AddChild(params BTBaseNode[] node) {_childList.AddRange(node);}
}
2.2 動(dòng)作/條件節(jié)點(diǎn)
? 動(dòng)作節(jié)點(diǎn)執(zhí)行具體的行為,沒(méi)有子節(jié)點(diǎn)。
? 執(zhí)行完行為后,可以返回是否執(zhí)行成功,因此需要外部添加執(zhí)行的方法。
using System;/// <summary>
/// 動(dòng)作節(jié)點(diǎn),執(zhí)行具體行為,沒(méi)有子節(jié)點(diǎn)
/// </summary>
public class BTActionNode : BTBaseNode
{private Func<bool> _action; // 返回值表示執(zhí)行是否成功public BTActionNode(Func<bool> action) { _action = action; }public override ENodeState Execute() {if (_action == null) return ENodeState.Failure;// 執(zhí)行行為return _action.Invoke() ? ENodeState.Success : ENodeState.Failure; }
}
? 條件節(jié)點(diǎn)用于評(píng)估條件,根據(jù)條件結(jié)果返回成功 / 失敗。
? 和動(dòng)作節(jié)點(diǎn)類似,也需要外部提供判斷條件的方法。
using System;/// <summary>
/// 條件節(jié)點(diǎn),評(píng)估一個(gè)條件,并返回成功 / 失敗
/// </summary>
public class BTConditionNode : BTBaseNode
{private Func<bool> _action; // 返回值表示執(zhí)行是否成功public BTConditionNode(Func<bool> action) { _action = action; }public override ENodeState Execute() {if (_action == null) return ENodeState.Failure;// 執(zhí)行行為return _action.Invoke() ? ENodeState.Success : ENodeState.Failure; }
}
2.3 選擇 / 順序節(jié)點(diǎn)
? 選擇 / 順序節(jié)點(diǎn)都僅依據(jù)子節(jié)點(diǎn)的狀態(tài),返回自己的狀態(tài)。因此只需要實(shí)現(xiàn) Execute() 方法即可,區(qū)別在于實(shí)現(xiàn)的邏輯不同。
using System;/// <summary>
/// 選擇節(jié)點(diǎn)<br/>
/// 特點(diǎn):<br/>
/// 1. 按順序執(zhí)行子節(jié)點(diǎn)<br/>
/// 2. 如果某子節(jié)點(diǎn)返回成功,則返回成功,不執(zhí)行后續(xù)結(jié)點(diǎn)<br/>
/// 3. 如果某子節(jié)點(diǎn)返回失敗,則繼續(xù)執(zhí)行下一個(gè)子節(jié)點(diǎn)
/// </summary>
public class BTSelectNode : BTControlNode
{public override ENodeState Execute() {var childNode = _childList[_currentIndex];var result = childNode.Execute();switch (result) {case ENodeState.Success: { // 成功,則重置索引,直接返回_currentIndex = 0;return ENodeState.Success;}case ENodeState.Failure: { // 失敗,則繼續(xù)下一個(gè)節(jié)點(diǎn)++_currentIndex;if (_currentIndex == _childList.Count) { // 執(zhí)行到最后,重置索引_currentIndex = 0;return ENodeState.Failure;}break;}case ENodeState.Running: {return ENodeState.Running;}default: throw new ArgumentOutOfRangeException();}// 沒(méi)有執(zhí)行完,或者節(jié)點(diǎn)失敗,才執(zhí)行該邏輯// 此時(shí)仍希望下一幀繼續(xù)往后執(zhí)行,因此返回成功return ENodeState.Success;}
}/// <summary>
/// 序列節(jié)點(diǎn)<br/>
/// 特點(diǎn):<br/>
/// 1. 按順序執(zhí)行子節(jié)點(diǎn)<br/>
/// 2. 只要有一個(gè)子節(jié)點(diǎn)返回失敗,則整個(gè)節(jié)點(diǎn)返回失敗<br/>
/// 3. 所有子節(jié)點(diǎn)都返回成功,則整個(gè)節(jié)點(diǎn)返回成功
/// </summary>
public class BTSequenceNode : BTControlNode
{public override ENodeState Execute() {var childNode = _childList[_currentIndex];var result = childNode.Execute();switch (result) {case ENodeState.Success: { // 成功,則繼續(xù)下一個(gè)節(jié)點(diǎn)++_currentIndex;if (_currentIndex == _childList.Count) { // 執(zhí)行到最后,重置索引_currentIndex = 0;return ENodeState.Success;}break;}case ENodeState.Failure: { // 失敗,則重置索引,直接返回_currentIndex = 0;return ENodeState.Failure;}case ENodeState.Running: {return ENodeState.Running;}default: throw new ArgumentOutOfRangeException();}return ENodeState.Success;}
}
3 怪物實(shí)現(xiàn)
? 類似 2024-07-12 Unity AI狀態(tài)機(jī)1 —— 框架介紹_有限狀態(tài)機(jī)編程框架-CSDN博客 中的怪物實(shí)現(xiàn),但將怪物數(shù)據(jù)寫(xiě)在各個(gè)行為的控制類中,因此具有以下 4 個(gè)控制類:
- PatrolControl(巡邏)
- ChaseControl(追逐)
- AttackControl(攻擊)
- BackControl(返回)
? 其余實(shí)現(xiàn)基本一致。
4 其他功能
? 為了輔助繪圖,在 Monster 類中的 Update 方法里判斷當(dāng)前執(zhí)行的行為 / 狀態(tài)。用二進(jìn)制位表示每個(gè)狀態(tài),異或運(yùn)算來(lái)計(jì)算當(dāng)前的狀態(tài):
private void Update() {_btAIRoot.Execute(); // 執(zhí)行行為樹(shù)switch (CurrentState) { // 依據(jù)當(dāng)前行為繪制輔助線case 1:AttackCtrl.DrawGizmos();break;case 2:BackCtrl.DrawGizmos();break;case 4:ChaseCtrl.DrawGizmos();break;case 8:PatrolCtrl.DrawGizmos();break;}
}
5 UML 類圖
