add
This commit is contained in:
210
Assets/CoolapeFrame/3rd/Hivemind/Scripts/BTAsset.cs
Normal file
210
Assets/CoolapeFrame/3rd/Hivemind/Scripts/BTAsset.cs
Normal file
@@ -0,0 +1,210 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Coolape;
|
||||
|
||||
namespace Hivemind
|
||||
{
|
||||
|
||||
[System.Serializable]
|
||||
public class BTAsset : ScriptableObject
|
||||
{
|
||||
|
||||
public string serializedBehaviorTree;
|
||||
public BehaviorTree behaviorTree;
|
||||
|
||||
public BehaviorTree Deserialize ()
|
||||
{
|
||||
Hashtable map = JSON.DecodeMap (serializedBehaviorTree);
|
||||
// Behavior Tree
|
||||
BehaviorTree bt = ScriptableObject.CreateInstance<BehaviorTree> ();
|
||||
ArrayList nodes = MapEx.getList (map, "nodes");
|
||||
string type = "";
|
||||
Node node = null;
|
||||
//先把所有的node创建好
|
||||
for (int i = 0; i < nodes.Count; i++) {
|
||||
type = MapEx.getString (nodes [i], "type");
|
||||
switch (type) {
|
||||
case "Hivemind.Root":
|
||||
node = bt.CreateNode<Root> ();
|
||||
((Root)node).Deserialize (ListEx.getMap (nodes, i));
|
||||
bt.SetRoot ((Root)node);
|
||||
break;
|
||||
case "Hivemind.NodeAction":
|
||||
node = bt.CreateNode<NodeAction> ();
|
||||
node.Deserialize (ListEx.getMap (nodes, i));
|
||||
bt.nodes.Add (node);
|
||||
break;
|
||||
case "Hivemind.NodeBranch":
|
||||
node = bt.CreateNode<NodeBranch> ();
|
||||
node.Deserialize (ListEx.getMap (nodes, i));
|
||||
bt.nodes.Add (node);
|
||||
break;
|
||||
case "Hivemind.NodeTogether":
|
||||
node = bt.CreateNode<NodeTogether> ();
|
||||
node.Deserialize (ListEx.getMap (nodes, i));
|
||||
bt.nodes.Add (node);
|
||||
break;
|
||||
default:
|
||||
node = bt.CreateNode<Node> ();
|
||||
node.Deserialize (ListEx.getMap (nodes, i));
|
||||
bt.nodes.Add (node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 处理子节点的的关系
|
||||
for (int i = 0; i < nodes.Count; i++) {
|
||||
node = bt.getNodeByID (MapEx.getInt (nodes [i], "id"));
|
||||
node.DeserializeChildren (ListEx.getMap (nodes, i));
|
||||
}
|
||||
|
||||
behaviorTree = bt;
|
||||
return bt;
|
||||
//=============================
|
||||
// XmlDocument doc = new XmlDocument();
|
||||
// doc.LoadXml(serializedBehaviorTree);
|
||||
|
||||
// Behavior Tree
|
||||
// BehaviorTree bt = ScriptableObject.CreateInstance<BehaviorTree>();
|
||||
|
||||
// Root
|
||||
// XmlElement rootEl = (XmlElement)doc.GetElementsByTagName ("root").Item (0);
|
||||
// Root root = (Root)DeserializeSubTree (rootEl, bt);
|
||||
// bt.SetRoot (root);
|
||||
//
|
||||
// // Unparented nodes
|
||||
// XmlElement unparentedRoot = (XmlElement)doc.GetElementsByTagName ("unparented").Item (0);
|
||||
// foreach (XmlNode xmlNode in unparentedRoot.ChildNodes) {
|
||||
// XmlElement el = xmlNode as XmlElement;
|
||||
// if (el != null)
|
||||
// DeserializeSubTree (el, bt);
|
||||
// }
|
||||
//
|
||||
// behaviorTree = bt;
|
||||
// return bt;
|
||||
}
|
||||
|
||||
// private Node DeserializeSubTree (XmlElement el, BehaviorTree bt)
|
||||
// {
|
||||
// Node node = null;
|
||||
//
|
||||
// if (el.Name == "root")
|
||||
// node = bt.CreateNode<Root> ();
|
||||
// else if (el.Name == "action")
|
||||
// node = bt.CreateNode<NodeAction> ();
|
||||
//
|
||||
//// else if(el.Name == "sequence") node = bt.CreateNode<Sequence>();
|
||||
//// else if(el.Name == "selector") node = bt.CreateNode<Selector>();
|
||||
//// else if(el.Name == "randomselector") node = bt.CreateNode<RandomSelector>();
|
||||
//// else if(el.Name == "parallel") node = bt.CreateNode<Parallel>();
|
||||
////
|
||||
//// else if(el.Name == "repeater") node = bt.CreateNode<Repeater>();
|
||||
//// else if(el.Name == "untilsucceed") node = bt.CreateNode<UntilSucceed>();
|
||||
//// else if(el.Name == "inverter") node = bt.CreateNode<Inverter>();
|
||||
//// else if(el.Name == "succeeder") node = bt.CreateNode<Succeeder>();
|
||||
//
|
||||
// else
|
||||
// throw new System.NotImplementedException (string.Format ("{0} deserialization not implemented", el.Name));
|
||||
//
|
||||
// float x = float.Parse (el.GetAttribute ("editorx"));
|
||||
// float y = float.Parse (el.GetAttribute ("editory"));
|
||||
// node.editorPosition = new Vector2 (x, y);
|
||||
//
|
||||
//// if (node is NodeAction) ((NodeAction) node).Deserialize(el);
|
||||
//// else if (node is Sequence) ((Sequence) node).Deserialize(el);
|
||||
//// else if (node is Selector) ((Selector) node).Deserialize(el);
|
||||
//
|
||||
// bt.nodes.Add (node);
|
||||
//
|
||||
// foreach (XmlNode xmlNode in el.ChildNodes) {
|
||||
// XmlElement childEl = xmlNode as XmlElement;
|
||||
// if (childEl != null && childEl.Name != "param") {
|
||||
// Node child = DeserializeSubTree (childEl, bt);
|
||||
// node.ConnectChild (child);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return node;
|
||||
// }
|
||||
|
||||
public void Serialize (BehaviorTree behaviorTree)
|
||||
{
|
||||
Hashtable map = new Hashtable ();
|
||||
// map ["root"] = behaviorTree.rootNode.Serialize ();
|
||||
ArrayList nodes = new ArrayList ();
|
||||
for (int i = 0; i < behaviorTree.nodes.Count; i++) {
|
||||
nodes.Add (behaviorTree.nodes [i].Serialize ());
|
||||
}
|
||||
map ["nodes"] = nodes;
|
||||
serializedBehaviorTree = JSON.JsonEncode (map);
|
||||
}
|
||||
// XML Document
|
||||
// XmlDocument doc = new XmlDocument();
|
||||
// Hashtable doc = new Hashtable();
|
||||
//
|
||||
// // Behavior Tree
|
||||
//// XmlElement btEl = doc.CreateElement("behaviortree");
|
||||
//// doc.AppendChild(btEl);
|
||||
// Hashtable btEl=new Hashtable ();
|
||||
// doc ["behaviortree"] = btEl;
|
||||
//
|
||||
// // Root SubTree
|
||||
// SerializeSubTree (behaviorTree.rootNode, btEl);
|
||||
//
|
||||
// // Unparented nodes root
|
||||
// XmlElement unparentedEl = doc.CreateElement("unparented");
|
||||
// btEl.AppendChild(unparentedEl);
|
||||
//
|
||||
// // Unparented nodes
|
||||
// for (int i = 0; i < behaviorTree.nodes.Count; i++) {
|
||||
// if (behaviorTree.nodes[i].parents.Count == 0 && !(behaviorTree.nodes[i] is Root)) {
|
||||
// SerializeSubTree(behaviorTree.nodes[i], unparentedEl);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// serializedBehaviorTree = doc.InnerXml;
|
||||
// }
|
||||
|
||||
// private void SerializeSubTree(Node node, Hashtable parentEl) {
|
||||
// Hashtable doc = parentEl;
|
||||
//
|
||||
// string tagName = TagForNodeType(node.GetType());
|
||||
// Hashtable el = new Hashtable ();
|
||||
// doc [tagName] = el;
|
||||
// el["editorx"]= node.editorPosition.x.ToString();
|
||||
// el["editory"]= node.editorPosition.y.ToString();
|
||||
//
|
||||
// if (node is NodeAction) ((NodeAction) node).Serialize(ref el);
|
||||
//// else if (node is Sequence) ((Sequence) node).Serialize(ref el);
|
||||
//// else if (node is Selector) ((Selector) node).Serialize(ref el);
|
||||
//
|
||||
//// parentEl.AppendChild(el);
|
||||
//
|
||||
// int count = node.ChildCount;
|
||||
// for (int i = 0; i < count; i ++) {
|
||||
// SerializeSubTree(node.Children[i], el);
|
||||
// }
|
||||
// }
|
||||
|
||||
// private string TagForNodeType(System.Type nodeType) {
|
||||
// if (nodeType == typeof(Root)) return "root";
|
||||
// else if (nodeType == typeof(NodeAction)) return "action";
|
||||
// else if (nodeType == typeof(NodeBranch)) return "branch";
|
||||
|
||||
// else if (nodeType == typeof(Sequence)) return "sequence";
|
||||
// else if (nodeType == typeof(Selector)) return "selector";
|
||||
// else if (nodeType == typeof(RandomSelector)) return "randomselector";
|
||||
// else if (nodeType == typeof(Parallel)) return "parallel";
|
||||
//
|
||||
// else if (nodeType == typeof(Repeater)) return "repeater";
|
||||
// else if (nodeType == typeof(UntilSucceed)) return "untilsucceed";
|
||||
// else if (nodeType == typeof(Succeeder)) return "succeeder";
|
||||
// else if (nodeType == typeof(Inverter)) return "inverter";
|
||||
|
||||
// else return "node";
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
10
Assets/CoolapeFrame/3rd/Hivemind/Scripts/BTAsset.cs.meta
Normal file
10
Assets/CoolapeFrame/3rd/Hivemind/Scripts/BTAsset.cs.meta
Normal file
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f68a0330f34b8447290696a10f310892
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
178
Assets/CoolapeFrame/3rd/Hivemind/Scripts/BehaviorTree.cs
Normal file
178
Assets/CoolapeFrame/3rd/Hivemind/Scripts/BehaviorTree.cs
Normal file
@@ -0,0 +1,178 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* Best practices for serialization:
|
||||
* - Don't use the `new` constructor
|
||||
* - Instead use ScriptableObject.CreateInstance()
|
||||
* - For initialization, use OnEnable() instead of the constructor
|
||||
*
|
||||
* Unity calls the constructor, deserializes the data (populating the object) and THEN calls OnEnable(),
|
||||
* so the data is guaranteed to be there in this method.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Hivemind
|
||||
{
|
||||
|
||||
public enum Status
|
||||
{
|
||||
Success,
|
||||
Failure,
|
||||
Running,
|
||||
Error
|
||||
}
|
||||
|
||||
public class Context
|
||||
{
|
||||
private Dictionary<string, object> context = new Dictionary<string, object>();
|
||||
|
||||
public Dictionary<string, object> All {
|
||||
get { return context; }
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key)
|
||||
{
|
||||
return context.ContainsKey(key);
|
||||
}
|
||||
|
||||
public T Get<T>(string key)
|
||||
{
|
||||
if (!context.ContainsKey(key)) {
|
||||
throw new System.MissingMemberException(string.Format("Key {0} not found in the current context", key));
|
||||
}
|
||||
T value = (T)context [key];
|
||||
return value;
|
||||
}
|
||||
|
||||
public T Get<T>(string key, T defaultValue)
|
||||
{
|
||||
if (!context.ContainsKey(key)) {
|
||||
Set<T>(key, defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
T value = (T)context [key];
|
||||
return value;
|
||||
}
|
||||
|
||||
public void Set<T>(string key, T value)
|
||||
{
|
||||
context [key] = value;
|
||||
}
|
||||
|
||||
public void Unset(string key)
|
||||
{
|
||||
context.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class BehaviorTree : ScriptableObject
|
||||
{
|
||||
|
||||
public static string[] NodeTypes = {
|
||||
"Action", //动作
|
||||
"Branch", //两分支
|
||||
"Together", // 汇集
|
||||
// "Inverter",
|
||||
// "Parallel",
|
||||
// "RandomSelector",
|
||||
// "Repeater",
|
||||
// "Selector",
|
||||
// "Sequence",
|
||||
// "Succeeder",
|
||||
// "UntilSucceed"
|
||||
};
|
||||
|
||||
public int nodeIndex = 0;
|
||||
public Root rootNode;
|
||||
public List<Node> nodes = new List<Node>();
|
||||
|
||||
public bool debugMode = false;
|
||||
public Node currentNode = null;
|
||||
|
||||
public int TotalTicks { get; private set; }
|
||||
|
||||
public delegate void NodeWillTick(Node node);
|
||||
|
||||
public delegate void NodeDidTick(Node node,Status result);
|
||||
|
||||
public NodeWillTick nodeWillTick;
|
||||
public NodeDidTick nodeDidTick;
|
||||
|
||||
public Node getNodeByID(int id)
|
||||
{
|
||||
for (int i = 0; i < nodes.Count; i++) {
|
||||
if (nodes [i].id == id) {
|
||||
return nodes [i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SetRoot(Root root)
|
||||
{
|
||||
rootNode = root;
|
||||
nodes.Add(root);
|
||||
root.behaviorTree = this;
|
||||
}
|
||||
|
||||
public T CreateNode<T>() where T : Node
|
||||
{
|
||||
T node = (T)ScriptableObject.CreateInstance<T>();
|
||||
if (rootNode != null) {
|
||||
rootNode.maxIndex++;
|
||||
node.index = rootNode.begainIndex + rootNode.maxIndex;
|
||||
}
|
||||
node.behaviorTree = this;
|
||||
return node;
|
||||
}
|
||||
|
||||
// Lifecycle
|
||||
public void OnEnable()
|
||||
{
|
||||
hideFlags = HideFlags.HideAndDontSave;
|
||||
}
|
||||
|
||||
public void OnDestroy()
|
||||
{
|
||||
foreach (Node node in nodes) {
|
||||
DestroyImmediate(node);
|
||||
}
|
||||
nodeIndex = 0;
|
||||
}
|
||||
|
||||
public Status Tick(GameObject agent, Context context)
|
||||
{
|
||||
BehaviorTreeAgent btAgent = agent.GetComponent<BehaviorTreeAgent>();
|
||||
if (btAgent) {
|
||||
debugMode = btAgent.debugMode;
|
||||
}
|
||||
|
||||
TotalTicks++;
|
||||
|
||||
Status result = rootNode.Tick(agent, context);
|
||||
rootNode.lastStatus = result;
|
||||
rootNode.lastTick = TotalTicks;
|
||||
return result;
|
||||
}
|
||||
|
||||
public Status Tick(Node node, GameObject agent, Context context)
|
||||
{
|
||||
|
||||
if (nodeWillTick != null && node != currentNode)
|
||||
nodeWillTick(node);
|
||||
|
||||
Status result = node.Tick(agent, context);
|
||||
|
||||
if (nodeDidTick != null)
|
||||
nodeDidTick(node, result);
|
||||
|
||||
currentNode = node;
|
||||
node.lastStatus = result;
|
||||
node.lastTick = TotalTicks;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d721d4ced48f4544a3f55b4fc2dfd3e
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,38 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace Hivemind {
|
||||
|
||||
[AddComponentMenu("Miscellaneous/Behavior Tree Agent")]
|
||||
public class BehaviorTreeAgent : MonoBehaviour {
|
||||
public BTAsset btAsset;
|
||||
[HideInInspector]
|
||||
public BehaviorTree behaviorTree;
|
||||
public bool debugMode = true;
|
||||
public Context context;
|
||||
|
||||
public void Awake() {
|
||||
behaviorTree = btAsset.Deserialize();
|
||||
context = new Context();
|
||||
}
|
||||
|
||||
public void Start() {
|
||||
if (btAsset == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void Update() {
|
||||
Tick();
|
||||
}
|
||||
|
||||
public void Tick() {
|
||||
if (behaviorTree == null) {
|
||||
throw new MissingReferenceException("Behavior Tree not defined");
|
||||
}
|
||||
|
||||
behaviorTree.Tick (gameObject, context);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b19824139cd641f6b5b5a0fbd948643
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 31d8eb409255c43c09c0ff1a74d1b733, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
237
Assets/CoolapeFrame/3rd/Hivemind/Scripts/Node.cs
Normal file
237
Assets/CoolapeFrame/3rd/Hivemind/Scripts/Node.cs
Normal file
@@ -0,0 +1,237 @@
|
||||
using UnityEngine;
|
||||
using Hivemind;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using Coolape;
|
||||
|
||||
namespace Hivemind
|
||||
{
|
||||
[System.Serializable]
|
||||
public class Node : ScriptableObject, System.IComparable
|
||||
{
|
||||
public string condition = "";
|
||||
public string result1 = "";
|
||||
public string result2 = "";
|
||||
|
||||
// Editor settings
|
||||
[SerializeField]
|
||||
public Vector2 editorPosition;
|
||||
public int id;
|
||||
public int index = 0;
|
||||
public bool canMultTimes = false;
|
||||
public string desc = "";
|
||||
|
||||
// The Behavior Tree this node belongs too
|
||||
public BehaviorTree behaviorTree;
|
||||
|
||||
// Used by the debugger to visually display the last status returned
|
||||
public Status? lastStatus;
|
||||
public int lastTick = 0;
|
||||
|
||||
public Node()
|
||||
{
|
||||
id = GetInstanceID();
|
||||
}
|
||||
|
||||
// 要结束的节点
|
||||
public List<Node> KillNodes = new List<Node>();
|
||||
public List<Node> ParentKillNodes = new List<Node>();
|
||||
|
||||
public virtual void ConnectKillChild(Node child)
|
||||
{
|
||||
if (!KillNodes.Contains(child) && !Children.Contains(child)) {
|
||||
KillNodes.Add(child);
|
||||
child.ParentKillNodes.Add(this);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void DisconnectKillChild(Node child)
|
||||
{
|
||||
if (KillNodes.Contains(child)) {
|
||||
KillNodes.Remove(child);
|
||||
child.ParentKillNodes.Remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Child connections
|
||||
public virtual void ConnectChild(Node child)
|
||||
{
|
||||
if (child == null)
|
||||
return;
|
||||
if (!Children.Contains(child) && !Children.Contains(child)) {
|
||||
Children.Add(child);
|
||||
child.setParent(this);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void DisconnectChild(Node child)
|
||||
{
|
||||
if (Children.Contains(child)) {
|
||||
Children.Remove(child);
|
||||
child.Unparent(this);
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
List<Node> _children = new List<Node>();
|
||||
|
||||
public virtual List<Node> Children { get { return _children; } }
|
||||
|
||||
public virtual int ChildCount { get { return Children.Count; } }
|
||||
|
||||
public virtual bool CanConnectChild { get { return true; } }
|
||||
|
||||
public virtual bool ContainsChild(Node child)
|
||||
{
|
||||
if (child == null)
|
||||
return false;
|
||||
return Children.Contains(child);
|
||||
}
|
||||
|
||||
// IComparable for sorting left-to-right in the visual editor
|
||||
public int CompareTo(object other)
|
||||
{
|
||||
Node otherNode = other as Node;
|
||||
return editorPosition.x < otherNode.editorPosition.x ? -1 : 1;
|
||||
}
|
||||
|
||||
// Parent connections
|
||||
[SerializeField]
|
||||
List<Node> _parents = new List<Node>();
|
||||
|
||||
public virtual List<Node> parents {
|
||||
get { return _parents; }
|
||||
}
|
||||
|
||||
public virtual void setParent(Node parent)
|
||||
{
|
||||
if (!parents.Contains(parent)) {
|
||||
parents.Add(parent);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Unparent()
|
||||
{
|
||||
for (int i = parents.Count - 1; i >= 0; i--) {
|
||||
Unparent(parents [i]);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Unparent(Node parent)
|
||||
{
|
||||
if (parent == null)
|
||||
return;
|
||||
if (!parents.Contains(parent)) {
|
||||
return;
|
||||
}
|
||||
if (parent != null) {
|
||||
parents.Remove(parent);
|
||||
parent.DisconnectChild(this);
|
||||
} else {
|
||||
Debug.LogWarning(string.Format("Attempted unparenting {0} while it has no parent"));
|
||||
}
|
||||
}
|
||||
|
||||
// All connections
|
||||
public virtual void Disconnect()
|
||||
{
|
||||
// Disconnect parent
|
||||
Node parent = null;
|
||||
for (int i = 0; i < parents.Count; i++) {
|
||||
parent = parents [i];
|
||||
if (parent != null) {
|
||||
Unparent(parent);
|
||||
}
|
||||
}
|
||||
parents.Clear();
|
||||
|
||||
// Disconnect children
|
||||
if (ChildCount > 0) {
|
||||
for (int i = ChildCount - 1; i >= 0; i--) {
|
||||
DisconnectChild(Children [i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = KillNodes.Count - 1; i >= 0; i--) {
|
||||
DisconnectKillChild(KillNodes [i]);
|
||||
}
|
||||
Node killNode = null;
|
||||
for (int i = ParentKillNodes.Count - 1; i >= 0; i--) {
|
||||
killNode = ParentKillNodes [i];
|
||||
killNode.DisconnectKillChild(this);
|
||||
if(killNode is NodeBranch) {
|
||||
NodeBranch branch = killNode as NodeBranch;
|
||||
branch.DisconnectKillLeftChild(this);
|
||||
branch.DisconnectKillRightChild(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lifecycle
|
||||
public void OnEnable()
|
||||
{
|
||||
hideFlags = HideFlags.HideAndDontSave;
|
||||
}
|
||||
|
||||
// Runtime
|
||||
public virtual Status Tick(GameObject agent, Context context)
|
||||
{
|
||||
return Status.Error;
|
||||
}
|
||||
|
||||
public virtual void Deserialize(Hashtable map)
|
||||
{
|
||||
float x = float.Parse(map ["editorx"].ToString());
|
||||
float y = float.Parse(map ["editory"].ToString());
|
||||
editorPosition = new Vector2(x, y);
|
||||
id = MapEx.getInt(map, "id");
|
||||
desc = MapEx.getString(map, "desc");
|
||||
index = MapEx.getInt(map, "index");
|
||||
canMultTimes = MapEx.getBool(map, "canMultTimes");
|
||||
}
|
||||
|
||||
public virtual void DeserializeChildren(Hashtable map)
|
||||
{
|
||||
ArrayList list = MapEx.getList(map, "Children");
|
||||
Node node = null;
|
||||
for (int i = 0; i < list.Count; i++) {
|
||||
int id = int.Parse(list [i].ToString());
|
||||
node = behaviorTree.getNodeByID(id);
|
||||
ConnectChild(node);
|
||||
}
|
||||
|
||||
list = MapEx.getList(map, "KillNodes");
|
||||
node = null;
|
||||
for (int i = 0; i < list.Count; i++) {
|
||||
int id = int.Parse(list [i].ToString());
|
||||
node = behaviorTree.getNodeByID(id);
|
||||
ConnectKillChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual Hashtable Serialize()
|
||||
{
|
||||
Hashtable m = new Hashtable();
|
||||
m ["id"] = id;
|
||||
m ["editorx"] = editorPosition.x.ToString();
|
||||
m ["editory"] = editorPosition.y.ToString();
|
||||
ArrayList subNodes = new ArrayList();
|
||||
for (int i = 0; i < ChildCount; i++) {
|
||||
subNodes.Add(Children [i].id);
|
||||
}
|
||||
m ["Children"] = subNodes;
|
||||
|
||||
ArrayList subkillNodes = new ArrayList();
|
||||
for (int i = 0; i < KillNodes.Count; i++) {
|
||||
subkillNodes.Add(KillNodes [i].id);
|
||||
}
|
||||
m ["KillNodes"] = subkillNodes;
|
||||
|
||||
m ["type"] = GetType().ToString();
|
||||
m ["desc"] = desc;
|
||||
m ["index"] = index;
|
||||
m ["canMultTimes"] = canMultTimes;
|
||||
return m;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/CoolapeFrame/3rd/Hivemind/Scripts/Node.cs.meta
Normal file
12
Assets/CoolapeFrame/3rd/Hivemind/Scripts/Node.cs.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 69db96d00ef55433a808d34c3cea48cc
|
||||
timeCreated: 1501502608
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
9
Assets/CoolapeFrame/3rd/Hivemind/Scripts/Nodes.meta
Normal file
9
Assets/CoolapeFrame/3rd/Hivemind/Scripts/Nodes.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e57d8564939ff40cf8909dcc8a9121aa
|
||||
folderAsset: yes
|
||||
timeCreated: 1501226182
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Assets/CoolapeFrame/3rd/Hivemind/Scripts/Nodes/ActionBase.cs
Normal file
27
Assets/CoolapeFrame/3rd/Hivemind/Scripts/Nodes/ActionBase.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Hivemind;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
public abstract class ActionBase
|
||||
{
|
||||
public abstract Hashtable Serialize ();
|
||||
|
||||
public abstract void Deserialize (Hashtable map);
|
||||
|
||||
public static ActionBase newAction (Hashtable map)
|
||||
{
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public abstract void DrawInspector (Node node);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c8d2fae72e25943db8b4cd1c62acb0c3
|
||||
timeCreated: 1501582378
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
77
Assets/CoolapeFrame/3rd/Hivemind/Scripts/Nodes/NodeAction.cs
Normal file
77
Assets/CoolapeFrame/3rd/Hivemind/Scripts/Nodes/NodeAction.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Hivemind;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
using Coolape;
|
||||
using System;
|
||||
|
||||
namespace Hivemind
|
||||
{
|
||||
public class NodeAction : Node
|
||||
{
|
||||
public ActionBase action;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
MonoScript _monoScript;
|
||||
public MonoScript monoScript{
|
||||
get {
|
||||
return _monoScript;
|
||||
}
|
||||
set {
|
||||
if(_monoScript != value && value != null) {
|
||||
Type tp = value.GetClass ();
|
||||
action = Activator.CreateInstance (tp) as ActionBase;
|
||||
}
|
||||
_monoScript = value;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public virtual void OnEnable() {
|
||||
#if UNITY_EDITOR
|
||||
if (monoScript == null) {
|
||||
monoScript = AssetDatabase.LoadAssetAtPath ("Assets/CoolapeFrame/Hivemind/Test/MyAction.cs", typeof(MonoScript)) as MonoScript;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public override Hashtable Serialize ()
|
||||
{
|
||||
Hashtable m = base.Serialize ();
|
||||
if (action != null) {
|
||||
m ["action"] = action.Serialize ();
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
if (monoScript != null) {
|
||||
string actionClass = AssetDatabase.GetAssetPath (monoScript);
|
||||
m ["actionClass"] = actionClass;
|
||||
}
|
||||
#endif
|
||||
return m;
|
||||
}
|
||||
|
||||
public override void Deserialize (Hashtable map)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
base.Deserialize (map);
|
||||
string actionClass = MapEx.getString (map, "actionClass");
|
||||
if (string.IsNullOrEmpty (actionClass)) {
|
||||
monoScript = null;
|
||||
} else {
|
||||
monoScript = AssetDatabase.LoadAssetAtPath (actionClass, typeof(MonoScript)) as MonoScript;
|
||||
if (monoScript != null) {
|
||||
Type tp = monoScript.GetClass ();
|
||||
action = Activator.CreateInstance (tp) as ActionBase;
|
||||
if (action != null) {
|
||||
action.Deserialize (MapEx.getMap (map, "action"));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 456f96f74bcae48cf8a2d9317b960e9f
|
||||
timeCreated: 1501551538
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
203
Assets/CoolapeFrame/3rd/Hivemind/Scripts/Nodes/NodeBranch.cs
Normal file
203
Assets/CoolapeFrame/3rd/Hivemind/Scripts/Nodes/NodeBranch.cs
Normal file
@@ -0,0 +1,203 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Hivemind;
|
||||
using Coolape;
|
||||
|
||||
namespace Hivemind
|
||||
{
|
||||
public class NodeBranch : NodeAction
|
||||
{
|
||||
|
||||
// 要结束的节点
|
||||
public List<Node> KillLeftNodes = new List<Node>();
|
||||
public List<Node> KillRightNodes = new List<Node>();
|
||||
|
||||
public virtual void ConnectKillLeftChild(Node child)
|
||||
{
|
||||
if (!KillLeftNodes.Contains(child) && !ChildrenLeft.Contains(child)) {
|
||||
KillLeftNodes.Add(child);
|
||||
child.ParentKillNodes.Add(this);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void DisconnectKillLeftChild(Node child)
|
||||
{
|
||||
if (KillLeftNodes.Contains(child)) {
|
||||
KillLeftNodes.Remove(child);
|
||||
child.ParentKillNodes.Remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ConnectKillRightChild(Node child)
|
||||
{
|
||||
if (!KillRightNodes.Contains(child) && !ChildrenRight.Contains(child)) {
|
||||
KillRightNodes.Add(child);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void DisconnectKillRightChild(Node child)
|
||||
{
|
||||
if (KillRightNodes.Contains(child)) {
|
||||
KillRightNodes.Remove(child);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[SerializeField]
|
||||
public List<Node> _childrenLeft = new List<Node>();
|
||||
[SerializeField]
|
||||
public List<Node> _childrenRight = new List<Node>();
|
||||
|
||||
public virtual List<Node> ChildrenLeft { get { return _childrenLeft; } }
|
||||
|
||||
public virtual List<Node> ChildrenRight { get { return _childrenRight; } }
|
||||
|
||||
public virtual bool inLeft(Node node)
|
||||
{
|
||||
if (node == null)
|
||||
return false;
|
||||
return ChildrenLeft.Contains(node);
|
||||
}
|
||||
|
||||
public virtual bool inRight(Node node)
|
||||
{
|
||||
if (node == null)
|
||||
return false;
|
||||
return ChildrenRight.Contains(node);
|
||||
}
|
||||
|
||||
public virtual void ConnectLeftChild(Node child)
|
||||
{
|
||||
if (child == null)
|
||||
return;
|
||||
if (!ChildrenLeft.Contains(child) && !KillLeftNodes.Contains(child)) {
|
||||
ChildrenLeft.Add(child);
|
||||
child.setParent(this);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ConnectRightChild(Node child)
|
||||
{
|
||||
if (child == null)
|
||||
return;
|
||||
if (!ChildrenRight.Contains(child) && !KillRightNodes.Contains(child)) {
|
||||
ChildrenRight.Add(child);
|
||||
child.setParent (this);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void DisconnectLeftChild(Node child)
|
||||
{
|
||||
if (child == null)
|
||||
return;
|
||||
if (ChildrenLeft.Contains(child)) {
|
||||
ChildrenLeft.Remove(child);
|
||||
child.Unparent(this);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void DisconnectRightChild(Node child)
|
||||
{
|
||||
if (child == null)
|
||||
return;
|
||||
if (ChildrenRight.Contains(child)) {
|
||||
ChildrenRight.Remove(child);
|
||||
child.Unparent(this);
|
||||
}
|
||||
}
|
||||
|
||||
public override void DisconnectChild(Node child)
|
||||
{
|
||||
if (child == null)
|
||||
return;
|
||||
base.DisconnectChild(child);
|
||||
DisconnectLeftChild(child);
|
||||
DisconnectRightChild(child);
|
||||
}
|
||||
|
||||
public override void Disconnect()
|
||||
{
|
||||
base.Disconnect();
|
||||
|
||||
// Disconnect children
|
||||
for (int i = ChildrenLeft.Count - 1; i >= 0; i--) {
|
||||
DisconnectLeftChild(ChildrenLeft [i]);
|
||||
}
|
||||
for (int i = ChildrenRight.Count - 1; i >= 0; i--) {
|
||||
DisconnectRightChild(ChildrenRight [i]);
|
||||
}
|
||||
|
||||
for (int i = KillLeftNodes.Count - 1; i >= 0; i--) {
|
||||
DisconnectKillLeftChild(KillLeftNodes [i]);
|
||||
}
|
||||
for (int i = KillRightNodes.Count - 1; i >= 0; i--) {
|
||||
DisconnectKillRightChild(KillRightNodes [i]);
|
||||
}
|
||||
}
|
||||
|
||||
public override Hashtable Serialize()
|
||||
{
|
||||
Hashtable map = base.Serialize();
|
||||
ArrayList lefts = new ArrayList();
|
||||
for (int i = 0; i < ChildrenLeft.Count; i++) {
|
||||
lefts.Add(ChildrenLeft [i].id);
|
||||
}
|
||||
map ["ChildrenLeft"] = lefts;
|
||||
|
||||
ArrayList rights = new ArrayList();
|
||||
for (int i = 0; i < ChildrenRight.Count; i++) {
|
||||
rights.Add(ChildrenRight [i].id);
|
||||
}
|
||||
map ["ChildrenRight"] = rights;
|
||||
|
||||
ArrayList killlefts = new ArrayList();
|
||||
for (int i = 0; i < KillLeftNodes.Count; i++) {
|
||||
killlefts.Add(KillLeftNodes [i].id);
|
||||
}
|
||||
map ["KillLeftNodes"] = killlefts;
|
||||
|
||||
ArrayList killrights = new ArrayList();
|
||||
for (int i = 0; i < KillRightNodes.Count; i++) {
|
||||
if (KillRightNodes [i] == null)
|
||||
continue;
|
||||
killrights.Add(KillRightNodes [i].id);
|
||||
}
|
||||
map ["KillRightNodes"] = killrights;
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
public override void DeserializeChildren(Hashtable map)
|
||||
{
|
||||
ArrayList children = MapEx.getList(map, "ChildrenLeft");
|
||||
Node node = null;
|
||||
for (int i = 0; i < children.Count; i++) {
|
||||
int id = int.Parse(children [i].ToString());
|
||||
node = behaviorTree.getNodeByID(id);
|
||||
ConnectLeftChild(node);
|
||||
}
|
||||
|
||||
children = MapEx.getList(map, "ChildrenRight");
|
||||
for (int i = 0; i < children.Count; i++) {
|
||||
int id = int.Parse(children [i].ToString());
|
||||
node = behaviorTree.getNodeByID(id);
|
||||
ConnectRightChild(node);
|
||||
}
|
||||
|
||||
children = MapEx.getList(map, "KillLeftNodes");
|
||||
for (int i = 0; i < children.Count; i++) {
|
||||
int id = int.Parse(children [i].ToString());
|
||||
node = behaviorTree.getNodeByID(id);
|
||||
ConnectKillLeftChild(node);
|
||||
}
|
||||
|
||||
children = MapEx.getList(map, "KillRightNodes");
|
||||
for (int i = 0; i < children.Count; i++) {
|
||||
int id = int.Parse(children [i].ToString());
|
||||
node = behaviorTree.getNodeByID(id);
|
||||
ConnectKillRightChild(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8296fe6385d2a4398a4edc55236087ed
|
||||
timeCreated: 1501552530
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,12 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Hivemind;
|
||||
using Coolape;
|
||||
|
||||
namespace Hivemind
|
||||
{
|
||||
public class NodeTogether : NodeAction
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0cb0498c85a854d1f92a5b6602aad53e
|
||||
timeCreated: 1502099325
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
146
Assets/CoolapeFrame/3rd/Hivemind/Scripts/Nodes/Root.cs
Normal file
146
Assets/CoolapeFrame/3rd/Hivemind/Scripts/Nodes/Root.cs
Normal file
@@ -0,0 +1,146 @@
|
||||
|
||||
// Root ------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
using Hivemind;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using Coolape;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
using System;
|
||||
|
||||
namespace Hivemind
|
||||
{
|
||||
[System.Serializable]
|
||||
public class Root : Node
|
||||
{
|
||||
public int begainIndex = 0;
|
||||
public int maxIndex = 0;
|
||||
|
||||
public ActionBase attr;
|
||||
#if UNITY_EDITOR
|
||||
MonoScript _monoScript;
|
||||
public MonoScript monoScript{
|
||||
get {
|
||||
return _monoScript;
|
||||
}
|
||||
set {
|
||||
if(_monoScript != value && value != null) {
|
||||
Type tp = value.GetClass ();
|
||||
attr = Activator.CreateInstance (tp) as ActionBase;
|
||||
}
|
||||
_monoScript = value;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public virtual void OnEnable() {
|
||||
#if UNITY_EDITOR
|
||||
if (monoScript == null) {
|
||||
monoScript = AssetDatabase.LoadAssetAtPath ("Assets/CoolapeFrame/Hivemind/Test/MyRoot.cs", typeof(MonoScript)) as MonoScript;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Child connections
|
||||
[SerializeField]
|
||||
Node _child;
|
||||
|
||||
public override void ConnectChild (Node child)
|
||||
{
|
||||
if (_child == null) {
|
||||
_child = child;
|
||||
child.setParent(this);
|
||||
} else {
|
||||
throw new System.InvalidOperationException (string.Format ("{0} already has a connected child, cannot connect {1}", this, child));
|
||||
}
|
||||
}
|
||||
|
||||
public override void DisconnectChild (Node child)
|
||||
{
|
||||
if (_child == child) {
|
||||
_child = null;
|
||||
child.Unparent(this);
|
||||
} else {
|
||||
throw new System.InvalidOperationException (string.Format ("{0} is not a child of {1}", child, this));
|
||||
}
|
||||
}
|
||||
|
||||
public override List<Node> Children {
|
||||
get {
|
||||
List<Node> nodeList = new List<Node> ();
|
||||
nodeList.Add (_child);
|
||||
return nodeList;
|
||||
}
|
||||
}
|
||||
|
||||
public override int ChildCount {
|
||||
get { return _child != null ? 1 : 0; }
|
||||
}
|
||||
|
||||
public override bool CanConnectChild {
|
||||
get { return _child == null; }
|
||||
}
|
||||
|
||||
public override bool ContainsChild (Node child)
|
||||
{
|
||||
return _child == child;
|
||||
}
|
||||
|
||||
public override Hashtable Serialize ()
|
||||
{
|
||||
Hashtable map = base.Serialize ();
|
||||
#if UNITY_EDITOR
|
||||
map ["begainIndex"] = begainIndex;
|
||||
map ["maxIndex"] = maxIndex;
|
||||
|
||||
if (attr != null) {
|
||||
map ["attr"] = attr.Serialize ();
|
||||
}
|
||||
|
||||
if (monoScript != null) {
|
||||
string actionClass = AssetDatabase.GetAssetPath (monoScript);
|
||||
map ["actionClass"] = actionClass;
|
||||
}
|
||||
|
||||
#endif
|
||||
return map;
|
||||
}
|
||||
|
||||
public override void Deserialize (Hashtable map)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
base.Deserialize (map);
|
||||
begainIndex = MapEx.getInt (map, "begainIndex");
|
||||
maxIndex = MapEx.getInt (map, "maxIndex");
|
||||
|
||||
string actionClass = MapEx.getString (map, "actionClass");
|
||||
if (string.IsNullOrEmpty (actionClass)) {
|
||||
monoScript = null;
|
||||
} else {
|
||||
monoScript = AssetDatabase.LoadAssetAtPath (actionClass, typeof(MonoScript)) as MonoScript;
|
||||
if (monoScript != null) {
|
||||
Type tp = monoScript.GetClass ();
|
||||
attr = Activator.CreateInstance (tp) as ActionBase;
|
||||
if (attr != null) {
|
||||
attr.Deserialize (MapEx.getMap (map, "attr"));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Runtime
|
||||
|
||||
public override Status Tick (GameObject agent, Context context)
|
||||
{
|
||||
Status result = Status.Error;
|
||||
if (_child != null) {
|
||||
result = behaviorTree.Tick (_child, agent, context);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/CoolapeFrame/3rd/Hivemind/Scripts/Nodes/Root.cs.meta
Normal file
12
Assets/CoolapeFrame/3rd/Hivemind/Scripts/Nodes/Root.cs.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f48fda5512bad4dc3835524f7ed477ba
|
||||
timeCreated: 1501502853
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user