Unity 使用 Behaviac (二)让unity的行为能执行behaviac搭建的树的逻辑

本人也是第一次使用behaviac做开发,可能有很多不对的地方和不明确的地方。希望各路大神能指点迷津或者指出错误。感谢!!!

本篇主要讲了: 使用behaviac编辑的行为树可以导出数据:xml文件和胶水文件(文章后面会解析),Unity通过XML和胶水文件来实现其功能。

一:使用Behaviac创建cs文件(行为脚本)
在behaviac升到3.6.x之后,我们就可以在behaviac中船舰cs文件了,如下图所示在类型信息面板中创建一个基于Agent的行为类的时候,可以勾选“生成代码”的勾选框,然后点击 “打开代码生成位置” 就能看到一个cs文件。如果你不勾选 “生成代码” 的话,就只能在工程里面自己建一个behaviac中的Agent类。再自己绑定;
在这里插入图片描述
下面我们看一下勾选“生成代码”和不勾选时,Agent类的区别:
(一)勾选生成代码后创建的类:

using System;
using System.Collections;
using System.Collections.Generic;

public class DebugAgent : behaviac.Agent
{
	public string name = "";

	public behaviac.EBTStatus PrintName()
	{
///<<< BEGIN WRITING YOUR CODE PrintName
		return behaviac.EBTStatus.BT_INVALID;
///<<< END WRITING YOUR CODE
	}

}

(二)不勾选生成代码时,自己创建的类;需要绑定

using UnityEngine;
using System.Collections;
using behaviac;

[behaviac.TypeMetaInfo("DebugAgent", "DebugAgent->Agent")]
public class DebugAgent : Agent
{
    [behaviac.MemberMetaInfo()]//标记成员变量
    public string name;

    [behaviac.MethodMetaInfo()]//标记成员函数
    public EBTStatus PrintName()
    {
        UnityEngine.Debug.Log(name);
        return EBTStatus.BT_SUCCESS;
    }
}

以上两种方式都可以实现,不过为了方便,我是用behaviac自动生成的cs文件;

二:搭建行为树,导出胶水文件、cs和xml文件
然后我们简单的搭建一个行为树:
先看一下我新建的Agent实例(有个mName变量和一个PrintName的函数)
在这里插入图片描述
然后是我的行为树;(循环打印十次mName的变量值)
在这里插入图片描述

ok;行为树搭建完了,导出行为树DebugTree;勾选XML和cs
在这里插入图片描述
在导出的目录下(项目根目录的exported文件夹下)会有以下两个文件夹和一个xml文件;meta是元数据,用不到可以不用管;behaviac_generated文件夹下就是胶水文件。然后就是DebugTree.xml用来让unity的程序实现运行树的逻辑。
在这里插入图片描述

三:胶水文件、xml、资源包导入unity工程
我们需要将三个东西导入到项目中:
(一)behaviac资源包导入:
将behaviac3.6.39.unitypackage资源包导入工程,可在官网下载;点击跳转下载
(二)胶水文件导入:
将“步骤二”中导出的胶水文件所在的整个behaviac_generated文件夹拖到项目中;
(三)xml文件导入
将“步骤二”导出的xml文件拖到工程中
ok;我的项目结构如下
在这里插入图片描述
四:脚本注册绑定xml行为树

(一)首先我们需要创建一个和behaviac注册绑定的类来建立连接,能让程序按照树的逻辑运行。创建一个BehaviacHelper脚本让它用来加载行为树:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BehaviacHelper : MonoBehaviour
{
    //xml的名称
    public static string mBTName = "DebugTree";

    private void Start()
    {
        //注册
        InitRegister();

		//加载
		LaodBT();

        //执行
        DebugAgent[] agents = FindObjectsOfType(typeof(DebugAgent)) as DebugAgent[];
        for (int i = 0; i < agents.Length; i++)
        {
            agents[i].ExcuteBT();
        }
    }
	
	/// <summary>
    /// 加载行为树
    /// </summary>
	void LaodBT()
	{
		 // ① 第一种加载的方式:用Agent类加载
		 behaviac.Agent[] agents = FindObjectsOfType(typeof(behaviac.Agent)) as behaviac.Agent[];
	 	 for (int i = 0; i < agents.Length; i++)
         {
            agents[i].btload(mBTName , true);
         }

		 /*
  		  * ② 第二种加载的方式:用WorkSpace加载。一次性加载(这个没测试过,不知道有没有问题)
		  * bool btloadResult = behaviac.Workspace.Instance.Load(mBTName, true);
          * if (!btloadResult)
          *    Debug.LogError("Behavior tree data load failed! " + mBTName);
          */
	}

    /// <summary>
    /// 行为注册
    /// </summary>
    void InitRegister()
    {
        //设置调试功能
        behaviac.Config.IsHotReload = true;
        behaviac.Config.IsLogging = true;
        behaviac.Config.IsSocketing = true;
        behaviac.Config.IsProfiling = true;
        //  ↑↑↑↑↑↑↑  上面设置的是开发功能相关的调试功能,想要了解更多可以到官网查看资料:https://www.behaviac.com/language/zh/config/

        //指定xml文件的加载路径;和加载方式:使用XML方式加载
        //###behaviac默认路径是resources下,要想改成其他路径,要同时改动它的FileManger脚本中的FileOpen方法
        behaviac.Workspace.Instance.FilePath = Application.streamingAssetsPath;
        behaviac.Workspace.Instance.FileFormat = behaviac.Workspace.EFileFormat.EFF_xml;

        //根据Agent名称,注册
        behaviac.Agent.RegisterInstanceName<DebugAgent>("DebugAgent");
       
        /* 你可以注册多棵树:
         * behaviac.Agent.RegisterInstanceName<DebugAgent_2>("DebugAgent_2");
         */
    }

    private void OnDestroy()
    {
        behaviac.Workspace.Instance.UnLoadAll();
        behaviac.Workspace.Instance.Cleanup();
    }
}

(二)完善DebugAgent类:
如下图目录所示可以找到我们导入到unity中的DebugAgent脚本;
在这里插入图片描述
打开这个脚本,完善它

// -------------------------------------------------------------------------------
// THIS FILE IS ORIGINALLY GENERATED BY THE DESIGNER.
// YOU ARE ONLY ALLOWED TO MODIFY CODE BETWEEN '///<<< BEGIN' AND '///<<< END'.
// PLEASE MODIFY AND REGENERETE IT IN THE DESIGNER FOR CLASS/MEMBERS/METHODS, ETC.
// -------------------------------------------------------------------------------

using System;
using System.Collections;
using System.Collections.Generic;

public class DebugAgent : behaviac.Agent
{
    public string mName = "";
    
    /// <summary>
    /// 执行行为树回调
    /// </summary>
    public void ExcuteBT()
    {
        this.btsetcurrent(BehaviacHelper.mBTName);
        behaviac.Workspace.Instance.DebugUpdate();
        this.btexec();
    }

    public behaviac.EBTStatus PrintName()
    {
        print(mName);
        return behaviac.EBTStatus.BT_SUCCESS;
    }
}

ok,因为我们在上面的脚本中写的加载的路径是在StreamingAssest文件夹下,所以,在工程中创建StreamingAssets文件夹,并将xml文件放进来:
在这里插入图片描述

OK,这样我们注册的完成了,执行回调也写了;接下来就是Unity编译器的工作了

五:unity中创建测试运行
(一)创建一个空物体,命名为BehaviacHelper。并挂载BehaviacHelper脚本。
在这里插入图片描述
(二)再次创建两个空物体,为其挂载DebugAgent脚本,并各设置mName变量为不同的值。
在这里插入图片描述
在这里插入图片描述
(三)运行程序,结果如下,不同的mName变量的值都打印了10次
在这里插入图片描述
以上便是我近期研究的behaviac和unity整合使用的总结,如有写错或者不准确的地方还请各位路过的大佬指点明津。抱拳。告辞。

.

补充一点:很重要,拿笔记下来:

当你把导出的xml放到项目中了,behaviac默认读取的路径是Resources文件夹,如果你想要将xml放到自定义的路径中,在behaviac中有个FileManager脚本,你需要重写里面的FileOpen、DirOpen和FileClose方法。而且人家腾讯在函数注释上声明的很明确了已经,如果你自定义了一个路径,你需要重写此函数。
例如:本篇文章就将xml文件放到了StreamingAssets下,下面是我FileManager.cs改动后的代码:

using System.IO;
using System.Collections;
using System.Collections.Generic;

// please define BEHAVIAC_NOT_USE_UNITY in your project file if you are not using unity
#if !BEHAVIAC_NOT_USE_UNITY
// if you have compiling errors complaining the following using 'UnityEngine',
//usually, you need to define BEHAVIAC_NOT_USE_UNITY in your project file
using UnityEngine;
#endif//!BEHAVIAC_NOT_USE_UNITY

namespace behaviac
{
    public class FileManager
    {
        #region Singleton

        private static FileManager ms_instance = null;

        public FileManager()
        {
            Debug.Check(ms_instance == null);
            ms_instance = this;
        }

        //~FileManager()
        //{
        //    ms_instance = null;
        //}

        #endregion Singleton

        public static FileManager Instance
        {
            get
            {
                if (ms_instance == null)
                {
                    ms_instance = new FileManager();
                }

                return ms_instance;
            }
        }

        /// <summary>
        /// open the specified file, this function should be consistent with
        /// Workspace.SetWorkspaceSettings's first param 'workspaceExportPath' and Workspace.Load's first param 'relativePath'
        /// as 'filePath' is the conbination of workspaceExportPath and relativePath
        ///
        /// you may need to override this function if you gave a customized 'workspaceExportPath' or used a AssetBundle.
        /// </summary>
        /// <returns>The open.</returns>
        /// <param name="filePath">without extension</param>
        /// <param name="ext">'ext' coult be .xml or .bson</param>
        public virtual byte[] FileOpen(string filePath, string ext)
        {

            try
            {
                if (ext == ".bson")
                {
                    ext += ".bytes";
                }

                filePath += ext;
                byte[] pBuffer = File.ReadAllBytes(filePath);

				// ***经过测试,当你exe包打出来,只要filePath以及xml文件没有问题;这里就直接跳出了
                return pBuffer;
            }
            catch (System.Exception e)
            {
                string msg = string.Format("FileManager::FileOpen exception:'{0}'", filePath);
                behaviac.Debug.LogWarning(msg + e.Message + e.StackTrace);
            }
            
            try
            {
#if !BEHAVIAC_NOT_USE_UNITY

                if (Application.platform == RuntimePlatform.WindowsEditor ||
                    Application.platform == RuntimePlatform.OSXEditor)
#endif
                {
                    if (ext == ".bson")
                    {
                        ext += ".bytes";
                    }

                    filePath += ext;
                    byte[] pBuffer = File.ReadAllBytes(filePath);

                    return pBuffer;
                }

#if !BEHAVIAC_NOT_USE_UNITY
                else
                {
                    if (ext == ".bson")
                    {
                        filePath += ext;
                    }

                    #region 设置xml文件位置
                    //skip 'Resources/'
                    //int k0 = filePath.IndexOf("Resources");
                    int k0 = filePath.IndexOf("StreamingAssets");
                    #endregion


                    if (k0 != -1)
                    {
                        k0 += /*10*/16;
                        string filePathInResources = filePath.Substring(k0);

                        TextAsset ta = Resources.Load(filePathInResources) as TextAsset;

                        if (ta == null)
                        {
                            string msg = string.Format("FileManager::FileOpen failed:'{0}' not loaded", filePath);
                            behaviac.Debug.LogWarning(msg);

                            return null;
                        }
                        else
                        {
                            byte[] pBuffer = ta.bytes;

                            return pBuffer;
                        }
                    }
                    else
                    {
                        string msg = string.Format("FileManager::FileOpen failed:'{0}' should be in /Resources", filePath);
                        behaviac.Debug.LogWarning(msg);
                    }
                }

#endif
            }
            catch (System.Exception e)
            {
                string msg = string.Format("FileManager::FileOpen exception:'{0}'", filePath);
                behaviac.Debug.LogWarning(msg + e.Message + e.StackTrace);
            }

            return null;
        }

        public virtual void FileClose(string filePath, string ext, byte[] pBuffer)
        {
        }

        public virtual List<byte[]> DirOpen(string szDir, string ext)
        {
            List<byte[]> buffers = new List<byte[]>();

            try
            {
                //#if BEHAVIAC_CS_ONLY
                //#endif
#if !BEHAVIAC_NOT_USE_UNITY
                if (Application.platform == RuntimePlatform.WindowsEditor ||
                    Application.platform == RuntimePlatform.OSXEditor)
#endif//
                {
                    string searchPattern = (ext == ".bson") ? "*.bson.bytes" : "*.xml";

                    string[] allFiles = Directory.GetFiles(szDir, searchPattern, SearchOption.TopDirectoryOnly);

                    foreach (string filePath in allFiles)
                    {
                        //string filePath = file.Replace('\\', '/');
                        byte[] pBuffer = FileOpen(filePath, "");
                        buffers.Add(pBuffer);
                    }

                    return buffers;
                }

#if !BEHAVIAC_NOT_USE_UNITY
                else
                {
                    //Debug.LogWarning("szDir.ext:" + szDir + " " + ext);

                    #region 设置xml文件位置
                    //int resourceIndex = szDir.IndexOf("Resources");
                    int resourceIndex = szDir.IndexOf("StreamingAssets");
                    #endregion

                    if (resourceIndex != -1)
                    {
                        string localPath = szDir.Substring(resourceIndex + /*10*/16);

                        //Debug.LogWarning("localPath: " + localPath);
                        //TextAsset[] as2 = Resources.LoadAll<TextAsset>("behaviac/exported/meta");
                        TextAsset[] metaFiles = Resources.LoadAll<TextAsset>(localPath);

                        foreach (TextAsset mf in metaFiles)
                        {
                            //Debug.LogWarning("mf.name: " + mf.name);

                            if (!string.IsNullOrEmpty(mf.name))
                            {
                                //skip
                                bool bIsBson = mf.name.IndexOf(".bson") > -1;
                                bool bAskBson = (ext == ".bson");

                                if ((bIsBson && bAskBson) || (!bIsBson && !bAskBson))
                                {
                                    byte[] pBuffer = mf.bytes;
                                    buffers.Add(pBuffer);
                                }
                            }
                        }

                        return buffers;
                    }
                }

#endif
            }
            catch (System.Exception e)
            {
                string msg = string.Format("FileManager::DirOpen exception:'{0}'", szDir);
                behaviac.Debug.LogWarning(msg + e.Message + e.StackTrace);
            }

            return null;
        }

        public virtual bool FileExist(string filePath, string ext)
        {
            return File.Exists(filePath + ext);
        }
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值