959e80cf72
assets upload description.
172 lines
5.2 KiB
C#
172 lines
5.2 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using XNode;
|
|
using RPGCreationKit.BehaviourTree;
|
|
using UnityEditor;
|
|
|
|
namespace RPGCreationKit.BehaviourTree
|
|
{
|
|
[CreateNodeMenu("RPGCK_BehaviourTree/Random Selector", order = 1)]
|
|
[System.Serializable]
|
|
public class RandomSelectorNode : BTNode
|
|
{
|
|
[Output(ShowBackingValue.Never, ConnectionType.Multiple, TypeConstraint.None)] public BTNode outputs;
|
|
|
|
// A list of indexes of every child task. This list is used by the Fischer-Yates shuffle algorithm.
|
|
private List<int> possibilities = new List<int>();
|
|
// The random child index execution order.
|
|
private Stack<int> orderStack = new Stack<int>();
|
|
|
|
public BTNode nodeExecuting;
|
|
|
|
// Use this for initialization
|
|
protected override void Init()
|
|
{
|
|
base.Init();
|
|
}
|
|
|
|
[ContextMenu("Work")]
|
|
public override void ReorderChild()
|
|
{
|
|
List<NodePort> endPorts = GetOutputPort("outputs").GetConnections();
|
|
|
|
List<BTNode> nodes = new List<BTNode>();
|
|
|
|
for (int i = 0; i < endPorts.Count; i++)
|
|
nodes.Add((endPorts[i].node as BTNode));
|
|
|
|
nodes.Sort(SortInGraphYPos);
|
|
|
|
for (int i = 0; i < nodes.Count; i++)
|
|
{
|
|
BTNode btNode = nodes[i] as BTNode;
|
|
btNode.indexInSequence = i;
|
|
}
|
|
}
|
|
|
|
// Return the correct value of an output port when requested
|
|
public override object GetValue(NodePort port)
|
|
{
|
|
return null; // Replace this
|
|
}
|
|
|
|
public override NodeState Execute()
|
|
{
|
|
if (m_NodeState == NodeState.Success || m_NodeState == NodeState.Failure)
|
|
if (hasEvaluated == true)
|
|
return m_NodeState;
|
|
|
|
if (!STARTED)
|
|
OnStart();
|
|
|
|
List<NodePort> endPorts = GetOutputPort("outputs").GetConnections();
|
|
|
|
if (nodeExecuting != null && nodeExecuting.m_NodeState != NodeState.Failure && nodeExecuting.m_NodeState != NodeState.Success)
|
|
{
|
|
switch (nodeExecuting.Execute())
|
|
{
|
|
case NodeState.Failure:
|
|
break;
|
|
|
|
case NodeState.Success:
|
|
m_NodeState = NodeState.Success;
|
|
hasEvaluated = true;
|
|
return m_NodeState;
|
|
|
|
case NodeState.Running:
|
|
m_NodeState = NodeState.Running;
|
|
return m_NodeState;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if(nodeExecuting != null && nodeExecuting.m_NodeState == NodeState.Success)
|
|
{
|
|
m_NodeState = NodeState.Success;
|
|
hasEvaluated = true;
|
|
return m_NodeState;
|
|
}
|
|
|
|
// Pop the top index from the stack and set the execution status.
|
|
while (orderStack.Count > 0)
|
|
{
|
|
nodeExecuting = (endPorts[orderStack.Pop()].node as BTNode);
|
|
return NodeState.Running;
|
|
}
|
|
|
|
// If we reach this far we've failed
|
|
m_NodeState = NodeState.Failure;
|
|
hasEvaluated = true;
|
|
return m_NodeState;
|
|
}
|
|
|
|
public override void ReEvaluate()
|
|
{
|
|
if (m_NodeState != NodeState.Running)
|
|
{
|
|
base.ReEvaluate();
|
|
hasEvaluated = false;
|
|
nodeExecuting = null;
|
|
OnStart();
|
|
|
|
List<NodePort> endPorts = GetOutputPort("outputs").GetConnections();
|
|
|
|
for (int i = 0; i < endPorts.Count; i++)
|
|
{
|
|
(endPorts[i].node as BTNode).ReEvaluate();
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void OnCreateConnection(NodePort from, NodePort to)
|
|
{
|
|
base.OnCreateConnection(from, to);
|
|
|
|
#if UNITY_EDITOR
|
|
EditorApplication.delayCall += ReorderChild;
|
|
#endif
|
|
}
|
|
|
|
public override void OnRemoveConnection(NodePort port)
|
|
{
|
|
base.OnRemoveConnection(port);
|
|
|
|
if (port.fieldName == "input")
|
|
indexInSequence = -1;
|
|
else if (port.fieldName == "outputs")
|
|
{
|
|
#if UNITY_EDITOR
|
|
EditorApplication.delayCall += ReorderChild;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
public override void OnStart()
|
|
{
|
|
possibilities.Clear();
|
|
for (int i = 0; i < GetOutputPort("outputs").GetConnections().Count; ++i)
|
|
possibilities.Add(i);
|
|
|
|
// Randomize the indecies
|
|
RandomizeIndicies();
|
|
|
|
STARTED = true;
|
|
}
|
|
|
|
private void RandomizeIndicies()
|
|
{
|
|
orderStack.Clear();
|
|
// Use Fischer-Yates shuffle to randomize the child index order.
|
|
for (int i = possibilities.Count; i > 0; --i)
|
|
{
|
|
int j = Random.Range(0, i);
|
|
int index = possibilities[j];
|
|
orderStack.Push(index);
|
|
possibilities[j] = possibilities[i - 1];
|
|
possibilities[i - 1] = index;
|
|
}
|
|
}
|
|
}
|
|
} |