using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
///
/// 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.
///
public class Database : MonoBehaviour {
// _database & _dataNames are 1 to 1 relationship
private List
BTPrecondition
节点准入条件类,它继承与BTNode,他的抽象类如下:
它提供了一个新的接口:Check(),用于检查准入条件是否通过,通常用于条件节点
并重写了Tick函数,检查是否能够执行
public abstract class BTPrecondition : BTNode {
public BTPrecondition () : base (null) {}
// Override to provide the condition check.
public abstract bool Check ();
// Functions as a node
public override BTResult Tick () {
bool success = Check();
if (success) {
return BTResult.Ended;
}
else {
return BTResult.Running;
}
}
}
接下来是一些通用的准入条件,与数据库中的数据进行对比
using UnityEngine;
using System.Collections;
namespace BT {
///
/// A pre condition that uses database.
///
public abstract class BTPreconditionUseDB : BTPrecondition {
protected string _dataToCheck;
protected int _dataIdToCheck;
public BTPreconditionUseDB (string dataToCheck) {
this._dataToCheck = dataToCheck;
}
public override void Activate (Database database) {
base.Activate (database);
_dataIdToCheck = database.GetDataId(_dataToCheck);
}
}
///
/// Used to check if the float data in the database is less than / equal to / greater than the data passed in through constructor.
///
public class BTPreconditionFloat : BTPreconditionUseDB {
public float rhs;
private FloatFunction func;
public BTPreconditionFloat (string dataToCheck, float rhs, FloatFunction func) : base(dataToCheck){
this.rhs = rhs;
this.func = func;
}
public override bool Check () {
float lhs = database.GetData(_dataIdToCheck);
switch (func) {
case FloatFunction.LessThan:
return lhs < rhs;
case FloatFunction.GreaterThan:
return lhs > rhs;
case FloatFunction.EqualTo:
return lhs == rhs;
}
return false;
}
public enum FloatFunction {
LessThan = 1,
GreaterThan = 2,
EqualTo = 3,
}
}
///
/// Used to check if the boolean data in database is equal to the data passed in through constructor
///
public class BTPreconditionBool : BTPreconditionUseDB {
public bool rhs;
public BTPreconditionBool (string dataToCheck, bool rhs) : base (dataToCheck) {
this.rhs = rhs;
}
public override bool Check () {
bool lhs = database.GetData(_dataIdToCheck);
return lhs == rhs;
}
}
///
/// Used to check if the boolean data in database is null
///
public class BTPreconditionNull : BTPreconditionUseDB {
private NullFunction func;
public BTPreconditionNull (string dataToCheck, NullFunction func) : base (dataToCheck) {
this.func = func;
}
public override bool Check () {
object lhs = database.GetData(_dataIdToCheck);
if (func == NullFunction.NotNull) {
return lhs != null;
}
else {
return lhs == null;
}
}
public enum NullFunction {
NotNull = 1, // return true when dataToCheck is not null
Null = 2, // return true when dataToCheck is not null
}
}
public enum CheckType {
Same,
Different
}
}
行为节点
BTAction
至此,行为树的基本结构已经有了,Database作为我们的全局变量存放处,BTNode作为所有节点的base class
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace BT {
public class BTAction : BTNode {
private BTActionStatus _status = BTActionStatus.Ready;
public BTAction (BTPrecondition precondition = null) : base (precondition) {}
protected virtual void Enter () {
if (BTConfiguration.ENABLE_BTACTION_LOG) { // For debug
Debug.Log("Enter " + this.name + " [" + this.GetType().ToString() + "]");
}
}
protected virtual void Exit () {
if (BTConfiguration.ENABLE_BTACTION_LOG) { // For debug
Debug.Log("Exit " + this.name + " [" + this.GetType().ToString() + "]");
}
}
protected virtual BTResult Execute () {
return BTResult.Running;
}
public override void Clear () {
if (_status != BTActionStatus.Ready) { // not cleared yet
Exit();
_status = BTActionStatus.Ready;
}
}
public override BTResult Tick () {
BTResult result = BTResult.Ended;
if (_status == BTActionStatus.Ready) {
Enter();
_status = BTActionStatus.Running;
}
if (_status == BTActionStatus.Running) { // not using else so that the status changes reflect instantly
result = Execute();
if (result != BTResult.Running) {
Exit();
_status = BTActionStatus.Ready;
}
}
return result;
}
public override void AddChild (BTNode aNode) {
Debug.LogError("BTAction: Cannot add a node into BTAction.");
}
public override void RemoveChild (BTNode aNode) {
Debug.LogError("BTAction: Cannot remove a node into BTAction.");
}
private enum BTActionStatus {
Ready = 1,
Running = 2,
}
}
}
逻辑节点
BTParallel(并行节点)
继承BTNode,并行节点的作用是同时执行他的孩子节点
属性
存储孩子节点执行结果的列表
并行类型:所有孩子节点都能通过,并行节点才能够通过/只要有任意一个孩子节点能通过,并行节点就能通过
函数重写
个性化检查:检查其孩子节点能够执行
Tick函数
清除函数
添加/删除孩子节点函数
独有函数
重置结果,重置所有孩子节点结果
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using BT;
namespace BT {
///
/// BTParallel evaluates all children, if any of them fails the evaluation, BTParallel fails.
///
/// BTParallel ticks all children, if
/// 1. ParallelFunction.And: ends when all children ends
/// 2. ParallelFunction.Or: ends when any of the children ends
///
/// NOTE: Order of child node added does matter!
///
public class BTParallel : BTNode {
protected List _results;
protected ParallelFunction _func;
public BTParallel (ParallelFunction func) : this (func, null) {}
public BTParallel (ParallelFunction func, BTPrecondition precondition) : base (precondition) {
_results = new List();
this._func = func;
}
protected override bool DoEvaluate () {
foreach (BTNode child in children) {
if (!child.Evaluate()) {
return false;
}
}
return true;
}
public override BTResult Tick () {
int endingResultCount = 0;
for (int i=0; i
行为树入口
之前的代码都是行为树框架本身,现在,我们需要通过节点去构建这个行为树入口,以能够真正的使用
属性
数据库
布尔变量,是否正在运行
重置变量,用于重置行为树
函数
初始化函数
更新函数
这个比较重要,每次更新函数,首先要判断行为树是否正在运行,然后判断是否重置。
其次才是判断节点的检查函数,如果检查通过则执行节点的Tick函数也就是执行函数
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(RESET)) {
Reset();
database.SetData(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();
if (database == null) {
database = gameObject.AddComponent();
}
_resetId = database.GetDataId(RESET);
database.SetData(_resetId, false);
}
protected void Reset () {
if (_root != null) {
_root.Clear();
}
}
}
声明: 本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/
public class Singleton {
}
/*
* 懒汉模式。注意,getInstance如果在多线程环境中调用,需要加上synchronized,否则存在线程不安全问题
*/
class LazySingleton
这个月公司安排我一个人做iOS客户端开发,由于急着用,我先发布一个版本,由于第一次发布iOS应用,期间出了不少问题,记录于此。
1、使用Application Loader 发布时报错:Communication error.please use diagnostic mode to check connectivity.you need to have outbound acc
/*
2013年3月15日15:16:24
malloc 就memory(内存) allocate(分配)的缩写
本程序没有实际含义,只是理解使用
*/
# include <stdio.h>
# include <malloc.h>
int main(void)
{
int i = 5; //分配了4个字节 静态分配
int * p
http://wiki.sdn.sap.com/wiki/display/BOBJ/Optimize+query+with+Query+Stripping+in+Web+Intelligence
and a very straightfoward video
http://www.sdn.sap.com/irj/scn/events?rid=/library/uuid/40ec3a0c-936