This commit is contained in:
2020-07-04 14:41:25 +08:00
parent 70c346d2c1
commit a8f02e4da5
3748 changed files with 587372 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 916848dfe36f8470da9b0346a7d178f4
folderAsset: yes
timeCreated: 1501226182
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 73525b0fba0614973bb8c2d52480c0a0
folderAsset: yes
timeCreated: 1501226182
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,6 @@
fileFormatVersion: 2
guid: cac08ba45fa2741ac964cc42d466ff1f
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,70 @@
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
namespace Hivemind {
[CustomEditor(typeof(BehaviorTreeAgent))]
public class BTAgentInspector : Editor {
private BTEditorManager _manager;
public void OnEnable() {
BehaviorTreeAgent btAgent = target as BehaviorTreeAgent;
BehaviorTree bt = null;
if (btAgent.behaviorTree == null) {
btAgent.Awake();
}
bt = btAgent.behaviorTree;
if (bt != null) {
_manager = BTEditorManager.Manager;
if (!_manager) {
_manager = BTEditorManager.CreateInstance(bt, btAgent.btAsset);
} else {
_manager.behaviorTree = bt;
}
_manager.btInspector = this;
_manager.inspectedAgent = btAgent;
}
}
public void OnDisable() {
if (!EditorApplication.isPlaying && _manager != null) {
DestroyImmediate (_manager);
} else if (_manager != null) {
_manager.behaviorTree = null;
}
}
public override void OnInspectorGUI() {
DrawDefaultInspector();
if (_manager.selectedNode != null) {
EditorGUILayout.LabelField("Last Status: " + _manager.selectedNode.lastStatus.ToString());
}
BehaviorTreeAgent btAgent = target as BehaviorTreeAgent;
if (btAgent.context != null) {
EditorGUILayout.LabelField("Current Context");
foreach (KeyValuePair<string, object> item in btAgent.context.All) {
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(item.Key);
EditorGUILayout.LabelField(item.Value.ToString ());
EditorGUILayout.EndHorizontal();
}
}
if (GUILayout.Button ("Show Behavior Tree editor")) {
BTEditorWindow.ShowWindow ();
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 718ad4335bf544699b489e985a0e8d59
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,293 @@
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.IO;
using Coolape;
namespace Hivemind
{
/*
* This manager is created by the BTInspector, the custom inspector for BehaviorTree assets.
* Every time the inspector receives the OnEnable message, a fresh manager is created, and
* destroyed when the inspector receives the OnDisable message.
*
* Its main responsibility is to serve as the sole route for BehaviorTree manipulation.
*
* It achieves that by exposing a selected BehaviorTree (determined by the current BehaviorTree
* being inspected in BTInspector) to the BTEditorWindow
*
* BTEditorWindow manages its own sub systems to provide editing functionality, and forwards
* all actual manipulations to this manager.
*
* Creation of new BehaviorTrees are also handled here.
*/
public class BTEditorManager : ScriptableObject
{
public Editor btInspector;
public Editor nodeInspector;
public BehaviorTreeAgent inspectedAgent;
public BTEditorWindow editorWindow;
public Node selectedNode;
public BehaviorTree _behaviorTree;
public BehaviorTree behaviorTree {
get { return _behaviorTree; }
set {
_behaviorTree = value;
if (_behaviorTree != null) {
_behaviorTree.nodeWillTick = OnNodeWillTick;
_behaviorTree.nodeDidTick = OnNodeDidTick;
}
}
}
public BTAsset btAsset;
public void OnNodeWillTick (Node node)
{
if (inspectedAgent.debugMode) {
Debug.Log (node.GetType ().Name);
}
}
public void OnNodeDidTick (Node node, Status result)
{
if (editorWindow != null)
editorWindow.Repaint ();
}
public static BTEditorManager Manager { get; private set; }
public static BTEditorManager CreateInstance (BehaviorTree bt, BTAsset asset)
{
if (Manager == null) {
Manager = (BTEditorManager)ScriptableObject.CreateInstance (typeof(BTEditorManager));
Manager.behaviorTree = bt;
Manager.btAsset = asset;
}
return Manager;
}
// Lifecycle
public void OnEnable ()
{
hideFlags = HideFlags.HideAndDontSave;
}
public void OnDestroy ()
{
Manager = null;
DestroyImmediate (behaviorTree);
}
// Asset management ------------------------------------------------------------------------------------------------------------------------------------
[MenuItem ("Coolape/New Behavior Tree", false, 3)]
static void CreateNewBehaviorTree (MenuCommand menuCommand)
{
// string path = AssetDatabase.GetAssetPath(Selection.activeObject);
// if (path == "")
// path = "Assets";
// else if (Path.GetExtension(path) != "")
// path = path.Replace(Path.GetFileName(AssetDatabase.GetAssetPath(Selection.activeObject)), "");
string basePath = PStr.b ().a ("Assets/").a (CLPathCfg.self.basePath).a ("/xRes/carbonEvent/").e ();
string fullPath = EditorUtility.SaveFilePanel ("Save Carbon Event", basePath, "New Behavior Tree", "asset");
if (string.IsNullOrEmpty (fullPath)) {
return;
}
// fullPath = AssetDatabase.GenerateUniqueAssetPath (fullPath);
fullPath = fullPath.Substring(fullPath.IndexOf("/Assets/") + 1);
BehaviorTree bt = ScriptableObject.CreateInstance<BehaviorTree> ();
Root root = ScriptableObject.CreateInstance<Root> ();
root.editorPosition = new Vector2 (0, 0);
bt.SetRoot (root);
BTAsset btAsset = ScriptableObject.CreateInstance<BTAsset> ();
btAsset.Serialize (bt);
AssetDatabase.CreateAsset (btAsset, fullPath);
AssetDatabase.Refresh ();
EditorUtility.FocusProjectWindow ();
Selection.activeObject = btAsset;
}
public void Dirty ()
{
if (editorWindow != null)
editorWindow.Repaint ();
btAsset.Serialize (behaviorTree);
EditorUtility.SetDirty (btAsset);
}
// Behavior Tree manipulation --------------------------------------------------------------------------------------------------------------------------
public void Add (Node parent, Vector2 position, string nodeType)
{
Node node = null;
switch (nodeType) {
case "Action":
node = behaviorTree.CreateNode<NodeAction> ();
break;
case "Branch":
node = behaviorTree.CreateNode<NodeBranch> ();
break;
case "Together":
node = behaviorTree.CreateNode<NodeTogether> ();
break;
// case "Inverter":
// node = behaviorTree.CreateNode<Inverter>();
// break;
// case "Parallel":
// node = behaviorTree.CreateNode<Parallel>();
// break;
// case "RandomSelector":
// node = behaviorTree.CreateNode<RandomSelector>();
// break;
// case "Repeater":
// node = behaviorTree.CreateNode<Repeater>();
// break;
// case "Selector":
// node = behaviorTree.CreateNode<Selector>();
// break;
// case "Sequence":
// node = behaviorTree.CreateNode<Sequence>();
// break;
// case "Succeeder":
// node = behaviorTree.CreateNode<Succeeder>();
// break;
// case "UntilSucceed":
// node = behaviorTree.CreateNode<UntilSucceed>();
// break;
}
behaviorTree.nodes.Add (node);
if (parent != null && parent.CanConnectChild) {
if (parent.ChildCount > 0) {
Node lastSibling = parent.Children [parent.ChildCount - 1];
node.editorPosition = lastSibling.editorPosition + new Vector2 (GridRenderer.step.x * 10, 0);
} else {
node.editorPosition = new Vector2 (parent.editorPosition.x, parent.editorPosition.y + GridRenderer.step.y * 10);
}
parent.ConnectChild (node);
// SortChildren(parent);
} else {
float xOffset = position.x % GridRenderer.step.x;
float yOffset = position.y % GridRenderer.step.y;
float xoffset1 = editorWindow.view.scrollPoint.x;
float yoffset1 = editorWindow.view.scrollPoint.y;
node.editorPosition = new Vector2 (position.x - xOffset +xoffset1, position.y - yOffset+yoffset1);
}
Dirty ();
// Select the newly added node
if (editorWindow != null)
editorWindow.view.SelectNode (node);
}
public void Connect (Node parent, Node child)
{
if (parent == child)
return;
if (parent.CanConnectChild) {
parent.ConnectChild (child);
// SortChildren(parent);
Dirty ();
} else {
Debug.LogWarning (string.Format ("{0} can't accept child {1}", parent, child));
}
}
public void ConnectKill (Node parent, Node child)
{
if (parent == child)
return;
parent.ConnectKillChild (child);
Dirty ();
}
public void ConnectLeft (NodeBranch parent, Node child)
{
if (parent == child)
return;
if (parent.CanConnectChild) {
parent.ConnectLeftChild (child);
// SortChildren(parent);
Dirty ();
} else {
Debug.LogWarning (string.Format ("{0} can't accept child {1}", parent, child));
}
}
public void ConnectLeftKill (NodeBranch parent, Node child)
{
if (parent == child)
return;
parent.ConnectKillLeftChild (child);
Dirty ();
}
public void ConnectRight (NodeBranch parent, Node child)
{
if (parent == child)
return;
if (parent.CanConnectChild) {
parent.ConnectRightChild (child);
// SortChildren(parent);
Dirty ();
} else {
Debug.LogWarning (string.Format ("{0} can't accept child {1}", parent, child));
}
}
public void ConnectRightKill (NodeBranch parent, Node child)
{
if (parent == child)
return;
parent.ConnectKillRightChild (child);
Dirty ();
}
public void Unparent (Node node)
{
node.Unparent ();
Dirty ();
}
public void DisconnectAll (Node node)
{
node.Disconnect ();
Dirty ();
}
public void Delete (Node node)
{
node.Disconnect ();
behaviorTree.nodes.Remove (node);
DestroyImmediate (node, true);
Dirty ();
}
public void SetEditorPosition (Node node, Vector2 position)
{
node.editorPosition = position;
// SortChildren(node.parent);
Dirty ();
}
// private void SortChildren(Node parent) {
// Composite parentComposite = parent as Composite;
// if (parentComposite != null)
// parentComposite.SortChildren();
// }
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 73316990941e844698e84ea9cb88a931
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,513 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.Collections;
using Coolape;
using System.Reflection;
using System;
using System.Linq;
namespace Hivemind
{
public class MenuAction
{
public string nodeType;
public Vector2 position;
public Node node;
public MenuAction (Node nodeVal)
{
node = nodeVal;
}
public MenuAction (Node nodeVal, Vector2 positionVal, string nodeTypeVal)
{
node = nodeVal;
position = positionVal;
nodeType = nodeTypeVal;
}
}
public class BTEditorWindow : EditorWindow
{
public View view;
private GUIStyle _noSelectionStyle;
private bool _debugMode;
[MenuItem ("Window/Behavior Tree Editor")]
public static void ShowWindow ()
{
BTEditorWindow editor = EditorWindow.GetWindow<BTEditorWindow> ();
editor.minSize = new Vector2 (480, 360);
editor.title = "Behavior Tree";
}
void OnSelectionChange ()
{
Repaint ();
}
void OnEnable ()
{
_noSelectionStyle = new GUIStyle ();
_noSelectionStyle.fontSize = 24;
_noSelectionStyle.alignment = TextAnchor.MiddleCenter;
if (BTEditorManager.Manager != null)
BTEditorManager.Manager.editorWindow = this;
}
void OnDisable ()
{
if (BTEditorManager.Manager)
BTEditorManager.Manager.editorWindow = null;
}
void OnDestroy ()
{
if (BTEditorManager.Manager)
BTEditorManager.Manager.editorWindow = null;
}
void OnGUI ()
{
if (BTEditorManager.Manager != null && BTEditorManager.Manager.behaviorTree != null) {
BTEditorManager.Manager.editorWindow = this;
if (view == null)
view = new View (this);
if (view.nodeInspector != null)
view.nodeInspector.OnInspectorGUI ();
bool viewNeedsRepaint = view.Draw (position);
if (viewNeedsRepaint)
Repaint ();
view.ResizeCanvas ();
} else {
GUI.Label (new Rect (0, 0, position.width, position.height), "No Behavior Tree selected", _noSelectionStyle);
}
}
public void ShowContextMenu (Vector2 point, Node node)
{
// if (Application.isPlaying) {
// return;
// }
var menu = new GenericMenu ();
if (node == null || node.CanConnectChild) {
// Add new node
string addMsg = (node == null ? "Add" : "Add Child") + "/";
// List all available node subclasses
int length = BehaviorTree.NodeTypes.Length;
for (int i = 0; i < length; i++) {
menu.AddItem (
new GUIContent (addMsg + BehaviorTree.NodeTypes [i]),
false,
Add,
new MenuAction (node, point, BehaviorTree.NodeTypes [i])
);
}
} else {
menu.AddDisabledItem (new GUIContent ("Add"));
}
int menuType = 0;
int selectedNodesCount = view.selectedNodes.Count;
if (selectedNodesCount == 0) {
menuType = 0;
} else if (selectedNodesCount == 1) {
menuType = 0;
} else if (selectedNodesCount == 2) {
menuType = 2;
} else {
menuType = 3;
}
if (menuType == 2) {
menu.AddItem (new GUIContent ("Disconnect From Selected Nodes"), false, DisconnectSelectedNodes, new MenuAction (node));
menu.AddSeparator ("");
menu.AddItem (new GUIContent ("Delete Selected Nodes"), false, DeleteSelectNodes, new MenuAction (node));
} else if (menuType == 3) {
//empty
menu.AddItem (new GUIContent ("Delete Selected Nodes"), false, DeleteSelectNodes, new MenuAction (node));
} else {
if (node == null) {
menu.AddSeparator ("");
menu.AddItem (new GUIContent ("Save"), false, Save, null);
menu.AddItem (new GUIContent ("Refresh Nodes Index"), false, RefreshNodesIndex, null);
menu.AddItem (new GUIContent ("Genrate Node State"), false, GenerateNodeState, null);
menu.AddItem (new GUIContent ("Export Data"), false, exportData, null);
}
menu.AddSeparator ("");
// Node actions
if (node != null) {
// Connect/Disconnect Parent
if (!(node is Root)) {
menu.AddItem (new GUIContent ("Disconnect from All Parent"), false, Unparent, new MenuAction (node));
menu.AddItem (new GUIContent ("Disconnect All"), false, DisconnectAll, new MenuAction (node));
menu.AddItem (new GUIContent ("Connect to Parent"), false, ConnectParent, new MenuAction (node));
}
menu.AddSeparator ("");
// Connect Child
if (node.CanConnectChild) {
if (node is NodeBranch) {
menu.AddItem (new GUIContent ("Connect to Left Child"), false, ConnectLeftChild, new MenuAction (node));
menu.AddItem (new GUIContent ("Connect to Left Kill Child"), false, ConnectLeftKillChild, new MenuAction (node));
menu.AddItem (new GUIContent ("Connect to Right Child"), false, ConnectRightChild, new MenuAction (node));
menu.AddItem (new GUIContent ("Connect to Right Kill Child"), false, ConnectRightKillChild, new MenuAction (node));
} else {
menu.AddItem (new GUIContent ("Connect to Child"), false, ConnectChild, new MenuAction (node));
menu.AddItem (new GUIContent ("Connect to Kill Child"), false, ConnectKillChild, new MenuAction (node));
}
} else {
menu.AddDisabledItem (new GUIContent ("Connect to Child"));
}
menu.AddSeparator ("");
// Deleting
if (node is Root)
menu.AddDisabledItem (new GUIContent ("Delete"));
else
menu.AddItem (new GUIContent ("Delete"), false, Delete, new MenuAction (node));
}
}
menu.DropDown (new Rect (point.x, point.y, 0, 0));
}
// Context Menu actions
public void Add (object userData)
{
MenuAction menuAction = userData as MenuAction;
BTEditorManager.Manager.Add (menuAction.node, menuAction.position, menuAction.nodeType);
view.ResizeCanvas ();
Repaint ();
}
public void Unparent (object userData)
{
MenuAction menuAction = userData as MenuAction;
BTEditorManager.Manager.Unparent (menuAction.node);
Repaint ();
}
public void DisconnectAll (object userData)
{
MenuAction menuAction = userData as MenuAction;
BTEditorManager.Manager.DisconnectAll (menuAction.node);
Repaint ();
}
public void ConnectParent (object userData)
{
MenuAction menuAction = userData as MenuAction;
view.ConnectParent (menuAction.node);
}
public void ConnectChild (object userData)
{
MenuAction menuAction = userData as MenuAction;
view.ConnectChild (menuAction.node);
}
public void ConnectKillChild (object userData)
{
MenuAction menuAction = userData as MenuAction;
view.ConnectKillChild (menuAction.node);
}
public void ConnectLeftChild (object userData)
{
MenuAction menuAction = userData as MenuAction;
view.ConnectLeftChild (menuAction.node);
}
public void ConnectLeftKillChild (object userData)
{
MenuAction menuAction = userData as MenuAction;
view.ConnectLeftKillChild (menuAction.node);
}
public void ConnectRightChild (object userData)
{
MenuAction menuAction = userData as MenuAction;
view.ConnectRightChild (menuAction.node);
}
public void ConnectRightKillChild (object userData)
{
MenuAction menuAction = userData as MenuAction;
view.ConnectRightKillChild (menuAction.node);
}
public void Delete (object userData)
{
MenuAction menuAction = userData as MenuAction;
BTEditorManager.Manager.Delete (menuAction.node);
Repaint ();
}
public void Save (object userData)
{
if (BTEditorManager.Manager != null
&& BTEditorManager.Manager.btAsset != null
&& BTEditorManager.Manager.behaviorTree != null) {
BTEditorManager.Manager.btAsset.Serialize (BTEditorManager.Manager.behaviorTree);
EditorUtility.SetDirty (BTEditorManager.Manager.btAsset);
}
AssetDatabase.Refresh ();
AssetDatabase.SaveAssets ();
Debug.Log ("Save");
}
public void DisconnectSelectedNodes (object userData)
{
if (view.selectedNodes.Count != 2)
return;
Node node1 = view.selectedNodes [0];
Node node2 = view.selectedNodes [1];
node1.DisconnectChild (node2);
node1.DisconnectKillChild (node2);
node1.Unparent (node2);
node2.DisconnectChild (node1);
node2.DisconnectKillChild (node1);
node2.Unparent (node1);
if (node1 is NodeBranch) {
((NodeBranch)node1).DisconnectLeftChild (node2);
((NodeBranch)node1).DisconnectRightChild (node2);
((NodeBranch)node1).DisconnectKillLeftChild (node2);
((NodeBranch)node1).DisconnectKillRightChild (node2);
}
if (node2 is NodeBranch) {
((NodeBranch)node2).DisconnectLeftChild (node1);
((NodeBranch)node2).DisconnectRightChild (node1);
((NodeBranch)node2).DisconnectKillLeftChild (node1);
((NodeBranch)node2).DisconnectKillRightChild (node1);
}
Repaint ();
// Save (userData);
}
public void DeleteSelectNodes (object userData)
{
for (int i = view.selectedNodes.Count - 1; i >= 0; i--) {
BTEditorManager.Manager.Delete (view.selectedNodes [i]);
}
view.selectedNodes.Clear ();
Repaint ();
// Save (userData);
}
public void RefreshNodesIndex (object userData)
{
Root node = BTEditorManager.Manager.behaviorTree.rootNode;
node.index = 0;
node.maxIndex = 0;
foreach (Node n in node.behaviorTree.nodes) {
if (n != node) {
node.maxIndex++;
n.index = node.begainIndex + node.maxIndex;
}
}
// Save (userData);
}
public void GenerateNodeState (object userData)
{
List<Node> nodes = BTEditorManager.Manager.behaviorTree.nodes;
Hashtable procedMap = new Hashtable ();
for (int i = 0; i < nodes.Count; i++) {
doGenerateNodeState (nodes [i], ref procedMap);
}
}
public void doGenerateNodeState (Node node, ref Hashtable map)
{
if (MapEx.getBool (map, node) || node == node.behaviorTree.rootNode) {
return;
}
map [node] = true;
int mainType = 14;
string pubStr = "";
if (node.behaviorTree.rootNode.attr != null) {
pubStr = mainType + "/" + ((MyRoot)(node.behaviorTree.rootNode.attr)).fubenID + "/";
} else {
pubStr = mainType + "/" + 0 + "/";
}
//Condition
if (node.parents != null && node.parents.Count > 0) {
node.condition = "{";
if ((node.parents.Count == 1 && (node.parents [0]) is Root)) {
node.condition += "{\"" + pubStr + node.index + "/" + 0 + "\"}";
} else if (node.parents.Contains (node.behaviorTree.rootNode)) {
node.condition += "{\"" + pubStr + node.index + "/" + 0 + "\",\"" + pubStr + node.index + "/" + 1 + "\"}";
} else {
node.condition += "{\"" + pubStr + node.index + "/" + 1 + "\"}";
}
if (node is NodeTogether) {
Node parent = null;
for (int i = 0; i < node.parents.Count; i++) {
parent = node.parents [i];
if (parent is Root) {
} else if (parent is NodeBranch) {
if (((NodeBranch)parent).inLeft (node)) {
node.condition += ",{\"" + pubStr + (-node.parents [i].index) + "/" + 1 + "\"}";
}
if (((NodeBranch)parent).inRight (node)) {
node.condition += ",{\"" + pubStr + (-node.parents [i].index) + "/" + 2 + "\"}";
}
} else {
node.condition += ",{\"" + pubStr + (-node.parents [i].index) + "/" + 1 + "\"}";
}
}
}
node.condition += "}";
} else {
node.condition = "{{\"" + pubStr + node.index + "/" + 0 + "\"}}";
}
//result
if (node is NodeBranch) {
NodeBranch branch = node as NodeBranch;
node.result1 = getResultWithSubNodes (branch, branch.ChildrenLeft, branch.KillLeftNodes);
node.result2 = getResultWithSubNodes (branch, branch.ChildrenRight, branch.KillRightNodes);
} else {
node.result1 = getResultWithSubNodes (node, node.Children, node.KillNodes);
node.result2 = node.result1;
}
}
public string getNodeResult (Node node, Node child)
{
string ret = "";
if (node is NodeBranch) {
if (((NodeBranch)node).inLeft (child)) {
if (child is NodeTogether) {
ret = -node.index + "/" + 1;
} else {
ret = child.index + "/" + 1;
}
}
if (((NodeBranch)node).inRight (child)) {
if (child is NodeTogether) {
ret = -node.index + "/" + 2;
} else {
ret = child.index + "/" + 1;
}
}
} else {
if (child is NodeTogether) {
ret = -node.index + "/" + 1;
} else {
ret = child.index + "/" + 1;
}
}
return ret;
}
public string getResultWithSubNodes (Node node, List<Node>children, List<Node>killChildren)
{
int mainType = 14;
string pubStr = "";
if (node.behaviorTree.rootNode.attr != null) {
pubStr = mainType + "/" + ((MyRoot)(node.behaviorTree.rootNode.attr)).fubenID + "/";
} else {
pubStr = mainType + "/" + 0 + "/";
}
string result = "{";
if (!node.canMultTimes) {
result = result + "\"" + pubStr + node.index + "/" + 9 + "\"";
}
if ((node is NodeAction) && ((((NodeAction)node).action) is MyAction)) {
int triggerType = ((MyAction)(((NodeAction)node).action)).triggerType;
if (node.canMultTimes && triggerType == 1) {
result = result + "\"" + pubStr + node.index + "/" + 9 + "\"";
Debug.LogError ("Node index=["+ node.index +"] have logic error, beacause it can multTimes and it triggered auto");
}
}
Node child = null;
for (int i = 0; i < children.Count; i++) {
child = children [i];
if (result.Length == 1) {
result = result + "\"" + pubStr + children [i].index + "/" + 1 + "\"";
} else {
result = result + ",\"" + pubStr + children [i].index + "/" + 1 + "\"";
}
if (children [i] is NodeTogether) {
result = result + ",\"" + pubStr + getNodeResult (node, children [i]) + "\"";
}
}
for (int i = 0; i < killChildren.Count; i++) {
if (killChildren [i] == null)
continue;
if (result.Length == 1) {
result = result + "\"" + pubStr + killChildren [i].index + "/" + 9 + "\"";
} else {
result = result + ",\"" + pubStr + killChildren [i].index + "/" + 9 + "\"";
}
result = result + ",\"" + pubStr + (-killChildren [i].index) + "/" + 9 + "\"";
}
result = result + "}";
if (result.Equals ("{}")) {
result = "";
}
return result;
}
//会调用加了【ExportHiveData】的函数
public void exportData (object userData)
{
GenerateNodeState (userData);
List<Node> nodes = BTEditorManager.Manager.behaviorTree.nodes;
callCustomExportHiveData (nodes);
EditorUtility.DisplayDialog ("Alert", "Finished!", "Okay");
}
static IEnumerable<MethodInfo> exportHiveDataMethodList = (from type in XLua.Utils.GetAllTypes ()
from method in type.GetMethods (BindingFlags.Static | BindingFlags.Public)
where method.IsDefined (typeof(ExportHiveDataAttribute), false)
select method);
static void callCustomExportHiveData (List<Node> nodes)
{
if (exportHiveDataMethodList.Count<MethodInfo> () == 0) {
Debug.LogError ("There is no customer export data function");
return;
}
foreach (var method in exportHiveDataMethodList) {
method.Invoke (null, new object[] { nodes });
}
}
}
public class ExportHiveDataAttribute : Attribute
{
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 6176253aeb08d47ec96605fb529f2f54
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,301 @@
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
namespace Hivemind
{
public class HivemindInspector : Editor
{
private static GUIStyle _titleStyle;
private static GUIStyle _subtitleStyle;
public static GUIStyle TitleStyle {
get {
if (_titleStyle == null) {
_titleStyle = new GUIStyle ();
_titleStyle.fontSize = 18;
}
return _titleStyle;
}
}
public static GUIStyle SubtitleStyle {
get {
if (_subtitleStyle == null) {
_subtitleStyle = new GUIStyle ();
_subtitleStyle.fontSize = 15;
}
return _subtitleStyle;
}
}
}
[CustomEditor (typeof(BTAsset))]
public class BTInspector : HivemindInspector
{
private BTEditorManager manager;
public void OnEnable ()
{
BTAsset btAsset = (BTAsset)serializedObject.targetObject;
BehaviorTree bt = btAsset.Deserialize ();
manager = BTEditorManager.CreateInstance (bt, btAsset);
manager.btInspector = this;
}
public void OnDisable ()
{
DestroyImmediate (manager);
}
public override void OnInspectorGUI ()
{
if (BTEditorManager.Manager.nodeInspector == null) {
EditorGUILayout.LabelField ("Behavior Tree", TitleStyle);
if (manager.behaviorTree.nodes.Count > 2)
EditorGUILayout.LabelField (string.Format ("{0} nodes", manager.behaviorTree.nodes.Count - 1));
else if (manager.behaviorTree.nodes.Count == 2)
EditorGUILayout.LabelField ("Empty");
else
EditorGUILayout.LabelField ("1 node");
EditorGUILayout.Space ();
if (GUILayout.Button ("Show Behavior Tree editor")) {
BTEditorWindow.ShowWindow ();
}
} else {
manager.nodeInspector.OnInspectorGUI ();
}
if (GUI.changed) {
manager.Dirty ();
}
}
}
[CustomEditor (typeof(Node), true)]
public class BTNodeInspector : HivemindInspector
{
public override void OnInspectorGUI ()
{
Node node = (Node)serializedObject.targetObject;
if (node is Root) {
DrawInspector ((Root)node);
} else if (node is NodeBranch) {
DrawInspector ((NodeBranch)node);
} else if (node is NodeAction) {
DrawInspector ((NodeAction)node);
}
// else if (node is Selector) { DrawInspector ((Selector) node); }
// else if (node is Sequence) { DrawInspector ((Sequence) node); }
// else if (node is Parallel) { DrawInspector ((Parallel) node); }
// else if (node is Repeater) { DrawInspector ((Repeater) node); }
// else if (node is RandomSelector) { DrawInspector ((RandomSelector) node); }
// else if (node is UntilSucceed) { DrawInspector ((UntilSucceed) node); }
// else if (node is Inverter) { DrawInspector ((Inverter) node); }
// else if (node is Succeeder) { DrawInspector ((Succeeder) node); }
if (GUI.changed) {
BTEditorManager.Manager.Dirty ();
}
}
// private int IndexOf (string[] array, string target)
// {
// int length = array.Length;
// for (var i = 0; i < length; i++) {
// if (array [i] == target)
// return i;
// }
// return 0;
// }
public void DrawInspectorBase (Node node)
{
ECLEditorUtl.BeginContents ();
{
EditorGUILayout.LabelField ("State values");
EditorGUILayout.TextField (new GUIContent ("Conditon"), node.condition);
EditorGUILayout.TextField (new GUIContent ("Result1"), node.result1);
EditorGUILayout.TextField (new GUIContent ("Result2"), node.result2);
}
ECLEditorUtl.EndContents ();
}
public void DrawInspector (Root node)
{
EditorGUILayout.LabelField (new GUIContent ("Root"), TitleStyle);
EditorGUILayout.Space ();
node.begainIndex = EditorGUILayout.IntField (new GUIContent ("Begain Index"), node.begainIndex);
node.monoScript = (MonoScript)EditorGUILayout.ObjectField ("Root Script", node.monoScript, typeof(MonoScript), false);
if (node.monoScript != null) {
if (!node.monoScript.GetClass ().IsSubclassOf (typeof(ActionBase))) {
EditorGUILayout.HelpBox (string.Format ("{0} is not a subclass of Hivemind.ActionBase", node.monoScript.GetClass ().ToString ()), MessageType.Warning);
// action.monoScript = null;
} else {
}
}
if (node.attr != null) {
ECLEditorUtl.BeginContents ();
{
EditorGUILayout.LabelField ("Event Content");
node.attr.DrawInspector (node);
}
ECLEditorUtl.EndContents ();
}
EditorGUILayout.Space ();
if (GUILayout.Button ("Refresh Nodes Index")) {
node.index = 0;
node.maxIndex = 0;
foreach (Node n in node.behaviorTree.nodes) {
if (n != node) {
node.maxIndex++;
n.index = node.begainIndex + node.maxIndex;
}
}
}
}
public void DrawInspector (NodeAction node)
{
EditorGUILayout.LabelField (new GUIContent ("Action"), TitleStyle);
EditorGUILayout.Space ();
node.desc = EditorGUILayout.TextField (new GUIContent ("Desc"), node.desc);
node.canMultTimes = EditorGUILayout.Toggle("Run MultTimes", node.canMultTimes);
// MonoScript selection field
NodeAction action = (NodeAction)serializedObject.targetObject;
action.monoScript = (MonoScript)EditorGUILayout.ObjectField ("Action Script", action.monoScript, typeof(MonoScript), false);
if (action.monoScript != null) {
if (!action.monoScript.GetClass ().IsSubclassOf (typeof(ActionBase))) {
EditorGUILayout.HelpBox (string.Format ("{0} is not a subclass of Hivemind.ActionBase", action.monoScript.GetClass ().ToString ()), MessageType.Warning);
// action.monoScript = null;
} else {
}
}
if (action.action != null) {
ECLEditorUtl.BeginContents ();
{
EditorGUILayout.LabelField ("Event Content");
action.action.DrawInspector (node);
}
ECLEditorUtl.EndContents ();
}
EditorGUILayout.Space ();
DrawInspectorBase (node);
serializedObject.ApplyModifiedProperties ();
}
// private object DrawParamControl(System.Type type, string label, object value) {
// if (type == typeof(string)) {
// return EditorGUILayout.TextField(label, (string) value);
// }
// else if (type == typeof(float)) {
// return EditorGUILayout.FloatField(label, (float) value);
// }
// return null;
// }
// public void DrawInspector(Selector node) {
// EditorGUILayout.LabelField(new GUIContent("Selector"), TitleStyle);
// EditorGUILayout.Space ();
// node.rememberRunning = EditorGUILayout.Toggle("Remember running child", node.rememberRunning);
// string message = "The Selector node ticks its children sequentially from left to right, until one of them returns SUCCESS, RUNNING or ERROR, at which point it returns that state. If all children return the failure state, the priority also returns FAILURE.";
// EditorGUILayout.HelpBox(message, MessageType.Info);
// message = "If \"Remember running chikd\" is on, when a child returns RUNNING the Selector will remember that child, and in future ticks it will skip directly to that child until it returns something other than RUNNING.";
// EditorGUILayout.HelpBox(message, MessageType.Info);
// }
//
// public void DrawInspector(Sequence node) {
// EditorGUILayout.LabelField(new GUIContent("Sequence"), TitleStyle);
// EditorGUILayout.Space ();
// node.rememberRunning = EditorGUILayout.Toggle("Remember running child", node.rememberRunning);
// string message = "The Sequence node ticks its children sequentially from left to right, until one of them returns FAILURE, RUNNING or ERROR, at which point the Sequence returns that state. If all children return the success state, the sequence also returns SUCCESS.";
// EditorGUILayout.HelpBox(message, MessageType.Info);
// message = "If \"Remember running child\" is on, when a child returns RUNNING the Sequence will remember that child, and in future ticks it will skip directly to that child until it returns something other than RUNNING.";
// EditorGUILayout.HelpBox(message, MessageType.Info);
// }
//
// public void DrawInspector(Parallel node) {
// EditorGUILayout.LabelField(new GUIContent("Parallel"), TitleStyle);
// EditorGUILayout.Space ();
//
//
// node.strategy = (Parallel.ResolutionStrategy) EditorGUILayout.EnumPopup("Return Strategy", node.strategy);
// string message = "The parallel node ticks all children sequentially from left to right, regardless of their return states. It returns SUCCESS if the number of succeeding children is larger than a local constant S, FAILURE if the number of failing children is larger than a local constant F or RUNNING otherwise.";
// EditorGUILayout.HelpBox(message, MessageType.Info);
// EditorGUILayout.HelpBox("Not yet implemented!", MessageType.Error);
// }
//
// public void DrawInspector(Repeater node) {
// EditorGUILayout.LabelField(new GUIContent("Repeater"), TitleStyle);
// EditorGUILayout.Space ();
// string message = "Repeater decorator sends the tick signal to its child every time that its child returns a SUCCESS or FAILURE.";
// EditorGUILayout.HelpBox(message, MessageType.Info);
// EditorGUILayout.HelpBox("Not yet implemented!", MessageType.Error);
// }
//
// public void DrawInspector(Inverter node) {
// EditorGUILayout.LabelField(new GUIContent("Inveter"), TitleStyle);
// EditorGUILayout.Space ();
// string message = "Like the NOT operator, the inverter decorator negates the result of its child node, i.e., SUCCESS state becomes FAILURE, and FAILURE becomes SUCCESS. RUNNING or ERROR states are returned as is.";
// EditorGUILayout.HelpBox(message, MessageType.Info);
// EditorGUILayout.HelpBox("Not yet implemented!", MessageType.Error);
// }
//
// public void DrawInspector(Succeeder node) {
// EditorGUILayout.LabelField(new GUIContent("Succeeder"), TitleStyle);
// EditorGUILayout.Space ();
// string message = "Succeeder always returns a SUCCESS, no matter what its child returns.";
// EditorGUILayout.HelpBox(message, MessageType.Info);
// EditorGUILayout.HelpBox("Not yet implemented!", MessageType.Error);
// }
//
// public void DrawInspector(UntilSucceed node) {
// EditorGUILayout.LabelField(new GUIContent("Repeat Until Succeed"), TitleStyle);
// EditorGUILayout.Space ();
// string message = "This decorator keeps calling its child until the child returns a SUCCESS value. When this happen, the decorator return a SUCCESS state.";
// EditorGUILayout.HelpBox(message, MessageType.Info);
// EditorGUILayout.HelpBox("Not yet implemented!", MessageType.Error);
// }
//
// public void DrawInspector(RandomSelector node) {
// EditorGUILayout.LabelField(new GUIContent("Random Selector"), TitleStyle);
// EditorGUILayout.Space ();
// if (node.ChildCount > 0) {
// float chance = 100f / node.ChildCount;
// EditorGUILayout.LabelField(new GUIContent("Each child has a " + chance.ToString ("F1") + "% chance of being selected."), SubtitleStyle);
// }
// string message = "The Random Selector sends the tick signal to one of its children, selected at random, and returns the state returned by that child.";
// EditorGUILayout.HelpBox(message, MessageType.Info);
// EditorGUILayout.HelpBox("Not yet implemented!", MessageType.Error);
// }
public void DrawError ()
{
EditorGUILayout.LabelField ("Selected node is invalid");
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: b96f652a0ef1a488fa6d57ad4e74bd74
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,64 @@
using UnityEngine;
using UnityEditor;
using System.Collections;
namespace Hivemind {
public class GridRenderer {
Texture2D gridTex;
public static int width { get { return 120; } }
public static int height { get { return 120; } }
public static Vector2 step { get { return new Vector2(width / 10, height / 10); } }
void GenerateGrid() {
gridTex = new Texture2D(width, height);
gridTex.hideFlags = HideFlags.DontSave;
Color bg = new Color(0.365f, 0.365f, 0.365f);
Color dark = new Color(0.278f, 0.278f, 0.278f);
Color light = new Color(0.329f, 0.329f, 0.329f);
Color darkX = new Color(0.216f, 0.216f, 0.216f);
Color lightX = new Color(0.298f, 0.298f, 0.298f);
for (int x = 0; x < width; x ++) {
for (int y = 0; y < height; y ++) {
if (x == 0 && y == 0)
gridTex.SetPixel(x, y, darkX);
else if (x == 0 || y == 0)
gridTex.SetPixel(x, y, dark);
else if (x % step.x == 0 && y % step.y == 0)
gridTex.SetPixel(x, y, lightX);
else if (x % step.x == 0 || y % step.y == 0)
gridTex.SetPixel(x, y, light);
else
gridTex.SetPixel(x, y, bg);
}
}
gridTex.Apply();
}
public void Draw(Vector2 scrollPoint, Rect canvas) {
if (!gridTex) GenerateGrid ();
float yOffset = scrollPoint.y % gridTex.height;
float yStart = scrollPoint.y - yOffset;
float yEnd = scrollPoint.y + canvas.height + yOffset;
float xOffset = scrollPoint.x % gridTex.width;
float xStart = scrollPoint.x - xOffset;
float xEnd = scrollPoint.x + canvas.width + xOffset;
for (float x = xStart; x < xEnd; x += gridTex.width) {
for (float y = yStart; y < yEnd; y += gridTex.height) {
GUI.DrawTexture(new Rect(x, y, gridTex.width, gridTex.height), gridTex);
}
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 022fe7acf7ac94fd29ae89afc1feb0d8
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,281 @@
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.Collections.Generic;
namespace Hivemind
{
public class NodeRenderer
{
Texture2D nodeTexture;
Texture2D nodeDebugTexture;
Texture2D shadowTexture;
Color edgeColor = Color.white;
Color shadowColor = new Color (0f, 0f, 0f, 0.15f);
// Selection
Texture2D selectionTexture;
Color selColor = new Color (1f, .78f, .353f);
float selMargin = 2f;
float selWidth = 2f;
private Dictionary<string, Texture2D> textures = new Dictionary<string, Texture2D> ();
public static float Width { get { return GridRenderer.step.x * 6; } }
public static float Height { get { return GridRenderer.step.y * 6; } }
public void Draw (Node node, bool selected)
{
float shadowOffset = 3;
Vector2 offset = new Vector2 (shadowOffset, shadowOffset);
// Edge
for (int i = 0; i < node.parents.Count; i++) {
if (node.parents [i] is NodeBranch) {
Vector2 startPos = node.parents [i].editorPosition;
if (((NodeBranch)(node.parents [i])).inLeft (node)) {
startPos.x -= (NodeRenderer.Width / 4);
// Shadow
DrawEdge (startPos + offset, node.editorPosition + offset, Width, Height, shadowColor);
// Line
DrawEdge (startPos, node.editorPosition, Width, Height, edgeColor);
}
startPos = node.parents [i].editorPosition;
if (((NodeBranch)(node.parents [i])).inRight (node)) {
startPos.x += (NodeRenderer.Width / 4);
// Shadow
DrawEdge (startPos + offset, node.editorPosition + offset, Width, Height, shadowColor);
// Line
DrawEdge (startPos, node.editorPosition, Width, Height, edgeColor);
}
} else {
// Shadow
DrawEdge (node.parents [i].editorPosition + offset, node.editorPosition + offset, Width, Height, shadowColor);
// Line
DrawEdge (node.parents [i].editorPosition, node.editorPosition, Width, Height, edgeColor);
}
}
//Kill nodes
if (node is NodeBranch) {
NodeBranch branch = node as NodeBranch;
for (int i = 0; i < branch.KillLeftNodes.Count; i++) {
Vector2 startPos = node.editorPosition;
startPos.x -= (NodeRenderer.Width / 4);
// Shadow
DrawEdge (startPos + offset, branch.KillLeftNodes [i].editorPosition + offset, Width, Height, shadowColor);
// Line
DrawEdge (startPos, branch.KillLeftNodes [i].editorPosition, Width, Height, Color.red);
}
for (int i = 0; i < branch.KillRightNodes.Count; i++) {
if (branch.KillRightNodes [i] == null)
continue;
Vector2 startPos = node.editorPosition;
startPos.x += (NodeRenderer.Width / 4);
// Shadow
DrawEdge (startPos + offset, branch.KillRightNodes [i].editorPosition + offset, Width, Height, shadowColor);
// Line
DrawEdge (startPos, branch.KillRightNodes [i].editorPosition, Width, Height, Color.red);
}
} else {
for (int i = 0; i < node.KillNodes.Count; i++) {
// Shadow
DrawEdge (node.editorPosition + offset, node.KillNodes [i].editorPosition + offset, Width, Height, shadowColor);
// Line
DrawEdge (node.editorPosition, node.KillNodes [i].editorPosition, Width, Height, Color.red);
}
}
// Node Shadow
Rect nodeRect = new Rect (node.editorPosition.x, node.editorPosition.y, Width, Height);
Rect shadowRect = new Rect (nodeRect.x + shadowOffset, nodeRect.y + shadowOffset, nodeRect.width, nodeRect.height);
if (shadowTexture == null) {
shadowTexture = new Texture2D (1, 1);
shadowTexture.hideFlags = HideFlags.DontSave;
shadowTexture.SetPixel (0, 0, shadowColor);
shadowTexture.Apply ();
}
GUI.DrawTexture (shadowRect, shadowTexture);
// Node
if (nodeTexture == null) {
Color colA = new Color (0.765f, 0.765f, 0.765f);
Color colB = new Color (0.886f, 0.886f, 0.886f);
nodeTexture = new Texture2D (1, (int)Height);
nodeTexture.hideFlags = HideFlags.DontSave;
for (int y = 0; y < Height; y++) {
nodeTexture.SetPixel (0, y, Color.Lerp (colA, colB, (float)y / 75));
}
nodeTexture.Apply ();
}
// Node Debug
if (nodeDebugTexture == null) {
Color colA = new Color (1.000f, 0.796f, 0.357f);
Color colB = new Color (0.894f, 0.443f, 0.008f);
nodeDebugTexture = new Texture2D (1, (int)Height);
nodeDebugTexture.hideFlags = HideFlags.DontSave;
for (int y = 0; y < Height; y++) {
nodeDebugTexture.SetPixel (0, y, Color.Lerp (colA, colB, (float)y / 75));
}
nodeDebugTexture.Apply ();
}
if (node.behaviorTree.debugMode && node.behaviorTree.currentNode == node) {
GUI.DrawTexture (nodeRect, nodeDebugTexture);
} else {
GUI.DrawTexture (nodeRect, nodeTexture);
}
// Icons
DrawNodeIcon (nodeRect, node);
GUI.color = Color.black;
EditorGUI.LabelField (new Rect (nodeRect.x, nodeRect.y + 58, nodeRect.width, nodeRect.height), node.index.ToString ());
GUI.color = Color.white;
DrawMuttimesIcon (nodeRect, node);
// Debug status
// DrawStatusIcon (nodeRect, node);
// Action title
if (node is NodeAction) {
// Node title
string title = node.desc;
// if (((Action)node).methodInfo != null)
// title = ((Action)node).methodName;
// else
// title = "";
title = title.Replace (".", ".\n");
Vector2 textSize = GUI.skin.label.CalcSize (new GUIContent (title));
float x = node.editorPosition.x + (Width / 2) - (textSize.x / 2) - 6;
Rect titleRect = new Rect (x, node.editorPosition.y + Height, textSize.x + 10, textSize.y);
EditorGUI.DropShadowLabel (titleRect, new GUIContent (title));
}
// Selection highlight
if (selected) {
if (selectionTexture == null) {
selectionTexture = new Texture2D (1, 1);
selectionTexture.hideFlags = HideFlags.DontSave;
selectionTexture.SetPixel (0, 0, selColor);
selectionTexture.Apply ();
}
float mbOffset = selMargin + selWidth; // Margin + Border offset
GUI.DrawTexture (new Rect (nodeRect.x - mbOffset, nodeRect.y - mbOffset, nodeRect.width + mbOffset * 2, selWidth), selectionTexture); // Top
GUI.DrawTexture (new Rect (nodeRect.x - mbOffset, nodeRect.y - selMargin, selWidth, nodeRect.height + selMargin * 2), selectionTexture); // Left
GUI.DrawTexture (new Rect (nodeRect.x + nodeRect.width + selMargin, nodeRect.y - selMargin, selWidth, nodeRect.height + selMargin * 2), selectionTexture); // Right
GUI.DrawTexture (new Rect (nodeRect.x - mbOffset, nodeRect.y + nodeRect.height + selMargin, nodeRect.width + mbOffset * 2, selWidth), selectionTexture); // Top
}
}
private void DrawMuttimesIcon (Rect nodeRect, Node node)
{
if (node.canMultTimes) {
if (!textures.ContainsKey ("canMultTimes")) {
Texture2D tex = (Texture2D)AssetDatabase.LoadAssetAtPath<Texture2D> ("Assets/CoolapeFrame/Hivemind/EditorResources/Status/Running.png");
if (tex == null) {
// Debug.LogWarning (status + ".png not found");
return;
}
tex.hideFlags = HideFlags.DontSave;
textures.Add ("canMultTimes", tex);
}
Rect statusRect = new Rect (nodeRect.x, nodeRect.y, 32f, 32f);
GUI.DrawTexture (statusRect, textures ["canMultTimes"]);
}
}
private void DrawStatusIcon (Rect nodeRect, Node node)
{
EditorGUI.LabelField (new Rect (nodeRect.x, nodeRect.y + 58f, nodeRect.width, nodeRect.height), node.lastTick.ToString ());
if (node.lastStatus != null && BTEditorManager.Manager.behaviorTree.TotalTicks == node.lastTick) {
string status = node.lastStatus.ToString ();
if (!textures.ContainsKey (status)) {
Texture2D tex = (Texture2D)AssetDatabase.LoadAssetAtPath<Texture2D> ("Assets/CoolapeFrame/Hivemind/EditorResources/Status/" + status + ".png");
if (tex == null) {
Debug.LogWarning (status + ".png not found");
return;
}
tex.hideFlags = HideFlags.DontSave;
textures.Add (status, tex);
}
Rect statusRect = new Rect (nodeRect.x, nodeRect.y, 32f, 32f);
GUI.DrawTexture (statusRect, textures [status]);
}
}
private void DrawNodeIcon (Rect nodeRect, Node node)
{
int width = NearestPowerOfTwo (nodeRect.width);
int height = NearestPowerOfTwo (nodeRect.height);
float xOffset = (nodeRect.width - width) / 2;
float yOffset = (nodeRect.height - height) / 2;
Rect iconRect = new Rect (nodeRect.x + xOffset, nodeRect.y + yOffset, width, height);
string nodeName = node.GetType ().Name;
// if (node is Sequence && ((Sequence) node).rememberRunning) nodeName = "MemSequence";
// if (node is Selector && ((Selector) node).rememberRunning) nodeName = "MemSelector";
if (!textures.ContainsKey (nodeName)) {
Texture2D tex = (Texture2D)AssetDatabase.LoadAssetAtPath<Texture2D> ("Assets/CoolapeFrame/Hivemind/EditorResources/Nodes/" + nodeName + ".png");
if (tex == null) {
Debug.LogWarning (nodeName + ".png not found");
return;
}
tex.hideFlags = HideFlags.DontSave;
textures.Add (nodeName, tex);
}
GUI.DrawTexture (iconRect, textures [nodeName]);
}
int NearestPowerOfTwo (float value)
{
int result = 1;
do {
result = result << 1;
} while (result << 1 < value);
return result;
}
public static void DrawEdge (Vector2 start, Vector2 end, float width, float height, Color color)
{
float offset = width / 2;
Vector3 startPos = new Vector3 (start.x + offset, start.y + height, 0);
Vector3 endPos = new Vector3 (end.x + offset, end.y, 0);
Vector3 startTan = startPos + Vector3.up * GridRenderer.step.x * 2;
Vector3 endTan = endPos + Vector3.down * GridRenderer.step.x * 2;
Handles.DrawBezier (startPos, endPos, startTan, endTan, color, null, 4);
// Handles.ArrowCap(0, endPos, Quaternion.FromToRotation(new Vector3(0, 0, 1), new Vector3(0, 0, 1)), 154);
Handles.color = color;
Handles.DrawSolidDisc (endPos, new Vector3 (0, 0, 1), 5);
Handles.color = Color.white;
}
public Rect rectForNode (Node node, Vector2 offset)
{
return new Rect (node.editorPosition.x - offset.x, node.editorPosition.y - offset.y, Width, Height);
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: dfe6e92e7477f475e985f16aef49f009
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,488 @@
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.Collections.Generic;
namespace Hivemind
{
enum Mode
{
NodeAction,
CanvasAction,
DragNode,
PanCanvas,
ConnectParent,
ConnectChild,
ConnectKillChild,
ConnectLeftChild,
ConnectLeftKillChild,
ConnectRightChild,
ConnectRightKillChild,
InvokeMenu,
None
}
public class View
{
GridRenderer gridRenderer;
Rect canvas;
public Vector2 scrollPoint = Vector2.zero;
NodeRenderer nodeRenderer;
public Editor nodeInspector;
BTEditorWindow editorWindow;
Mode currentMode = Mode.None;
Node contextNode;
Vector2 initialMousePosition = Vector2.zero;
public List<Node> selectedNodes = new List<Node> ();
Vector2 nodeActionOffset = Vector2.zero;
public View (BTEditorWindow owner)
{
editorWindow = owner;
canvas = new Rect (0, 0, owner.position.width, owner.position.height);
}
void DrawNodes (List<Node> nodes)
{
if (nodeRenderer == null)
nodeRenderer = new NodeRenderer ();
int count = nodes.Count;
for (int i = 0; i < count; i++) {
if (nodes [i] != null) {
nodeRenderer.Draw (nodes [i], selectedNodes.Contains (nodes [i]));
}
}
}
public bool Draw (Rect position)
{
bool needsRepaint = HandleMouseEvents (position, BTEditorManager.Manager.behaviorTree.nodes);
scrollPoint = GUI.BeginScrollView (new Rect (0, 0, position.width, position.height), scrollPoint, canvas);
if (gridRenderer == null)
gridRenderer = new GridRenderer ();
gridRenderer.Draw (scrollPoint, canvas);
DrawNodes (BTEditorManager.Manager.behaviorTree.nodes);
if (currentMode == Mode.ConnectChild || currentMode == Mode.ConnectParent
|| currentMode == Mode.ConnectLeftChild || currentMode == Mode.ConnectRightChild) {
DrawConnectionLine (Color.white);
needsRepaint = true;
} else if (currentMode == Mode.ConnectKillChild
|| currentMode == Mode.ConnectRightKillChild
|| currentMode == Mode.ConnectLeftKillChild) {
DrawConnectionLine (Color.red);
needsRepaint = true;
}
GUI.EndScrollView ();
return needsRepaint;
}
void DrawConnectionLine (Color color)
{
Vector3 startPos = Vector3.zero;
Vector3 startTan = Vector3.zero;
Vector3 endPos = new Vector3 (Event.current.mousePosition.x, Event.current.mousePosition.y, 0);
Vector3 endTan = Vector3.zero;
if (currentMode == Mode.ConnectParent) {
startPos = new Vector3 (contextNode.editorPosition.x + (NodeRenderer.Width / 2), contextNode.editorPosition.y, 0);
startTan = startPos + Vector3.down * GridRenderer.step.x * 2;
endTan = endPos + Vector3.up * GridRenderer.step.x * 2;
} else if (currentMode == Mode.ConnectChild || currentMode == Mode.ConnectKillChild) {
startPos = new Vector3 (contextNode.editorPosition.x + (NodeRenderer.Width / 2), contextNode.editorPosition.y + NodeRenderer.Height, 0);
startTan = startPos + Vector3.up * GridRenderer.step.x * 2;
endTan = endPos + Vector3.down * GridRenderer.step.x * 2;
} else if (currentMode == Mode.ConnectLeftChild || currentMode == Mode.ConnectLeftKillChild) {
startPos = new Vector3 (contextNode.editorPosition.x + (NodeRenderer.Width / 2) - (NodeRenderer.Width / 4), contextNode.editorPosition.y + NodeRenderer.Height, 0);
startTan = startPos + Vector3.up * GridRenderer.step.x * 2;
endTan = endPos + Vector3.down * GridRenderer.step.x * 2;
} else if (currentMode == Mode.ConnectRightChild || currentMode == Mode.ConnectRightKillChild) {
startPos = new Vector3 (contextNode.editorPosition.x + (NodeRenderer.Width / 2) + (NodeRenderer.Width / 4), contextNode.editorPosition.y + NodeRenderer.Height, 0);
startTan = startPos + Vector3.up * GridRenderer.step.x * 2;
endTan = endPos + Vector3.down * GridRenderer.step.x * 2;
}
Handles.DrawBezier (startPos, endPos, startTan, endTan, color, null, 4);
// Handles.ArrowCap(0, endPos, Quaternion.FromToRotation(startPos, endPos), 54);
Handles.DrawWireCube (endPos, Vector3.one * 10);
}
// Returns true if needs a repaint
bool HandleMouseEvents (Rect position, List<Node> nodes)
{
// MouseDown //
// Identify the control being clicked
if (Event.current.type == EventType.MouseDown) {
// Do nothing for MouseDown on the horizontal scrollbar, if present
if (canvas.width > position.width && Event.current.mousePosition.y >= position.height - 20) {
currentMode = Mode.None;
}
// Do nothing for MouseDown on the vertical scrollbar, if present
else if (canvas.height > position.height && Event.current.mousePosition.x >= position.width - 20) {
currentMode = Mode.None;
}
// MouseDown in the canvas, check if in a node or on background
else {
// Store the mouse position
initialMousePosition = Event.current.mousePosition;
// Loop through nodes and check if their rects contain the mouse position
for (int i = 0; i < nodes.Count; i++) {
if (nodes [i] != null && nodeRenderer.rectForNode (nodes [i], scrollPoint).Contains (Event.current.mousePosition)) {
// Connect a parent to a child
if (contextNode is NodeBranch) {
if (currentMode == Mode.ConnectLeftChild) {
BTEditorManager.Manager.ConnectLeft ((NodeBranch)contextNode, nodes [i]);
editorWindow.wantsMouseMove = false;
currentMode = Mode.None;
break;
} else if (currentMode == Mode.ConnectLeftKillChild) {
BTEditorManager.Manager.ConnectLeftKill ((NodeBranch)contextNode, nodes [i]);
editorWindow.wantsMouseMove = false;
currentMode = Mode.None;
break;
} else if (currentMode == Mode.ConnectRightChild) {
BTEditorManager.Manager.ConnectRight ((NodeBranch)contextNode, nodes [i]);
editorWindow.wantsMouseMove = false;
currentMode = Mode.None;
break;
} else if (currentMode == Mode.ConnectRightKillChild) {
BTEditorManager.Manager.ConnectRightKill ((NodeBranch)contextNode, nodes [i]);
editorWindow.wantsMouseMove = false;
currentMode = Mode.None;
break;
} else if (currentMode == Mode.ConnectParent) {
BTEditorManager.Manager.Connect (nodes [i], contextNode);
editorWindow.wantsMouseMove = false;
currentMode = Mode.None;
break;
}
// Perform a node action at key up
else {
currentMode = Mode.NodeAction;
contextNode = nodes [i];
nodeActionOffset = Event.current.mousePosition - nodes [i].editorPosition;
}
} else {
if (currentMode == Mode.ConnectChild) {
BTEditorManager.Manager.Connect (contextNode, nodes [i]);
editorWindow.wantsMouseMove = false;
currentMode = Mode.None;
break;
} else if (currentMode == Mode.ConnectKillChild) {
BTEditorManager.Manager.ConnectKill (contextNode, nodes [i]);
editorWindow.wantsMouseMove = false;
currentMode = Mode.None;
break;
}
// Connect a child to a parent
else if (currentMode == Mode.ConnectParent) {
BTEditorManager.Manager.Connect (nodes [i], contextNode);
editorWindow.wantsMouseMove = false;
currentMode = Mode.None;
break;
}
// Perform a node action at key up
else {
currentMode = Mode.NodeAction;
contextNode = nodes [i];
nodeActionOffset = Event.current.mousePosition - nodes [i].editorPosition;
}
}
}
}
// Cancel the connection
if (currentMode == Mode.ConnectParent || currentMode == Mode.ConnectChild
|| currentMode == Mode.ConnectLeftChild || currentMode == Mode.ConnectRightChild
|| currentMode == Mode.ConnectKillChild || currentMode == Mode.ConnectLeftKillChild
|| currentMode == Mode.ConnectRightKillChild) {
editorWindow.wantsMouseMove = false;
currentMode = Mode.None;
}
// MouseDown on the canvas background enables panning the view
if (currentMode == Mode.None) {
currentMode = Mode.CanvasAction;
}
}
}
// Mouse Up //
// MouseUp resets the current interaction mode to None
if (Event.current.type == EventType.MouseUp) {
// Select node
if (currentMode == Mode.NodeAction && Event.current.button == 0) {
currentMode = Mode.None;
SelectNode (contextNode);
return true;
}
// Deselect node
else if (currentMode == Mode.CanvasAction && Event.current.button == 0) {
SelectNode (null);
currentMode = Mode.None;
return true;
}
// Context Menu
else if (Event.current.button == 1) {
if (currentMode == Mode.NodeAction) {
editorWindow.ShowContextMenu (Event.current.mousePosition, contextNode);
} else if (currentMode == Mode.CanvasAction) {
editorWindow.ShowContextMenu (Event.current.mousePosition, null);
}
currentMode = Mode.None;
}
// Resize canvas after a drag
else if (currentMode == Mode.DragNode) {
ResizeCanvas ();
currentMode = Mode.None;
return true;
} else {
currentMode = Mode.None;
}
}
// Mouse Drag //
if (Event.current.type == EventType.MouseDrag && Event.current.button == 0) {
// Switch to Pan mode
if (currentMode == Mode.CanvasAction) {
currentMode = Mode.PanCanvas;
}
// Switch to node dragging mode
if (currentMode == Mode.NodeAction && contextNode != null) {
float deltaX = Mathf.Abs (Event.current.mousePosition.x - initialMousePosition.x);
float deltaY = Mathf.Abs (Event.current.mousePosition.y - initialMousePosition.y);
// Ignore mouse drags inside nodes lesser than the grid step. These would be rounded,
// and make selecting a node slightly more difficult.
if (deltaX >= GridRenderer.step.x || deltaY >= GridRenderer.step.y) {
currentMode = Mode.DragNode;
}
}
// Pan if the mouse drag initiated by MouseDown outside any windows
if (currentMode == Mode.PanCanvas) {
scrollPoint.x += -Event.current.delta.x;
scrollPoint.y += -Event.current.delta.y;
currentMode = Mode.PanCanvas;
return true;
}
// Drag a node
if (currentMode == Mode.DragNode) {
Vector2 newPositionAbs = Event.current.mousePosition - nodeActionOffset;
float x = newPositionAbs.x - (newPositionAbs.x % GridRenderer.step.x);
float y = newPositionAbs.y - (newPositionAbs.y % GridRenderer.step.y);
DragNode (contextNode, new Vector2 (x, y));
currentMode = Mode.DragNode;
return true;
}
}
return false;
}
public void ResizeCanvas ()
{
Rect newCanvas = new Rect (0, 0, editorWindow.position.width, editorWindow.position.height);
foreach (Node node in BTEditorManager.Manager.behaviorTree.nodes) {
float xOffset = node.editorPosition.x + NodeRenderer.Width + GridRenderer.step.x * 2;
if (xOffset > newCanvas.width) {
newCanvas.width = xOffset;
}
float yOffset = node.editorPosition.y + NodeRenderer.Height + GridRenderer.step.y * 2;
if (yOffset > newCanvas.height) {
newCanvas.height = yOffset;
}
canvas = newCanvas;
}
}
public void SelectNode (Node node)
{
if (node == null) {
selectedNodes.Clear ();
} else {
if (Event.current != null && (Event.current.command || Event.current.control)) {
if (!selectedNodes.Contains (node)) {
selectedNodes.Add (node);
}
} else {
selectedNodes.Clear ();
selectedNodes.Add (node);
}
}
Editor nodeInspector = Editor.CreateEditor (node);
if (nodeInspector != null) {
BTEditorManager.Manager.nodeInspector = nodeInspector;
BTEditorManager.Manager.nodeInspector.Repaint ();
} else if (BTEditorManager.Manager.btInspector != null) {
BTEditorManager.Manager.nodeInspector = null;
BTEditorManager.Manager.btInspector.Repaint ();
}
}
private void DragNode (Node node, Vector2 newPosition)
{
// if (Application.isPlaying) {
// return;
// }
Hashtable map = new Hashtable ();
doDragNode (node, newPosition, ref map);
map.Clear ();
map = null;
}
private void doDragNode (Node node, Vector2 newPosition, ref Hashtable map)
{
Node _node;
map [node] = true;
if (Event.current.shift) {
if (node.ChildCount > 0) {
for (int i = 0; i < node.ChildCount; i++) {
_node = node.Children [i];
Vector2 childOffset = _node.editorPosition - node.editorPosition;
Vector2 newChildPosition = newPosition + childOffset;
if (map [_node] == null) {
doDragNode (_node, newChildPosition, ref map);
}
}
}
for (int i = 0; i < node.KillNodes.Count; i++) {
_node = node.KillNodes [i];
Vector2 childOffset = _node.editorPosition - node.editorPosition;
Vector2 newChildPosition = newPosition + childOffset;
if (map [_node] == null) {
doDragNode (_node, newChildPosition, ref map);
}
}
if (node is NodeBranch) {
for (int i = 0; i < ((NodeBranch)node).ChildrenLeft.Count; i++) {
_node = ((NodeBranch)node).ChildrenLeft [i];
Vector2 childOffset = _node.editorPosition - node.editorPosition;
Vector2 newChildPosition = newPosition + childOffset;
if (map [_node] == null) {
doDragNode (_node, newChildPosition, ref map);
}
}
for (int i = 0; i < ((NodeBranch)node).KillLeftNodes.Count; i++) {
_node = ((NodeBranch)node).KillLeftNodes [i];
Vector2 childOffset = _node.editorPosition - node.editorPosition;
Vector2 newChildPosition = newPosition + childOffset;
if (map [_node] == null) {
doDragNode (_node, newChildPosition, ref map);
}
}
for (int i = 0; i < ((NodeBranch)node).ChildrenRight.Count; i++) {
_node = ((NodeBranch)node).ChildrenRight [i];
Vector2 childOffset = _node.editorPosition - node.editorPosition;
Vector2 newChildPosition = newPosition + childOffset;
if (map [_node] == null) {
doDragNode (_node, newChildPosition, ref map);
}
}
for (int i = 0; i < ((NodeBranch)node).KillRightNodes.Count; i++) {
_node = ((NodeBranch)node).KillRightNodes [i];
Vector2 childOffset = _node.editorPosition - node.editorPosition;
Vector2 newChildPosition = newPosition + childOffset;
if (map [_node] == null) {
doDragNode (_node, newChildPosition, ref map);
}
}
}
}
BTEditorManager.Manager.SetEditorPosition (node, newPosition);
}
public void ConnectParent (Node node)
{
editorWindow.wantsMouseMove = true;
contextNode = node;
currentMode = Mode.ConnectParent;
}
public void ConnectChild (Node node)
{
editorWindow.wantsMouseMove = true;
contextNode = node;
currentMode = Mode.ConnectChild;
}
public void ConnectKillChild (Node node)
{
editorWindow.wantsMouseMove = true;
contextNode = node;
currentMode = Mode.ConnectKillChild;
}
public void ConnectLeftChild (Node node)
{
editorWindow.wantsMouseMove = true;
contextNode = node;
currentMode = Mode.ConnectLeftChild;
}
public void ConnectLeftKillChild (Node node)
{
editorWindow.wantsMouseMove = true;
contextNode = node;
currentMode = Mode.ConnectLeftKillChild;
}
public void ConnectRightChild (Node node)
{
editorWindow.wantsMouseMove = true;
contextNode = node;
currentMode = Mode.ConnectRightChild;
}
public void ConnectRightKillChild (Node node)
{
editorWindow.wantsMouseMove = true;
contextNode = node;
currentMode = Mode.ConnectRightKillChild;
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: e0a34463203824fe3a3b375ee3725023
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 78544a8fd044c4861b1c26794ecb984f
folderAsset: yes
timeCreated: 1501226182
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 9237ae549d6704f62a7ba048896bbcdb
folderAsset: yes
timeCreated: 1501226182
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1,90 @@
fileFormatVersion: 2
guid: 44647b938762b496480af21e344f7658
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,90 @@
fileFormatVersion: 2
guid: 8db14f77c98c4481baa5ab1273862943
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,90 @@
fileFormatVersion: 2
guid: 15a49b030cf2449f89cb0bf3c7499a1f
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 B

View File

@@ -0,0 +1,90 @@
fileFormatVersion: 2
guid: f50247411f96442d4bc3faae5e1b98e5
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,90 @@
fileFormatVersion: 2
guid: 8cdac8ea096424f8faf166b7dfd3de10
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -0,0 +1,92 @@
fileFormatVersion: 2
guid: 56437b0e37e154c20960b5bfeae6f1c3
timeCreated: 1501927475
licenseType: Pro
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,90 @@
fileFormatVersion: 2
guid: c1177e118197f4a57b5561a3a1188fb8
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -0,0 +1,90 @@
fileFormatVersion: 2
guid: d3a1dba32140548278b4947c8db83a23
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -0,0 +1,90 @@
fileFormatVersion: 2
guid: fd926f80fdf8c4ee18dd5adfcf50ed00
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -0,0 +1,90 @@
fileFormatVersion: 2
guid: 781e78412ffdb45c4aab82017511dff7
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 903 B

View File

@@ -0,0 +1,90 @@
fileFormatVersion: 2
guid: c229709a9f71e4de885b96d1648d526c
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 B

View File

@@ -0,0 +1,90 @@
fileFormatVersion: 2
guid: d3c29495514184ff0b050356966d2688
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,90 @@
fileFormatVersion: 2
guid: 44c920aaa4f434e17b89a9a5dcd585fb
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@@ -0,0 +1,90 @@
fileFormatVersion: 2
guid: 7df45aa7443a74d85b7bc4dc5802f382
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 3cc6d3fab80ba4a31b7ce63bbbfd3c88
folderAsset: yes
timeCreated: 1501226182
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 B

View File

@@ -0,0 +1,90 @@
fileFormatVersion: 2
guid: ddb9814b6904348bc91dedc887137a9b
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

View File

@@ -0,0 +1,90 @@
fileFormatVersion: 2
guid: bedce6baac1184c96ab6e8bb993fb4ae
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 728 B

View File

@@ -0,0 +1,90 @@
fileFormatVersion: 2
guid: 47c99ea64fb6a47c9a65d1ef94b33662
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 B

View File

@@ -0,0 +1,90 @@
fileFormatVersion: 2
guid: c10858103b2d748df855c00d09e92803
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,66 @@
fileFormatVersion: 2
guid: 31d8eb409255c43c09c0ff1a74d1b733
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 1
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Bruno Daniel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,6 @@
fileFormatVersion: 2
guid: 8dd5dc4cf19b2490a892d905acff4434
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,86 @@
![](HivemindLogo.png?raw=true)
# Hivemind
Hivemind is a [Behavior Tree](http://en.wikipedia.org/wiki/Behavior_Trees_(Artificial_Intelligence,_Robotics_and_Control)) implementation for Unity3D that features a visual editor with runtime visual debugging capabilities.
![Screenshot](Screenshot.png?raw=true)
## Warning!
This project is in early development, and while everything described bellow is currently functional, keep in mind:
- Many node types are simply not yet implemented (a warning will be displayed in the inspector for these) and will always return the Error status.
- There might be many undiscovered bugs.
- Performance will probably degrade rapidly with very large trees or many concurrent agents.
## What is a Behavior Tree?
Behavior Trees are widely used in the game development industry (as well as other fields such as robotics) that allows a designer to map a complex set of branching actions, sensors and conditions that simulate inteligent behavior in an artificial agent, be it an individual game character or a virtual oponent or ally controlling multiple agents or game mechanics.
## How to use Hivemind to implement Behavior Trees in your game
### The Behavior Tree asset
A Hivemind `Behavior Tree` is a reusable custom assets that you store in your Unity project, and behave similarly to the native `Animator Controller`.
As any other asset, simply chose `Assets / Create / Behavior Tree` to create a Hivemind Behavior Tree asset in your project.
With a Behavior Tree asset selected in your Project view, you can bring up the visual editor by clicking `Window / Behavior Tree Editor`.
A newly created Behavior Tree will have a single "root" node. Most of the visual editor functionality is controlled via right-click context menus on the nodes and the editor background, as well as the Unity3D inspector for configuring selected nodes.
### The Behavior Tree Agent component
`Behavior Tree Agent` is a component that can be added to any `GameObject`, that lets you assign an existing Behavior Tree to that Game Object to create AI enabled agents in your game.
### Action Libraries
Actions are mapped to methods in classes that inherit from `Hivemind.ActionLibrary`. The action library methods can then be decorated with the `[Hivemind.Action]` attribute, making that action available in the visual editor.
##### Variables
Action Libraries have two inherited variables:
- `agent`: holds a reference to the current agent
- `context`: a dictionary-like structure that can be used to pass data between actions, instantiated once per behavior tree, per agent
##### Implementing Action Libraries
Actions can be as generic as the designer wants them, so that they can be reused as much as possible in the project.
An action library class is instantiated (on demand) once per agent, per behavior tree. The behavior tree will call the `Start` function of the action library as soon as the library is instantiated and the agent and context variables have been populated, so the user can do any necessary initialization.
Multiple Action Libraries can be used in a Behavior Tree, but each will only be instantiated once.
Actions __must__ return a value from the `Hivemind.Status` enum, which include:
- `Success`
- `Failure`
- `Running`
- `Error`
##### Parameters
The method parameters can be used to configure an action node. Currently, only the C# primitives `string` and `float` are allowed. More C# primitives and other value types, as well as common Unity3D object references are planned for future implementation.
##### Context
The current Context, accessible via the `context` variable inherited from `Hivemind.ActionLibrary`, is a key-value store similar to dictionaries, but implemented as a C# generic. It has the following public methods:
- `Set<T>(string key, T value)`: Sets a value of type T
- `Get<T>(string key)`: Retrieves a value of type T
- `Unset(string key)`: Removes a value from the context
Action methods can be decorated with attributes that hint to Context values that method expects or populates, and these will show up on the visual editor inspector:
- `[Hivemind.Expects(string key, Type type)]`
- `[Hivemind.Outputs(string key, Tyoe type)]`
In the future, a design-time debugging feature will ensure context values required by an action are populated in previous actions. For the moment, a designer can use the above attributes as reference.
### Debugging
To watch the execution of a behavior tree in real time, make sure you have selected a _Game Object_ that has a _Behavior Tree Agent_ component attached, and open the _Behavior Tree Editor window_. The screenshot above illustrates a runing Behavior Tree.
Additionaly, the current _Context_ is displayed in the _Behavior Tree Agent_ component inspector.

View File

@@ -0,0 +1,6 @@
fileFormatVersion: 2
guid: 6cdda0ca0d27945f5bcfdfb067240672
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -0,0 +1,66 @@
fileFormatVersion: 2
guid: f10d8e593d9a64f31b1884970131face
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: -1
mipBias: -1
wrapMode: -1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 1022d6d162577442b8478317c6b23ac6
folderAsset: yes
timeCreated: 1501502688
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View 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";
//
// }
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: f68a0330f34b8447290696a10f310892
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 8d721d4ced48f4544a3f55b4fc2dfd3e
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 8b19824139cd641f6b5b5a0fbd948643
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 31d8eb409255c43c09c0ff1a74d1b733, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}
}

View 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:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: e57d8564939ff40cf8909dcc8a9121aa
folderAsset: yes
timeCreated: 1501226182
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View 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
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: c8d2fae72e25943db8b4cd1c62acb0c3
timeCreated: 1501582378
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 456f96f74bcae48cf8a2d9317b960e9f
timeCreated: 1501551538
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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);
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 8296fe6385d2a4398a4edc55236087ed
timeCreated: 1501552530
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,12 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Hivemind;
using Coolape;
namespace Hivemind
{
public class NodeTogether : NodeAction
{
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0cb0498c85a854d1f92a5b6602aad53e
timeCreated: 1502099325
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}
}

View 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:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 47f41e969821b4cb5855ddde1dafbe26
folderAsset: yes
timeCreated: 1501588335
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 757ebf96fe3c24e7cbdaa8d92a707973
folderAsset: yes
timeCreated: 1501659114
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,80 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Hivemind;
using Coolape;
public class DataExporter
{
[ExportHiveData]
public static void exportEventCfg (List<Node> nodes)
{
ArrayList list = new ArrayList ();
ArrayList cell = new ArrayList ();
Node node = null;
PStr pstr = PStr.b ();
for (int i = 0; i < nodes.Count; i++) {
node = nodes [i];
if (node is Root) {
continue;
}
pstr.a (node.index);
pstr.a ("\t");
if (node.behaviorTree.rootNode.attr != null) {
pstr.a (((MyRoot)(node.behaviorTree.rootNode.attr)).fubenID);
} else {
pstr.a (0);
}
pstr.a ("\t");
pstr.a (node.condition);
pstr.a ("\t");
if (node is NodeAction) {
if (((NodeAction)node).action != null) {
MyAction action = ((NodeAction)node).action as MyAction;
pstr.a (action.triggerType);
pstr.a ("\t");
pstr.a (action.hideSelf.ToString ().ToLower ());
pstr.a ("\t");
pstr.a (action.talkId);
pstr.a ("\t");
pstr.a (action.npcCfg);
pstr.a ("\t");
pstr.a (action.boxCfg);
pstr.a ("\t");
} else {
pstr.a (0);
pstr.a ("\t");
pstr.a ("false");
pstr.a ("\t");
pstr.a (0);
pstr.a ("\t");
pstr.a ("");
pstr.a ("\t");
pstr.a (0);
pstr.a ("\t");
}
} else {
pstr.a (0);
pstr.a ("\t");
pstr.a ("false");
pstr.a ("\t");
pstr.a (0);
pstr.a ("\t");
pstr.a ("");
pstr.a ("\t");
pstr.a (0);
pstr.a ("\t");
}
pstr.a (node.result2);
pstr.a ("\t");
pstr.a (node.result1);
pstr.a ("\t");
pstr.a ("");
pstr.a ("\n");
}
Debug.Log (pstr.e ());
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 1104598e91bc7462fbd7c1e35b5c48e3
timeCreated: 1501659135
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,57 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Hivemind;
using Coolape;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class MyAction : ActionBase
{
public int triggerType = 0;
public bool hideSelf = false;
public int talkId = 0;
public string npcCfg = "";
public string boxCfg = "";
public override Hashtable Serialize ()
{
Hashtable m = new Hashtable ();
m["triggerType"] = triggerType;
m ["hideSelf"] = hideSelf;
m ["talkId"] = talkId;
m ["npcCfg"] = npcCfg.Trim ();
m ["boxCfg"] = boxCfg;
return m;
}
public override void Deserialize (Hashtable map)
{
triggerType = MapEx.getInt (map, "triggerType");
hideSelf = MapEx.getBool (map, "hideSelf");
talkId = MapEx.getInt (map, "talkId");
npcCfg = MapEx.getString (map, "npcCfg");
boxCfg = MapEx.getString (map, "boxCfg");
}
#if UNITY_EDITOR
public override void DrawInspector (Node node)
{
triggerType = (EditorGUILayout.Toggle (new GUIContent ("主角碰撞触发"), (triggerType== 0?true:false))) ?0:1;
triggerType = (EditorGUILayout.Toggle (new GUIContent ("自动触发"), (triggerType == 0 ? false : true ))) ? 1:0;
EditorGUILayout.LabelField("---------------------------");
EditorGUILayout.Space();
hideSelf = EditorGUILayout.Toggle (new GUIContent ("Hide Self"), hideSelf);
talkId = EditorGUILayout.IntField (new GUIContent ("Talking id"), talkId);
// EditorGUILayout.BeginHorizontal ();
EditorGUILayout.LabelField (new GUIContent ("Npc Config"));
npcCfg = EditorGUILayout.TextArea (npcCfg);
// EditorGUILayout.EndHorizontal ();
boxCfg = EditorGUILayout.TextField (new GUIContent ("Box Config"), boxCfg);
}
#endif
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: d1b15828fcf774418a4eac9e2084bb1d
timeCreated: 1501588346
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,31 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Hivemind;
using Coolape;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class MyRoot:ActionBase
{
public int fubenID;
public override void Deserialize (Hashtable map)
{
fubenID = MapEx.getInt (map, "fubenID");
}
public override Hashtable Serialize ()
{
Hashtable m = new Hashtable ();
m["fubenID"] = fubenID;
return m;
}
#if UNITY_EDITOR
public override void DrawInspector (Node node)
{
fubenID = EditorGUILayout.IntField (new GUIContent ("副本ID"), fubenID);
}
#endif
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 9f1d5ab0d67244c82b0962f1c71f6420
timeCreated: 1501666617
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: