自用行为树逻辑,分为权重和顺序
基类
using UnityEngine;
using XXKJ.Project2.Data;
/// <summary>
/// AI接口
/// </summary>
public interface IActorAIHelper
{
bool Boot { get; set; }
void AIInit(int id, float stunnedTime, BaseActorBrain bac);
}
/// <summary>
/// 仇恨类
/// </summary>
public class ActorHatred
{
public ActorHatred(BaseActorBrain tar, int value)
{
target = tar;
Hatred = value;
}
public BaseActorBrain target;
public int Hatred;
}
仇恨基类
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
public class BaseBattleAIHelper :MonoBehaviour,IActorAIHelper{
public BaseActorBrain CurTarget;
public List<ActorHatred> TargetList = new List<ActorHatred>();
public bool Boot { get { return isOpenAI; } set { isOpenAI = value; } }
protected bool isOpenAI;
public void SetHatred(BaseActorBrain tar, int value)
{
bool isContain = false;
for (int i = 0; i < TargetList.Count; i++)
{
if (TargetList[i].target == tar)
{
TargetList[i].Hatred += value;
isContain = true;
break;
}
}
if (!isContain)
{
TargetList.Add(new ActorHatred(tar, value));
}
}
public void RemoveHatred(GameObject tar)
{
for (int i = 0; i < TargetList.Count; i++)
{
if (TargetList[i].target == tar)
{
TargetList.RemoveAt(i);
}
}
}
public void UpdateHatredList()
{
for (int i = TargetList.Count-1; i>=0 ; i--) {
if (TargetList[i].target == null || TargetList[i].target.CurFSMState.ID == FSMStateID.DEAD||!TargetList[i].target.gameObject.activeInHierarchy) {
TargetList.RemoveAt (i);
}
}
if (TargetList.Count == 0) {
CurTarget = null;
return;
}
TargetList.Sort(HatredCompare);
CurTarget = TargetList[0].target;
}
public int HatredCompare(ActorHatred a, ActorHatred b)
{
if (a.Hatred > b.Hatred)
return 1;
else if (a.Hatred < b.Hatred)
return -1;
float aDis = Vector3.Distance(a.target.transform.position, transform.position);
float bDis = Vector3.Distance(b.target.transform.position, transform.position);
if (aDis > bDis)
{
return 1;
}
else if (bDis > aDis)
{
return -1;
}
return 0;
}
public virtual void AIInit (int id, float stunnedTime, BaseActorBrain bac)
{
}
}
行为节点基类
/// <summary>
/// Behavior Tree
/// </summary>
using UnityEngine;
///basenode
public class BaseNode {
//父节点
public BaseNode mParentNode;
//子节点
public BaseNode[] mChildNodeList;
//内在前提
protected virtual bool _DoEvaluate (BevTreeInput bti) {
return true;
}
//外在前提
protected BaseNodePrecondition mo_NodePrecondition;
public bool Evaluate (BevTreeInput bti) {
return (mo_NodePrecondition == null || mo_NodePrecondition.ExternalCondition(bti)) && _DoEvaluate (bti);
}
public virtual BevTreeOutput GetConclusion (BevTreeInput bti) {
return default(BevTreeOutput);
}
}
//前提
public class BaseNodePrecondition {
public virtual bool ExternalCondition (BevTreeInput bti) {
return true;
}
}
//输入
public class BevTreeInput {
public BaseBeing self;
public int[] CanCastSKill;
public int weaponType;
public int skillStep;
public Transform CurTar;
public float TargetDisX;
public float TargetDisZ;
}
//输出
public struct BevTreeOutput {
public FSMEvent OutputEv;
}
//行为树基类
using UnityEngine;
using System.Collections;
public class BaseAIBevTreeControl{
protected BaseNode Root;
public BaseAIBevTreeControl () {
}
public FSMEvent GetResult (BevTreeInput bti) {
if (Root.Evaluate (bti)) {
return Root.GetConclusion (bti).OutputEv;
}
return null;
}
}
///行为树基类,行为不都传了,参考一下即可
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using XXKJ.Project2.Data;
public class PlayerBevTreeControl : BaseAIBevTreeControl
{
public PlayerBevTreeControl(int weaponType, List<ActorSkillInfo> skillInfo)
{
//根节点
Root = new OrderControlNode();
//二级节点
BaseControlNode attackNode = new OrderControlNode();
BaseControlNode moveNode = new WeightControlNode(90,10);
BaseControlNode rightMoveNode = new OrderControlNode();
//三级
BaseControlNode runNode = new OrderControlNode();
BaseControlNode otherNode = new WeightControlNode(100);
行为节点
BaseActionNode idle = new PlayerIdleANode();
//技能
PlayerAI_Ex ai = DataManager.GetInstance().ExcelObjectByID<PlayerAI_Ex>(weaponType);
BaseActionNode forward = new PlayerRunForwardANode(ai);
BaseActionNode right = new PlayerRightRunANode(ai);
string[] skillIDArr = ai.SkillList.Split('|');
int[] skillArr = new int[skillIDArr.Length];
for (int i = 0; i < skillIDArr.Length; i++)
{
skillArr[i] = int.Parse(skillIDArr[i]);
}
List<ActorSkillInfo> skillList = new List<ActorSkillInfo>();
if (skillInfo.Count > 0)
{
for (int i = 0; i < skillArr.Length; i++)
{
for (int j = 0; j < skillInfo.Count; j++)
{
if (skillInfo[j].btnIndex == skillArr[i])
{
skillList.Add(skillInfo[j]);
}
}
}
}
BaseActionNode skills = new PlayerSkillANode(skillList, ai);
skills.mParentNode = attackNode;
//绑定关系
Root.mChildNodeList = new BaseNode[3] { attackNode, moveNode, rightMoveNode };
attackNode.mChildNodeList = new BaseNode[1] { skills };
moveNode.mParentNode = rightMoveNode.mParentNode = attackNode.mParentNode = Root;
rightMoveNode.mChildNodeList = new BaseNode[1] { right };
right.mParentNode = rightMoveNode;
//移动
moveNode.mChildNodeList = new BaseNode[2] { runNode, otherNode };
runNode.mParentNode = otherNode.mParentNode = moveNode;
runNode.mChildNodeList = new BaseNode[1] { forward};
forward.mParentNode = runNode;
otherNode.mChildNodeList = new BaseNode[1] { idle };
idle.mParentNode = otherNode;
//
}
}
行为节点基类
using UnityEngine;
using System.Collections;
public class BaseActionNode : BaseNode {
}
行为节点基类2
using UnityEngine;
using System.Collections;
public class BaseControlNode : BaseNode {
}
//其中一个具体行为
using UnityEngine;
using XXKJ.Project2.Data;
using System.Collections;
public class PlayerRightRunANode : BaseActionNode
{
PlayerAI_Ex info;
public PlayerRightRunANode(PlayerAI_Ex _info)
{
info = _info;
}
protected override bool _DoEvaluate(BevTreeInput bti)
{
bool isCancast = false;
if (bti.weaponType == info.ID && bti.CurTar == null)
{
isCancast = true;
}
return isCancast;
}
public override BevTreeOutput GetConclusion(BevTreeInput bti)
{
FSMEvent eve = new FSMEvent();
eve.eventType = Transition.JoyStick;
eve.subType = SubTransition.Move;
eve.OperEnum = OperatorEnum.Fit;
eve.param1 = 0;
eve.objParam = new Vector2(1,0);
BevTreeOutput re = new BevTreeOutput();
re.OutputEv = eve;
return re;
}
}