diff --git a/Assets/FluidBehaviorTree/Runtime/BehaviorTree/Builder/BehaviorTreeBuilder.cs b/Assets/FluidBehaviorTree/Runtime/BehaviorTree/Builder/BehaviorTreeBuilder.cs index d184e8b8..a7b9539c 100644 --- a/Assets/FluidBehaviorTree/Runtime/BehaviorTree/Builder/BehaviorTreeBuilder.cs +++ b/Assets/FluidBehaviorTree/Runtime/BehaviorTree/Builder/BehaviorTreeBuilder.cs @@ -62,6 +62,18 @@ public BehaviorTreeBuilder ReturnFailure (string name = "return failure") { return ParentTask(name); } + public BehaviorTreeBuilder RepeatUntilSuccess (string name = "repeat until success") { + return ParentTask(name); + } + + public BehaviorTreeBuilder RepeatUntilFailure (string name = "repeat until failure") { + return ParentTask(name); + } + + public BehaviorTreeBuilder RepeatForever (string name = "repeat forever") { + return ParentTask(name); + } + public BehaviorTreeBuilder Sequence (string name = "sequence") { return ParentTask(name); } diff --git a/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatForever.cs b/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatForever.cs new file mode 100644 index 00000000..2790f9b8 --- /dev/null +++ b/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatForever.cs @@ -0,0 +1,12 @@ +using CleverCrow.Fluid.BTs.Trees; +using CleverCrow.Fluid.BTs.Decorators; +using CleverCrow.Fluid.BTs.Tasks; + +namespace CleverCrow.Fluid.BTs.Decorators { + public class RepeatForever : DecoratorBase { + protected override TaskStatus OnUpdate () { + Child?.Update(); + return TaskStatus.Continue; + } + } +} \ No newline at end of file diff --git a/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatForever.cs.meta b/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatForever.cs.meta new file mode 100644 index 00000000..c16bf277 --- /dev/null +++ b/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatForever.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 65839dd3e71d9955cab17e0d05863a0a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilFailure.cs b/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilFailure.cs new file mode 100644 index 00000000..29a25491 --- /dev/null +++ b/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilFailure.cs @@ -0,0 +1,23 @@ +using CleverCrow.Fluid.BTs.Trees; +using CleverCrow.Fluid.BTs.Decorators; +using CleverCrow.Fluid.BTs.Tasks; + +namespace CleverCrow.Fluid.BTs.Decorators { + public class RepeatUntilFailure : DecoratorBase { + protected override TaskStatus OnUpdate () { + if (Child == null) { + return TaskStatus.Failure; + } + + var childStatus = Child.Update(); + var status = childStatus; + + if (status == TaskStatus.Failure) { + return TaskStatus.Failure; + } + else { + return TaskStatus.Continue; + } + } + } +} \ No newline at end of file diff --git a/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilFailure.cs.meta b/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilFailure.cs.meta new file mode 100644 index 00000000..8dd3ade3 --- /dev/null +++ b/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilFailure.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5fb297690fca8cd7786b74d71ef239e0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilSuccess.cs b/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilSuccess.cs new file mode 100644 index 00000000..ba856812 --- /dev/null +++ b/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilSuccess.cs @@ -0,0 +1,23 @@ +using CleverCrow.Fluid.BTs.Trees; +using CleverCrow.Fluid.BTs.Decorators; +using CleverCrow.Fluid.BTs.Tasks; + +namespace CleverCrow.Fluid.BTs.Decorators { + public class RepeatUntilSuccess : DecoratorBase { + protected override TaskStatus OnUpdate () { + if (Child == null) { + return TaskStatus.Success; + } + + var childStatus = Child.Update(); + var status = childStatus; + + if (status == TaskStatus.Success) { + return TaskStatus.Success; + } + else { + return TaskStatus.Continue; + } + } + } +} \ No newline at end of file diff --git a/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilSuccess.cs.meta b/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilSuccess.cs.meta new file mode 100644 index 00000000..62144074 --- /dev/null +++ b/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilSuccess.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 54b8ae154a20d7962807cc92d3eb7beb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatForeverTest.cs b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatForeverTest.cs new file mode 100644 index 00000000..9a65e0d5 --- /dev/null +++ b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatForeverTest.cs @@ -0,0 +1,40 @@ +using CleverCrow.Fluid.BTs.Decorators; +using CleverCrow.Fluid.BTs.Tasks; +using NUnit.Framework; + +namespace CleverCrow.Fluid.BTs.Testing { + public class RepeatForeverTest { + public class UpdateMethod { + [Test] + public void Returns_continue_on_child_failure () { + var repeater = new RepeatForever(); + repeater.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Failure).Build()); + + Assert.AreEqual(TaskStatus.Continue, repeater.Update()); + } + + [Test] + public void Returns_continue_on_child_success () { + var repeater = new RepeatForever(); + repeater.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Success).Build()); + + Assert.AreEqual(TaskStatus.Continue, repeater.Update()); + } + + [Test] + public void Returns_continue_on_child_continue () { + var repeater = new RepeatForever(); + repeater.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Continue).Build()); + + Assert.AreEqual(TaskStatus.Continue, repeater.Update()); + } + + [Test] + public void Does_not_crash_if_no_child () { + var repeater = new RepeatForever(); + + Assert.DoesNotThrow(() => repeater.Update()); + } + } + } +} \ No newline at end of file diff --git a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatForeverTest.cs.meta b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatForeverTest.cs.meta new file mode 100644 index 00000000..f7abc484 --- /dev/null +++ b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatForeverTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a9fec445c46d5cfc3ac851729718f4c9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilFailureTest.cs b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilFailureTest.cs new file mode 100644 index 00000000..42b9b97e --- /dev/null +++ b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilFailureTest.cs @@ -0,0 +1,40 @@ +using CleverCrow.Fluid.BTs.Decorators; +using CleverCrow.Fluid.BTs.Tasks; +using NUnit.Framework; + +namespace CleverCrow.Fluid.BTs.Testing { + public class RepeatUntilFailureTest { + public class UpdateMethod { + [Test] + public void Returns_failure_on_child_failure () { + var repeater = new RepeatUntilFailure(); + repeater.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Failure).Build()); + + Assert.AreEqual(TaskStatus.Failure, repeater.Update()); + } + + [Test] + public void Returns_continue_on_child_success () { + var repeater = new RepeatUntilFailure(); + repeater.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Success).Build()); + + Assert.AreEqual(TaskStatus.Continue, repeater.Update()); + } + + [Test] + public void Returns_continue_on_child_continue () { + var repeater = new RepeatUntilFailure(); + repeater.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Continue).Build()); + + Assert.AreEqual(TaskStatus.Continue, repeater.Update()); + } + + [Test] + public void Does_not_crash_if_no_child () { + var repeater = new RepeatUntilFailure(); + + Assert.DoesNotThrow(() => repeater.Update()); + } + } + } +} \ No newline at end of file diff --git a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilFailureTest.cs.meta b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilFailureTest.cs.meta new file mode 100644 index 00000000..4e380188 --- /dev/null +++ b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilFailureTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 13022081698b1f4178aba4db227f8581 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilSuccessTest.cs b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilSuccessTest.cs new file mode 100644 index 00000000..56749a5f --- /dev/null +++ b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilSuccessTest.cs @@ -0,0 +1,40 @@ +using CleverCrow.Fluid.BTs.Decorators; +using CleverCrow.Fluid.BTs.Tasks; +using NUnit.Framework; + +namespace CleverCrow.Fluid.BTs.Testing { + public class RepeatUntilSuccessTest { + public class UpdateMethod { + [Test] + public void Returns_continue_on_child_failure () { + var repeater = new RepeatUntilSuccess(); + repeater.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Failure).Build()); + + Assert.AreEqual(TaskStatus.Continue, repeater.Update()); + } + + [Test] + public void Returns_success_on_child_success () { + var repeater = new RepeatUntilSuccess(); + repeater.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Success).Build()); + + Assert.AreEqual(TaskStatus.Success, repeater.Update()); + } + + [Test] + public void Returns_continue_on_child_continue () { + var repeater = new RepeatUntilSuccess(); + repeater.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Continue).Build()); + + Assert.AreEqual(TaskStatus.Continue, repeater.Update()); + } + + [Test] + public void Does_not_crash_if_no_child () { + var repeater = new RepeatUntilSuccess(); + + Assert.DoesNotThrow(() => repeater.Update()); + } + } + } +} \ No newline at end of file diff --git a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilSuccessTest.cs.meta b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilSuccessTest.cs.meta new file mode 100644 index 00000000..79188009 --- /dev/null +++ b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilSuccessTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0bf525114006ef88e9d68806ac766bfb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: