first commit
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
using NodeCanvas.Framework;
|
||||
using ParadoxNotion;
|
||||
using ParadoxNotion.Design;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace NodeCanvas.BehaviourTrees
|
||||
{
|
||||
|
||||
[Category("Composites")]
|
||||
[Description("Quick way to execute the left or the right child, based on a Condition Task.")]
|
||||
[ParadoxNotion.Design.Icon("Condition")]
|
||||
[Color("b3ff7f")]
|
||||
public class BinarySelector : BTNode, ITaskAssignable<ConditionTask>
|
||||
{
|
||||
|
||||
[Tooltip("If true, the condition will be re-evaluated per frame.")]
|
||||
public bool dynamic;
|
||||
|
||||
[SerializeField]
|
||||
private ConditionTask _condition;
|
||||
|
||||
private int succeedIndex;
|
||||
|
||||
public override int maxOutConnections { get { return 2; } }
|
||||
public override Alignment2x2 commentsAlignment { get { return Alignment2x2.Right; } }
|
||||
|
||||
public override string name {
|
||||
get { return base.name.ToUpper(); }
|
||||
}
|
||||
|
||||
public Task task {
|
||||
get { return condition; }
|
||||
set { condition = (ConditionTask)value; }
|
||||
}
|
||||
|
||||
private ConditionTask condition {
|
||||
get { return _condition; }
|
||||
set { _condition = value; }
|
||||
}
|
||||
|
||||
protected override Status OnExecute(Component agent, IBlackboard blackboard) {
|
||||
|
||||
if ( condition == null || outConnections.Count < 2 ) {
|
||||
return Status.Optional;
|
||||
}
|
||||
|
||||
if ( status == Status.Resting ) {
|
||||
condition.Enable(agent, blackboard);
|
||||
}
|
||||
|
||||
if ( dynamic || status == Status.Resting ) {
|
||||
var lastIndex = succeedIndex;
|
||||
succeedIndex = condition.Check(agent, blackboard) ? 0 : 1;
|
||||
if ( succeedIndex != lastIndex ) {
|
||||
outConnections[lastIndex].Reset();
|
||||
}
|
||||
}
|
||||
|
||||
return outConnections[succeedIndex].Execute(agent, blackboard);
|
||||
}
|
||||
|
||||
protected override void OnReset() {
|
||||
if ( condition != null ) { condition.Disable(); }
|
||||
}
|
||||
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
///---------------------------------------UNITY EDITOR-------------------------------------------
|
||||
#if UNITY_EDITOR
|
||||
|
||||
public override string GetConnectionInfo(int i) {
|
||||
return i == 0 ? "TRUE" : "FALSE";
|
||||
}
|
||||
|
||||
protected override void OnNodeGUI() {
|
||||
if ( dynamic ) {
|
||||
GUILayout.Label("<b>DYNAMIC</b>");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 48e71e5905e9e394e83cbdce71c91feb
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 14914
|
||||
packageName: NodeCanvas
|
||||
packageVersion: 3.3.1
|
||||
assetPath: Assets/ParadoxNotion/NodeCanvas/Modules/BehaviourTrees/Nodes/Composites/BinarySelector.cs
|
||||
uploadId: 704937
|
||||
@@ -0,0 +1,48 @@
|
||||
using NodeCanvas.Framework;
|
||||
using ParadoxNotion.Design;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace NodeCanvas.BehaviourTrees
|
||||
{
|
||||
|
||||
[Category("Composites")]
|
||||
[Description("Works like a normal Selector, but when a child returns Success, that child will be moved to the end.\nAs a result, previously Failed children will always be checked first and recently Successful children last.")]
|
||||
[ParadoxNotion.Design.Icon("FlipSelector")]
|
||||
[Color("b3ff7f")]
|
||||
public class FlipSelector : BTComposite
|
||||
{
|
||||
|
||||
private int current;
|
||||
|
||||
protected override Status OnExecute(Component agent, IBlackboard blackboard) {
|
||||
|
||||
for ( var i = current; i < outConnections.Count; i++ ) {
|
||||
|
||||
status = outConnections[i].Execute(agent, blackboard);
|
||||
|
||||
if ( status == Status.Running ) {
|
||||
current = i;
|
||||
return Status.Running;
|
||||
}
|
||||
|
||||
if ( status == Status.Success ) {
|
||||
SendToBack(i);
|
||||
return Status.Success;
|
||||
}
|
||||
}
|
||||
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
void SendToBack(int i) {
|
||||
var c = outConnections[i];
|
||||
outConnections.RemoveAt(i);
|
||||
outConnections.Add(c);
|
||||
}
|
||||
|
||||
protected override void OnReset() {
|
||||
current = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dcf40bac689367f4ba07b1a75299e628
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 14914
|
||||
packageName: NodeCanvas
|
||||
packageVersion: 3.3.1
|
||||
assetPath: Assets/ParadoxNotion/NodeCanvas/Modules/BehaviourTrees/Nodes/Composites/FlipSelector.cs
|
||||
uploadId: 704937
|
||||
@@ -0,0 +1,123 @@
|
||||
using System.Collections.Generic;
|
||||
using NodeCanvas.Framework;
|
||||
using ParadoxNotion;
|
||||
using ParadoxNotion.Design;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace NodeCanvas.BehaviourTrees
|
||||
{
|
||||
|
||||
[Name("Parallel", 8)]
|
||||
[Category("Composites")]
|
||||
[Description("Executes all children simultaneously and return Success or Failure depending on the selected Policy.")]
|
||||
[ParadoxNotion.Design.Icon("Parallel")]
|
||||
[Color("ff64cb")]
|
||||
public class Parallel : BTComposite
|
||||
{
|
||||
|
||||
public enum ParallelPolicy
|
||||
{
|
||||
FirstFailure,
|
||||
FirstSuccess,
|
||||
FirstSuccessOrFailure
|
||||
}
|
||||
|
||||
[Tooltip("The policy determines when the Parallel node will end and return its Status.")]
|
||||
public ParallelPolicy policy = ParallelPolicy.FirstFailure;
|
||||
[Name("Repeat"), Tooltip("If true, finished children are repeated until the Policy set is met, or until all children have had a chance to finish at least once.")]
|
||||
public bool dynamic;
|
||||
|
||||
private bool[] finishedConnections;
|
||||
private int finishedConnectionsCount;
|
||||
|
||||
public override void OnGraphStarted() {
|
||||
finishedConnections = new bool[outConnections.Count];
|
||||
finishedConnectionsCount = 0;
|
||||
}
|
||||
|
||||
protected override Status OnExecute(Component agent, IBlackboard blackboard) {
|
||||
|
||||
var defferedStatus = Status.Resting;
|
||||
for ( var i = 0; i < outConnections.Count; i++ ) {
|
||||
var connection = outConnections[i];
|
||||
var isConnectionFinished = finishedConnections[i] == true;
|
||||
|
||||
if ( !dynamic && isConnectionFinished ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( connection.status != Status.Running && isConnectionFinished ) {
|
||||
connection.Reset();
|
||||
}
|
||||
|
||||
status = connection.Execute(agent, blackboard);
|
||||
|
||||
if ( defferedStatus == Status.Resting ) {
|
||||
if ( status == Status.Failure && ( policy == ParallelPolicy.FirstFailure || policy == ParallelPolicy.FirstSuccessOrFailure ) ) {
|
||||
defferedStatus = Status.Failure;
|
||||
}
|
||||
|
||||
if ( status == Status.Success && ( policy == ParallelPolicy.FirstSuccess || policy == ParallelPolicy.FirstSuccessOrFailure ) ) {
|
||||
defferedStatus = Status.Success;
|
||||
}
|
||||
}
|
||||
|
||||
if ( status != Status.Running && !isConnectionFinished ) {
|
||||
finishedConnections[i] = true;
|
||||
finishedConnectionsCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( defferedStatus != Status.Resting ) {
|
||||
ResetRunning();
|
||||
status = defferedStatus;
|
||||
return defferedStatus;
|
||||
}
|
||||
|
||||
if ( finishedConnectionsCount == outConnections.Count ) {
|
||||
ResetRunning();
|
||||
switch ( policy ) {
|
||||
case ParallelPolicy.FirstFailure:
|
||||
return Status.Success;
|
||||
case ParallelPolicy.FirstSuccess:
|
||||
return Status.Failure;
|
||||
}
|
||||
}
|
||||
|
||||
return Status.Running;
|
||||
}
|
||||
|
||||
protected override void OnReset() {
|
||||
for ( var i = 0; i < finishedConnections.Length; i++ ) { finishedConnections[i] = false; }
|
||||
finishedConnectionsCount = 0;
|
||||
}
|
||||
|
||||
void ResetRunning() {
|
||||
for ( var i = 0; i < outConnections.Count; i++ ) {
|
||||
if ( outConnections[i].status == Status.Running ) {
|
||||
outConnections[i].Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
///---------------------------------------UNITY EDITOR-------------------------------------------
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
public override string GetConnectionInfo(int i) {
|
||||
if ( dynamic && status == Status.Running ) {
|
||||
return finishedConnections[i] ? "Repeating" : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected override void OnNodeGUI() {
|
||||
GUILayout.Label(( dynamic ? "<b>REPEAT</b>\n" : "" ) + policy.ToString().SplitCamelCase());
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 20bb0006fe2ddc941b3bddd6e00a1321
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 14914
|
||||
packageName: NodeCanvas
|
||||
packageVersion: 3.3.1
|
||||
assetPath: Assets/ParadoxNotion/NodeCanvas/Modules/BehaviourTrees/Nodes/Composites/Parallel.cs
|
||||
uploadId: 704937
|
||||
@@ -0,0 +1,205 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NodeCanvas.Framework;
|
||||
using ParadoxNotion.Design;
|
||||
using ParadoxNotion.Serialization.FullSerializer;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace NodeCanvas.BehaviourTrees
|
||||
{
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
class PrioritySelector_0 : BTComposite
|
||||
{
|
||||
[SerializeField] public List<BBParameter<float>> priorities = null;
|
||||
}
|
||||
///----------------------------------------------------------------------------------------------
|
||||
|
||||
[Category("Composites")]
|
||||
[Description("Used for Utility AI, the Priority Selector executes the child with the highest utility weight. If it fails, the Priority Selector will continue with the next highest utility weight child until one Succeeds, or until all Fail (similar to how a normal Selector does).\n\nEach child branch represents a desire, where each desire has one or more consideration which are all averaged.\nConsiderations are a pair of input value and curve, which together produce the consideration utility weight.\n\nIf Dynamic option is enabled, will continously evaluate utility weights and execute the child with the highest one regardless of what status the children return.")]
|
||||
[ParadoxNotion.Design.Icon("Priority")]
|
||||
[Color("b3ff7f")]
|
||||
[fsMigrateVersions(typeof(PrioritySelector_0))]
|
||||
public class PrioritySelector : BTComposite, IMigratable<PrioritySelector_0>
|
||||
{
|
||||
///----------------------------------------------------------------------------------------------
|
||||
void IMigratable<PrioritySelector_0>.Migrate(PrioritySelector_0 model) {
|
||||
this.desires = new List<Desire>();
|
||||
foreach ( var priority in model.priorities ) {
|
||||
var desire = new Desire();
|
||||
this.desires.Add(desire);
|
||||
var consideration = desire.AddConsideration(graphBlackboard);
|
||||
consideration.input = priority;
|
||||
}
|
||||
}
|
||||
///----------------------------------------------------------------------------------------------
|
||||
|
||||
[System.Serializable]
|
||||
public class Desire
|
||||
{
|
||||
[ParadoxNotion.Serialization.FullSerializer.fsIgnoreInBuild]
|
||||
public string name;
|
||||
[ParadoxNotion.Serialization.FullSerializer.fsIgnoreInBuild]
|
||||
public bool foldout;
|
||||
public List<Consideration> considerations = new List<Consideration>();
|
||||
|
||||
public Consideration AddConsideration(IBlackboard bb) {
|
||||
var result = new Consideration(bb);
|
||||
considerations.Add(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void RemoveConsideration(Consideration consideration) { considerations.Remove(consideration); }
|
||||
|
||||
public float GetCompoundUtility() {
|
||||
float total = 0;
|
||||
for ( var i = 0; i < considerations.Count; i++ ) {
|
||||
total += considerations[i].utility;
|
||||
}
|
||||
return total / considerations.Count;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class Consideration
|
||||
{
|
||||
public BBParameter<float> input;
|
||||
public BBParameter<AnimationCurve> function;
|
||||
public float utility => function.value != null ? function.value.Evaluate(input.value) : input.value;
|
||||
public Consideration(IBlackboard blackboard) {
|
||||
input = new BBParameter<float> { value = 1f, bb = blackboard };
|
||||
function = new BBParameter<AnimationCurve> { bb = blackboard };
|
||||
}
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
|
||||
[Tooltip("If enabled, will continously evaluate utility weights and execute the child with the highest one accordingly. In this mode child return status does not matter.")]
|
||||
public bool dynamic;
|
||||
[AutoSortWithChildrenConnections]
|
||||
public List<Desire> desires;
|
||||
|
||||
private Connection[] orderedConnections;
|
||||
private int current = 0;
|
||||
|
||||
public override void OnChildConnected(int index) {
|
||||
if ( desires == null ) { desires = new List<Desire>(); }
|
||||
if ( desires.Count < outConnections.Count ) { desires.Insert(index, new Desire()); }
|
||||
}
|
||||
|
||||
public override void OnChildDisconnected(int index) { desires.RemoveAt(index); }
|
||||
|
||||
protected override Status OnExecute(Component agent, IBlackboard blackboard) {
|
||||
|
||||
if ( dynamic ) {
|
||||
var highestPriority = float.NegativeInfinity;
|
||||
var best = 0;
|
||||
for ( var i = 0; i < outConnections.Count; i++ ) {
|
||||
var priority = desires[i].GetCompoundUtility();
|
||||
if ( priority > highestPriority ) {
|
||||
highestPriority = priority;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
|
||||
if ( best != current ) {
|
||||
outConnections[current].Reset();
|
||||
current = best;
|
||||
}
|
||||
return outConnections[current].Execute(agent, blackboard);
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
|
||||
if ( status == Status.Resting ) {
|
||||
orderedConnections = outConnections.OrderBy(c => desires[outConnections.IndexOf(c)].GetCompoundUtility()).ToArray();
|
||||
}
|
||||
|
||||
for ( var i = orderedConnections.Length; i-- > 0; ) {
|
||||
status = orderedConnections[i].Execute(agent, blackboard);
|
||||
if ( status == Status.Success ) {
|
||||
return Status.Success;
|
||||
}
|
||||
|
||||
if ( status == Status.Running ) {
|
||||
current = i;
|
||||
return Status.Running;
|
||||
}
|
||||
}
|
||||
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
protected override void OnReset() { current = 0; }
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
///---------------------------------------UNITY EDITOR-------------------------------------------
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
//..
|
||||
public override string GetConnectionInfo(int i) {
|
||||
var desire = desires[i];
|
||||
var desireName = string.IsNullOrEmpty(desire.name) ? "DESIRE " + i.ToString() : desire.name;
|
||||
var result = desireName.ToUpper() + "\n";
|
||||
for ( var j = 0; j < desire.considerations.Count; j++ ) {
|
||||
result += desire.considerations[j].input.ToString() + " (" + desire.considerations[j].utility.ToString("0.00") + ")" + "\n";
|
||||
}
|
||||
return result += string.Format("<b>Avg.</b> ({0})", desire.GetCompoundUtility().ToString("0.00"));
|
||||
}
|
||||
|
||||
//..
|
||||
public override void OnConnectionInspectorGUI(int i) {
|
||||
var desire = desires[i];
|
||||
var optionsB = new EditorUtils.ReorderableListOptions();
|
||||
optionsB.allowAdd = false;
|
||||
optionsB.allowRemove = true;
|
||||
EditorUtils.ReorderableList(desire.considerations, optionsB, (j, pickedB) =>
|
||||
{
|
||||
var consideration = desire.considerations[j];
|
||||
GUILayout.BeginVertical("box");
|
||||
consideration.input = (BBParameter<float>)NodeCanvas.Editor.BBParameterEditor.ParameterField("Input", consideration.input, true);
|
||||
consideration.function = (BBParameter<AnimationCurve>)NodeCanvas.Editor.BBParameterEditor.ParameterField("Curve", consideration.function);
|
||||
GUILayout.EndVertical();
|
||||
});
|
||||
|
||||
if ( GUILayout.Button("Add Consideration") ) { desire.AddConsideration(graphBlackboard); }
|
||||
EditorUtils.Separator();
|
||||
}
|
||||
|
||||
protected override void OnNodeGUI() {
|
||||
if ( dynamic ) { GUILayout.Label("<b>DYNAMIC</b>"); }
|
||||
}
|
||||
|
||||
//..
|
||||
protected override void OnNodeInspectorGUI() {
|
||||
|
||||
if ( outConnections.Count == 0 ) {
|
||||
GUILayout.Label("Make some connections first");
|
||||
return;
|
||||
}
|
||||
|
||||
dynamic = UnityEditor.EditorGUILayout.Toggle(new GUIContent("Dynamic", "If enabled, will continously evaluate utility weights and execute the child with the highest one accordingly. In this mode child return status does not matter."), dynamic);
|
||||
|
||||
EditorUtils.Separator();
|
||||
EditorUtils.CoolLabel("Desires");
|
||||
|
||||
var optionsA = new EditorUtils.ReorderableListOptions();
|
||||
optionsA.allowAdd = false;
|
||||
optionsA.allowRemove = false;
|
||||
EditorUtils.ReorderableList(desires, optionsA, (i, pickedA) =>
|
||||
{
|
||||
var desire = desires[i];
|
||||
var desireName = string.IsNullOrEmpty(desire.name) ? "DESIRE " + i.ToString() : desire.name;
|
||||
desire.foldout = UnityEditor.EditorGUILayout.Foldout(desire.foldout, new GUIContent(desireName));
|
||||
if ( desire.foldout ) {
|
||||
desire.name = UnityEditor.EditorGUILayout.TextField(" Friendly Name", desire.name);
|
||||
OnConnectionInspectorGUI(i);
|
||||
}
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 39f51e3aa06f96c4399b79d7656917c6
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 14914
|
||||
packageName: NodeCanvas
|
||||
packageVersion: 3.3.1
|
||||
assetPath: Assets/ParadoxNotion/NodeCanvas/Modules/BehaviourTrees/Nodes/Composites/PrioritySelector.cs
|
||||
uploadId: 704937
|
||||
@@ -0,0 +1,133 @@
|
||||
using System.Collections.Generic;
|
||||
using NodeCanvas.Framework;
|
||||
using ParadoxNotion.Design;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace NodeCanvas.BehaviourTrees
|
||||
{
|
||||
|
||||
[Category("Composites")]
|
||||
[Description("Selects a child to execute based on its chance to be selected and returns Success if the child returns Success, otherwise picks another child.\nReturns Failure if all children return Failure, or a direct 'Failure Chance' is introduced.")]
|
||||
[ParadoxNotion.Design.Icon("ProbabilitySelector")]
|
||||
[Color("b3ff7f")]
|
||||
public class ProbabilitySelector : BTComposite
|
||||
{
|
||||
|
||||
[AutoSortWithChildrenConnections, Tooltip("The weights of the children.")]
|
||||
public List<BBParameter<float>> childWeights;
|
||||
[Tooltip("A chance for the node to fail immediately.")]
|
||||
public BBParameter<float> failChance;
|
||||
|
||||
private bool[] indexFailed;
|
||||
private float[] tmpWeights;
|
||||
private float tmpFailWeight;
|
||||
private float tmpTotal;
|
||||
private float tmpDice;
|
||||
|
||||
public override void OnChildConnected(int index) {
|
||||
if ( childWeights == null ) { childWeights = new List<BBParameter<float>>(); }
|
||||
if ( childWeights.Count < outConnections.Count ) {
|
||||
childWeights.Insert(index, new BBParameter<float> { value = 1, bb = graphBlackboard });
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnChildDisconnected(int index) {
|
||||
childWeights.RemoveAt(index);
|
||||
}
|
||||
|
||||
public override void OnGraphStarted() { OnReset(); }
|
||||
|
||||
protected override Status OnExecute(Component agent, IBlackboard blackboard) {
|
||||
|
||||
if ( status == Status.Resting ) {
|
||||
tmpDice = Random.value;
|
||||
tmpFailWeight = failChance.value;
|
||||
tmpTotal = tmpFailWeight;
|
||||
for ( var i = 0; i < childWeights.Count; i++ ) {
|
||||
var childWeight = childWeights[i].value;
|
||||
tmpTotal += childWeight;
|
||||
tmpWeights[i] = childWeight;
|
||||
}
|
||||
}
|
||||
|
||||
var prob = tmpFailWeight / tmpTotal;
|
||||
if ( tmpDice < prob ) {
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
for ( var i = 0; i < outConnections.Count; i++ ) {
|
||||
|
||||
if ( indexFailed[i] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
prob += tmpWeights[i] / tmpTotal;
|
||||
if ( tmpDice <= prob ) {
|
||||
status = outConnections[i].Execute(agent, blackboard);
|
||||
if ( status == Status.Success || status == Status.Running ) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if ( status == Status.Failure ) {
|
||||
indexFailed[i] = true;
|
||||
tmpTotal -= tmpWeights[i];
|
||||
return Status.Running;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
protected override void OnReset() {
|
||||
tmpWeights = new float[outConnections.Count];
|
||||
indexFailed = new bool[outConnections.Count];
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
///---------------------------------------UNITY EDITOR-------------------------------------------
|
||||
#if UNITY_EDITOR
|
||||
|
||||
float GetTotal() {
|
||||
var total = failChance.value;
|
||||
for ( var i = 0; i < childWeights.Count; i++ ) {
|
||||
total += childWeights[i].value;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public override string GetConnectionInfo(int i) {
|
||||
return Mathf.Round(( childWeights[i].value / GetTotal() ) * 100) + "%";
|
||||
}
|
||||
|
||||
public override void OnConnectionInspectorGUI(int i) {
|
||||
NodeCanvas.Editor.BBParameterEditor.ParameterField("Weight", childWeights[i]);
|
||||
}
|
||||
|
||||
protected override void OnNodeInspectorGUI() {
|
||||
|
||||
if ( outConnections.Count == 0 ) {
|
||||
GUILayout.Label("Make some connections first");
|
||||
return;
|
||||
}
|
||||
|
||||
var total = GetTotal();
|
||||
for ( var i = 0; i < childWeights.Count; i++ ) {
|
||||
GUILayout.BeginHorizontal();
|
||||
childWeights[i] = (BBParameter<float>)NodeCanvas.Editor.BBParameterEditor.ParameterField("Weight", childWeights[i]);
|
||||
GUILayout.Label(Mathf.Round(( childWeights[i].value / total ) * 100) + "%", GUILayout.Width(38));
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
GUILayout.Space(5);
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
failChance = (BBParameter<float>)NodeCanvas.Editor.BBParameterEditor.ParameterField("Direct Failure Chance", failChance);
|
||||
GUILayout.Label(Mathf.Round(( failChance.value / total ) * 100) + "%", GUILayout.Width(38));
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 23428d321072cac43b4e9c02610e96d6
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 14914
|
||||
packageName: NodeCanvas
|
||||
packageVersion: 3.3.1
|
||||
assetPath: Assets/ParadoxNotion/NodeCanvas/Modules/BehaviourTrees/Nodes/Composites/ProbabilitySelector.cs
|
||||
uploadId: 704937
|
||||
@@ -0,0 +1,82 @@
|
||||
using NodeCanvas.Framework;
|
||||
using ParadoxNotion;
|
||||
using ParadoxNotion.Design;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace NodeCanvas.BehaviourTrees
|
||||
{
|
||||
|
||||
[Name("Selector", 9)]
|
||||
[Category("Composites")]
|
||||
[Description("Executes its childrfen in order and returns Failure if all children return Failure. As soon as a child returns Success, the Selector will stop and return Success as well.")]
|
||||
[ParadoxNotion.Design.Icon("Selector")]
|
||||
[Color("b3ff7f")]
|
||||
public class Selector : BTComposite
|
||||
{
|
||||
|
||||
[Tooltip("If true, then higher priority children are re-evaluated per frame and if either returns Success, then the Selector will immediately stop and return Success as well.")]
|
||||
public bool dynamic;
|
||||
[Tooltip("If true, the children order of execution is shuffled each time the Selector resets.")]
|
||||
public bool random;
|
||||
|
||||
private int lastRunningNodeIndex;
|
||||
|
||||
protected override Status OnExecute(Component agent, IBlackboard blackboard) {
|
||||
|
||||
for ( var i = dynamic ? 0 : lastRunningNodeIndex; i < outConnections.Count; i++ ) {
|
||||
|
||||
status = outConnections[i].Execute(agent, blackboard);
|
||||
|
||||
switch ( status ) {
|
||||
case Status.Running:
|
||||
|
||||
if ( dynamic && i < lastRunningNodeIndex ) {
|
||||
for ( var j = i + 1; j <= lastRunningNodeIndex; j++ ) {
|
||||
outConnections[j].Reset();
|
||||
}
|
||||
}
|
||||
|
||||
lastRunningNodeIndex = i;
|
||||
return Status.Running;
|
||||
|
||||
case Status.Success:
|
||||
|
||||
if ( dynamic && i < lastRunningNodeIndex ) {
|
||||
for ( var j = i + 1; j <= lastRunningNodeIndex; j++ ) {
|
||||
outConnections[j].Reset();
|
||||
}
|
||||
}
|
||||
|
||||
return Status.Success;
|
||||
}
|
||||
}
|
||||
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
protected override void OnReset() {
|
||||
lastRunningNodeIndex = 0;
|
||||
if ( random ) { outConnections = outConnections.Shuffle(); }
|
||||
}
|
||||
|
||||
public override void OnChildDisconnected(int index) {
|
||||
if ( index != 0 && index == lastRunningNodeIndex ) {
|
||||
lastRunningNodeIndex--;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGraphStarted() { OnReset(); }
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
///---------------------------------------UNITY EDITOR-------------------------------------------
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnNodeGUI() {
|
||||
if ( dynamic ) { GUILayout.Label("<b>DYNAMIC</b>"); }
|
||||
if ( random ) { GUILayout.Label("<b>RANDOM</b>"); }
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa1c35ff60b06c74cb9102cc2babf462
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 14914
|
||||
packageName: NodeCanvas
|
||||
packageVersion: 3.3.1
|
||||
assetPath: Assets/ParadoxNotion/NodeCanvas/Modules/BehaviourTrees/Nodes/Composites/Selector.cs
|
||||
uploadId: 704937
|
||||
@@ -0,0 +1,80 @@
|
||||
using NodeCanvas.Framework;
|
||||
using ParadoxNotion;
|
||||
using ParadoxNotion.Design;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NodeCanvas.BehaviourTrees
|
||||
{
|
||||
|
||||
[Name("Sequencer", 10)]
|
||||
[Category("Composites")]
|
||||
[Description("Executes its children in order and returns Success if all children return Success. As soon as a child returns Failure, the Sequencer will stop and return Failure as well.")]
|
||||
[ParadoxNotion.Design.Icon("Sequencer")]
|
||||
[Color("bf7fff")]
|
||||
public class Sequencer : BTComposite
|
||||
{
|
||||
|
||||
[Tooltip("If true, then higher priority children are re-evaluated per frame and if either returns Failure, then the Sequencer will immediately stop and return Failure as well.")]
|
||||
public bool dynamic;
|
||||
[Tooltip("If true, the children order of execution is shuffled each time the Sequencer resets.")]
|
||||
public bool random;
|
||||
|
||||
private int lastRunningNodeIndex = 0;
|
||||
|
||||
protected override Status OnExecute(Component agent, IBlackboard blackboard) {
|
||||
|
||||
for ( var i = dynamic ? 0 : lastRunningNodeIndex; i < outConnections.Count; i++ ) {
|
||||
|
||||
status = outConnections[i].Execute(agent, blackboard);
|
||||
|
||||
switch ( status ) {
|
||||
case Status.Running:
|
||||
|
||||
if ( dynamic && i < lastRunningNodeIndex ) {
|
||||
for ( var j = i + 1; j <= lastRunningNodeIndex; j++ ) {
|
||||
outConnections[j].Reset();
|
||||
}
|
||||
}
|
||||
|
||||
lastRunningNodeIndex = i;
|
||||
return Status.Running;
|
||||
|
||||
case Status.Failure:
|
||||
|
||||
if ( dynamic && i < lastRunningNodeIndex ) {
|
||||
for ( var j = i + 1; j <= lastRunningNodeIndex; j++ ) {
|
||||
outConnections[j].Reset();
|
||||
}
|
||||
}
|
||||
|
||||
return Status.Failure;
|
||||
}
|
||||
}
|
||||
|
||||
return Status.Success;
|
||||
}
|
||||
|
||||
protected override void OnReset() {
|
||||
lastRunningNodeIndex = 0;
|
||||
if ( random ) { outConnections = outConnections.Shuffle(); }
|
||||
}
|
||||
|
||||
public override void OnChildDisconnected(int index) {
|
||||
if ( index != 0 && index == lastRunningNodeIndex ) {
|
||||
lastRunningNodeIndex--;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGraphStarted() { OnReset(); }
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
///---------------------------------------UNITY EDITOR-------------------------------------------
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnNodeGUI() {
|
||||
if ( dynamic ) { GUILayout.Label("<b>DYNAMIC</b>"); }
|
||||
if ( random ) { GUILayout.Label("<b>RANDOM</b>"); }
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bafebe0850f5ea84eb87e77c674123e8
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 14914
|
||||
packageName: NodeCanvas
|
||||
packageVersion: 3.3.1
|
||||
assetPath: Assets/ParadoxNotion/NodeCanvas/Modules/BehaviourTrees/Nodes/Composites/Sequencer.cs
|
||||
uploadId: 704937
|
||||
@@ -0,0 +1,32 @@
|
||||
using NodeCanvas.Framework;
|
||||
using ParadoxNotion.Design;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace NodeCanvas.BehaviourTrees
|
||||
{
|
||||
|
||||
[Name("Step Sequencer")]
|
||||
[Category("Composites")]
|
||||
[Description("In comparison to a normal Sequencer which executes all its children until one fails, Step Sequencer executes its children one-by-one per Step Sequencer execution. The executed child status is returned regardless of Success or Failure.")]
|
||||
[ParadoxNotion.Design.Icon("StepIterator")]
|
||||
[Color("bf7fff")]
|
||||
public class StepIterator : BTComposite
|
||||
{
|
||||
|
||||
private int current;
|
||||
|
||||
public override void OnGraphStarted() {
|
||||
current = 0;
|
||||
}
|
||||
|
||||
protected override Status OnExecute(Component agent, IBlackboard blackboard) {
|
||||
current = current % outConnections.Count;
|
||||
return outConnections[current].Execute(agent, blackboard);
|
||||
}
|
||||
|
||||
protected override void OnReset() {
|
||||
current++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1beecc40e55bf82488985475900341fe
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 14914
|
||||
packageName: NodeCanvas
|
||||
packageVersion: 3.3.1
|
||||
assetPath: Assets/ParadoxNotion/NodeCanvas/Modules/BehaviourTrees/Nodes/Composites/StepIterator.cs
|
||||
uploadId: 704937
|
||||
@@ -0,0 +1,137 @@
|
||||
using System.Collections.Generic;
|
||||
using NodeCanvas.Framework;
|
||||
using NodeCanvas.Framework.Internal;
|
||||
using ParadoxNotion;
|
||||
using ParadoxNotion.Design;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NodeCanvas.BehaviourTrees
|
||||
{
|
||||
|
||||
[Category("Composites")]
|
||||
[Description("Executes one child based on the provided int or enum case and returns its status.")]
|
||||
[ParadoxNotion.Design.Icon("IndexSwitcher")]
|
||||
[Color("b3ff7f")]
|
||||
public class Switch : BTComposite
|
||||
{
|
||||
|
||||
public enum CaseSelectionMode
|
||||
{
|
||||
IndexBased = 0,
|
||||
EnumBased = 1
|
||||
}
|
||||
|
||||
public enum OutOfRangeMode
|
||||
{
|
||||
ReturnFailure,
|
||||
LoopIndex
|
||||
}
|
||||
|
||||
[Tooltip("If true and the 'case' change while a child is running, that child will immediately be interrupted and the new child will be executed.")]
|
||||
public bool dynamic;
|
||||
[Tooltip("The selection mode used.")]
|
||||
public CaseSelectionMode selectionMode = CaseSelectionMode.IndexBased;
|
||||
|
||||
[ShowIf("selectionMode", 0)]
|
||||
public BBParameter<int> intCase;
|
||||
[ShowIf("selectionMode", 0)]
|
||||
public OutOfRangeMode outOfRangeMode = OutOfRangeMode.LoopIndex;
|
||||
|
||||
[ShowIf("selectionMode", 1), BlackboardOnly]
|
||||
public BBObjectParameter enumCase = new BBObjectParameter(typeof(System.Enum));
|
||||
private Dictionary<int, int> enumCasePairing;
|
||||
|
||||
private int current;
|
||||
private int runningIndex;
|
||||
|
||||
public override void OnGraphStarted() {
|
||||
if ( selectionMode == CaseSelectionMode.EnumBased ) {
|
||||
var enumValue = enumCase.value;
|
||||
if ( enumValue != null ) {
|
||||
enumCasePairing = new Dictionary<int, int>();
|
||||
var enumValues = System.Enum.GetValues(enumValue.GetType());
|
||||
for ( var i = 0; i < enumValues.Length; i++ ) {
|
||||
enumCasePairing[(int)enumValues.GetValue(i)] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override Status OnExecute(Component agent, IBlackboard blackboard) {
|
||||
|
||||
if ( outConnections.Count == 0 ) {
|
||||
return Status.Optional;
|
||||
}
|
||||
|
||||
if ( status == Status.Resting || dynamic ) {
|
||||
|
||||
if ( selectionMode == CaseSelectionMode.IndexBased ) {
|
||||
current = intCase.value;
|
||||
if ( outOfRangeMode == OutOfRangeMode.LoopIndex ) {
|
||||
current = Mathf.Abs(current) % outConnections.Count;
|
||||
}
|
||||
|
||||
} else {
|
||||
current = enumCasePairing[(int)enumCase.value];
|
||||
}
|
||||
|
||||
if ( runningIndex != current ) {
|
||||
outConnections[runningIndex].Reset();
|
||||
}
|
||||
|
||||
if ( current < 0 || current >= outConnections.Count ) {
|
||||
return Status.Failure;
|
||||
}
|
||||
}
|
||||
|
||||
status = outConnections[current].Execute(agent, blackboard);
|
||||
|
||||
if ( status == Status.Running ) {
|
||||
runningIndex = current;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
///---------------------------------------UNITY EDITOR-------------------------------------------
|
||||
#if UNITY_EDITOR
|
||||
|
||||
public override string GetConnectionInfo(int i) {
|
||||
if ( selectionMode == CaseSelectionMode.EnumBased ) {
|
||||
if ( enumCase.value == null ) {
|
||||
return "Null Enum".FormatError();
|
||||
}
|
||||
var enumNames = System.Enum.GetNames(enumCase.value.GetType());
|
||||
if ( i >= enumNames.Length ) {
|
||||
return "Never".FormatError();
|
||||
}
|
||||
return enumNames[i];
|
||||
}
|
||||
return i.ToString();
|
||||
}
|
||||
|
||||
protected override void OnNodeGUI() {
|
||||
if ( dynamic ) {
|
||||
GUILayout.Label("<b>DYNAMIC</b>");
|
||||
}
|
||||
GUILayout.Label(selectionMode == CaseSelectionMode.IndexBased ? ( "Current = " + intCase.ToString() ) : enumCase.ToString());
|
||||
}
|
||||
|
||||
protected override void OnNodeInspectorGUI() {
|
||||
base.OnNodeInspectorGUI();
|
||||
if ( selectionMode == CaseSelectionMode.EnumBased ) {
|
||||
if ( enumCase.value != null ) {
|
||||
GUILayout.BeginVertical("box");
|
||||
foreach ( var s in System.Enum.GetNames(enumCase.value.GetType()) ) {
|
||||
GUILayout.Label(s);
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d3c9285b12215614d98d6497ad391e78
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 14914
|
||||
packageName: NodeCanvas
|
||||
packageVersion: 3.3.1
|
||||
assetPath: Assets/ParadoxNotion/NodeCanvas/Modules/BehaviourTrees/Nodes/Composites/Switch.cs
|
||||
uploadId: 704937
|
||||
Reference in New Issue
Block a user