DataBase
数据库作为存放所有数据的地方,能够通过key-Value的方式去调取任意数据,你可以理解为全局变量黑板,我们可以手动添加数据,并通过节点来访问数据:
using UnityEngine; using System.Collections; using System.Collections.Generic; using System; /// <summary> /// Database is the blackboard in a classic blackboard system. /// (I found the name "blackboard" a bit hard to understand so I call it database ;p) /// /// It is the place to store data from local nodes, cross-tree nodes, and even other scripts. /// Nodes can read the data inside a database by the use of a string, or an int id of the data. /// The latter one is prefered for efficiency's sake. /// </summary> public class Database : MonoBehaviour { // _database & _dataNames are 1 to 1 relationship private List<object> _database = new List<object>(); private List<string> _dataNames = new List<string>(); // Should use dataId as parameter to get data instead of this public T GetData<T> (string dataName) { int dataId = IndexOfDataId(dataName); if (dataId == -1) Debug.LogError("Database: Data for " + dataName + " does not exist!"); return (T) _database[dataId]; } // Should use this function to get data! public T GetData<T> (int dataId) { if (BT.BTConfiguration.ENABLE_DATABASE_LOG) { Debug.Log("Database: getting data for " + _dataNames[dataId]); } return (T) _database[dataId]; } public void SetData<T> (string dataName, T data) { int dataId = GetDataId(dataName); _database[dataId] = (object) data; } public void SetData<T> (int dataId, T data) { _database[dataId] = (object) data; } public int GetDataId (string dataName) { int dataId = IndexOfDataId(dataName); if (dataId == -1) { _dataNames.Add(dataName); _database.Add(null); dataId = _dataNames.Count - 1; } return dataId; } private int IndexOfDataId (string dataName) { for (int i=0; i<_dataNames.Count; i++) { if (_dataNames[i].Equals(dataName)) return i; } return -1; } public bool ContainsData (string dataName) { return IndexOfDataId(dataName) != -1; } } // IMPORTANT: users may want to put Jargon in a separate file //public enum Jargon { // ShouldReset = 1, //}
行为树入口
之前的代码都是行为树框架本身,现在,我们需要通过节点去构建这个行为树入口,以能够真正的使用:
using UnityEngine; using System.Collections; using System.Collections.Generic; using BT; // How to use: // 1. Initiate values in the database for the children to use. // 2. Initiate BT _root // 3. Some actions & preconditions that will be used later // 4. Add children nodes // 5. Activate the _root, including the children nodes' initialization public abstract class BTTree : MonoBehaviour { protected BTNode _root = null; [HideInInspector] public Database database; [HideInInspector] public bool isRunning = true; public const string RESET = "Rest"; private static int _resetId; void Awake () { Init(); _root.Activate(database); } void Update () { if (!isRunning) return; if (database.GetData<bool>(RESET)) { Reset(); database.SetData<bool>(RESET, false); } // Iterate the BT tree now! if (_root.Evaluate()) { _root.Tick(); } } void OnDestroy () { if (_root != null) { _root.Clear(); } } // Need to be called at the initialization code in the children. protected virtual void Init () { database = GetComponent<Database>(); if (database == null) { database = gameObject.AddComponent<Database>(); } _resetId = database.GetDataId(RESET); database.SetData<bool>(_resetId, false); } protected void Reset () { if (_root != null) { _root.Clear(); } } }
行为树的事件GraphEvent
当发送一个事件时,场景里的所有的owener都可以同时响应这个事件。
也可以通过脚本来发送事件,做受击响应可行。
发送事件
监听事件
脚本发送事件