From f376ea6ac2e7400b542c09fb3917ec49ae0bd1be Mon Sep 17 00:00:00 2001 From: Jesse Talavera-Greenberg Date: Mon, 3 Jun 2019 21:51:18 -0400 Subject: [PATCH 1/7] feat(decorators): add three new decorators RepeatForever, RepeatUntilSuccess, and RepeatUntilFailure are new decorators used to continue a task indefinitely. RepeatForever executes its child and returns TaskStatus.Continue, regardless of its child's return status. RepeatUntilSuccess returns TaskStatus.Success if its child returns success, else it returns TaskStatus.Continue. RepeatUntilFailure returns TaskStatus.Failure if its child returns failure, else it returns TaskStatus.Continue. --- .../Builder/BehaviorTreeBuilder.cs | 12 ++++++ .../Runtime/Decorators/RepeatForever.cs | 12 ++++++ .../Runtime/Decorators/RepeatForever.cs.meta | 11 +++++ .../Runtime/Decorators/RepeatUntilFailure.cs | 23 +++++++++++ .../Decorators/RepeatUntilFailure.cs.meta | 11 +++++ .../Runtime/Decorators/RepeatUntilSuccess.cs | 23 +++++++++++ .../Decorators/RepeatUntilSuccess.cs.meta | 11 +++++ .../Editor/Decorators/RepeatForeverTest.cs | 40 +++++++++++++++++++ .../Decorators/RepeatForeverTest.cs.meta | 11 +++++ .../Decorators/RepeatUntilFailureTest.cs | 40 +++++++++++++++++++ .../Decorators/RepeatUntilFailureTest.cs.meta | 11 +++++ .../Decorators/RepeatUntilSuccessTest.cs | 40 +++++++++++++++++++ .../Decorators/RepeatUntilSuccessTest.cs.meta | 11 +++++ 13 files changed, 256 insertions(+) create mode 100644 Assets/FluidBehaviorTree/Runtime/Decorators/RepeatForever.cs create mode 100644 Assets/FluidBehaviorTree/Runtime/Decorators/RepeatForever.cs.meta create mode 100644 Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilFailure.cs create mode 100644 Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilFailure.cs.meta create mode 100644 Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilSuccess.cs create mode 100644 Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilSuccess.cs.meta create mode 100644 Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatForeverTest.cs create mode 100644 Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatForeverTest.cs.meta create mode 100644 Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilFailureTest.cs create mode 100644 Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilFailureTest.cs.meta create mode 100644 Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilSuccessTest.cs create mode 100644 Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilSuccessTest.cs.meta 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: From 1eecfb61bf845f58008955cdee75d37953ab2d19 Mon Sep 17 00:00:00 2001 From: Jesse Talavera-Greenberg Date: Mon, 10 Jun 2019 18:02:12 -0400 Subject: [PATCH 2/7] refactor(decorators): simplify logic in the three new decorators Remove unneeded local variables, and let the three new decorators return `TaskStatus.Failure` if they have no child --- .../Runtime/Decorators/RepeatForever.cs | 2 +- .../Runtime/Decorators/RepeatUntilFailure.cs | 14 +++----------- .../Runtime/Decorators/RepeatUntilSuccess.cs | 12 ++---------- 3 files changed, 6 insertions(+), 22 deletions(-) diff --git a/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatForever.cs b/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatForever.cs index 2790f9b8..35cd8903 100644 --- a/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatForever.cs +++ b/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatForever.cs @@ -5,7 +5,7 @@ namespace CleverCrow.Fluid.BTs.Decorators { public class RepeatForever : DecoratorBase { protected override TaskStatus OnUpdate () { - Child?.Update(); + Child.Update(); return TaskStatus.Continue; } } diff --git a/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilFailure.cs b/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilFailure.cs index 29a25491..f89e62c1 100644 --- a/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilFailure.cs +++ b/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilFailure.cs @@ -5,19 +5,11 @@ namespace CleverCrow.Fluid.BTs.Decorators { public class RepeatUntilFailure : DecoratorBase { protected override TaskStatus OnUpdate () { - if (Child == null) { + if (Child.Update() == TaskStatus.Failure) { return TaskStatus.Failure; } - - var childStatus = Child.Update(); - var status = childStatus; - - if (status == TaskStatus.Failure) { - return TaskStatus.Failure; - } - else { - return TaskStatus.Continue; - } + + return TaskStatus.Continue; } } } \ No newline at end of file diff --git a/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilSuccess.cs b/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilSuccess.cs index ba856812..e141f058 100644 --- a/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilSuccess.cs +++ b/Assets/FluidBehaviorTree/Runtime/Decorators/RepeatUntilSuccess.cs @@ -5,19 +5,11 @@ namespace CleverCrow.Fluid.BTs.Decorators { public class RepeatUntilSuccess : DecoratorBase { protected override TaskStatus OnUpdate () { - if (Child == null) { + if (Child.Update() == TaskStatus.Success) { return TaskStatus.Success; } - var childStatus = Child.Update(); - var status = childStatus; - - if (status == TaskStatus.Success) { - return TaskStatus.Success; - } - else { - return TaskStatus.Continue; - } + return TaskStatus.Continue; } } } \ No newline at end of file From 4702aef61e5e5ba56cea47ee346b03b9d4affb78 Mon Sep 17 00:00:00 2001 From: Jesse Talavera-Greenberg Date: Mon, 10 Jun 2019 18:17:08 -0400 Subject: [PATCH 3/7] test(decorators): move a repeater test to the DecoratorTest class Now that DecoratorBase returns failure if it has no child, Does_not_crash_if_no_child can be moved to the base decorator tests --- .../Tests/Editor/Decorators/DecoratorTest.cs | 9 ++++++++- .../Tests/Editor/Decorators/RepeatForeverTest.cs | 7 ------- .../Tests/Editor/Decorators/RepeatUntilFailureTest.cs | 7 ------- .../Tests/Editor/Decorators/RepeatUntilSuccessTest.cs | 7 ------- 4 files changed, 8 insertions(+), 22 deletions(-) diff --git a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/DecoratorTest.cs b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/DecoratorTest.cs index cd532bcc..cfb3655e 100644 --- a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/DecoratorTest.cs +++ b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/DecoratorTest.cs @@ -1,4 +1,4 @@ -using CleverCrow.Fluid.BTs.Decorators; +using CleverCrow.Fluid.BTs.Decorators; using CleverCrow.Fluid.BTs.Tasks; using NSubstitute; using NUnit.Framework; @@ -50,6 +50,13 @@ public void It_should_return_failure_if_a_child_is_missing () { _decorator.Children.RemoveAt(0); Assert.AreEqual(TaskStatus.Failure, _decorator.Update()); } + + [Test] + public void Does_not_crash_if_no_child () { + _decorator.Children.RemoveAt(0); + + Assert.DoesNotThrow(() => _decorator.Update()); + } } public class EndMethod : DecoratorTest { diff --git a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatForeverTest.cs b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatForeverTest.cs index 9a65e0d5..feb5414f 100644 --- a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatForeverTest.cs +++ b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatForeverTest.cs @@ -28,13 +28,6 @@ public void Returns_continue_on_child_continue () { 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/RepeatUntilFailureTest.cs b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilFailureTest.cs index 42b9b97e..e7d84bba 100644 --- a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilFailureTest.cs +++ b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilFailureTest.cs @@ -28,13 +28,6 @@ public void Returns_continue_on_child_continue () { 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/RepeatUntilSuccessTest.cs b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilSuccessTest.cs index 56749a5f..27c5250b 100644 --- a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilSuccessTest.cs +++ b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilSuccessTest.cs @@ -28,13 +28,6 @@ public void Returns_continue_on_child_continue () { 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 From 40067a5c3250cb52816f5df989d38efa4e42c0c0 Mon Sep 17 00:00:00 2001 From: Jesse Talavera-Greenberg Date: Mon, 10 Jun 2019 18:18:18 -0400 Subject: [PATCH 4/7] test(decorators): move repeater creation to a [SetUp] method --- .../Tests/Editor/Decorators/RepeatForeverTest.cs | 10 +++++++--- .../Tests/Editor/Decorators/RepeatUntilFailureTest.cs | 10 +++++++--- .../Tests/Editor/Decorators/RepeatUntilSuccessTest.cs | 10 +++++++--- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatForeverTest.cs b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatForeverTest.cs index feb5414f..662db1ef 100644 --- a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatForeverTest.cs +++ b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatForeverTest.cs @@ -5,9 +5,15 @@ namespace CleverCrow.Fluid.BTs.Testing { public class RepeatForeverTest { public class UpdateMethod { + private RepeatForever repeater; + + [SetUp] + public void Setup_repeater () { + repeater = new RepeatForever(); + } + [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()); @@ -15,7 +21,6 @@ public void Returns_continue_on_child_failure () { [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()); @@ -23,7 +28,6 @@ public void Returns_continue_on_child_success () { [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()); diff --git a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilFailureTest.cs b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilFailureTest.cs index e7d84bba..c24cdca2 100644 --- a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilFailureTest.cs +++ b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilFailureTest.cs @@ -5,9 +5,15 @@ namespace CleverCrow.Fluid.BTs.Testing { public class RepeatUntilFailureTest { public class UpdateMethod { + private RepeatUntilFailure repeater; + + [SetUp] + public void Setup_repeater () { + repeater = new RepeatUntilFailure(); + } + [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()); @@ -15,7 +21,6 @@ public void Returns_failure_on_child_failure () { [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()); @@ -23,7 +28,6 @@ public void Returns_continue_on_child_success () { [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()); diff --git a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilSuccessTest.cs b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilSuccessTest.cs index 27c5250b..ba030112 100644 --- a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilSuccessTest.cs +++ b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/RepeatUntilSuccessTest.cs @@ -5,9 +5,15 @@ namespace CleverCrow.Fluid.BTs.Testing { public class RepeatUntilSuccessTest { public class UpdateMethod { + private RepeatUntilSuccess repeater; + + [SetUp] + public void Setup_repeater () { + repeater = new RepeatUntilSuccess(); + } + [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()); @@ -15,7 +21,6 @@ public void Returns_continue_on_child_failure () { [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()); @@ -23,7 +28,6 @@ public void Returns_success_on_child_success () { [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()); From 1fecd28bfb8b92aa81eac824bc489e95f3897268 Mon Sep 17 00:00:00 2001 From: Jesse Talavera-Greenberg Date: Mon, 10 Jun 2019 18:29:02 -0400 Subject: [PATCH 5/7] docs(decorators): document the new repeater decorators Adds documentation for RepeatForever, RepeatUntilSuccess, and RepeatUntilFailure to README.md --- README.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/README.md b/README.md index 9f8aec86..d809f566 100644 --- a/README.md +++ b/README.md @@ -148,6 +148,9 @@ with units who attempt to capture the flag while grabbing power ups to try and g - [Inverter](#inverter) - [ReturnSuccess](#returnsuccess) - [ReturnFailure](#returnfailure) + - [RepeatForever](#repeatforever) + - [RepeatUntilFailure](#repeatuntilfailure) + - [RepeatUntilSuccess](#repeatuntilsuccess) * [Creating Reusable Behavior Trees](#creating-reusable-behavior-trees) * [Creating Custom Reusable Nodes](#creating-custom-reusable-nodes) + [Your First Custom Node and Tree](#your-first-custom-node-and-extension) @@ -356,6 +359,43 @@ Does not change `TaskStatus.Continue`. .End() ``` +#### RepeatForever + +Return `TaskStatus.Continue` regardless of what status the child returns. This decorator (and all descendent +tasks) can be interrupted by calling `BehaviorTree.Reset()`. + +```C# +.Sequence() + .RepeatForever() + .Do(() => { return TaskStatus.Success; }) + .End() +.End() +``` + +#### RepeatUntilFailure + +Return `TaskStatus.Failure` if the child returns `TaskStatus.Failure`, otherwise it returns `TaskStatus.Continue`. + +```C# +.Sequence() + .RepeatUntilFailure() + .Do(() => { return TaskStatus.Success; }) + .End() +.End() +``` + +#### RepeatUntilSuccess + +Return `TaskStatus.Success` if the child returns `TaskStatus.Success`, otherwise it returns `TaskStatus.Continue`. + +```C# +.Sequence() + .RepeatUntilSuccess() + .Do(() => { return TaskStatus.Success; }) + .End() +.End() +``` + ## Creating Reusable Behavior Trees Trees can be combined with just a few line of code. This allows you to create injectable behavior trees that bundles different From 8fbcc0d86c4703dc2ffb13cbc394ab9c37e3f87b Mon Sep 17 00:00:00 2001 From: Jesse Talavera-Greenberg Date: Mon, 10 Jun 2019 19:07:46 -0400 Subject: [PATCH 6/7] style(visualizer): add icons for the new decorators Add icons for representing RepeatForever, RepeatUntilFailure, and RepeatUntilSuccess in the visualizer --- .../Editor/Icons/Tasks/EventAvailable.png | Bin 0 -> 279 bytes .../Icons/Tasks/EventAvailable.png.meta | 112 ++++++++++++++++++ .../Editor/Icons/Tasks/EventBusy.png | Bin 0 -> 317 bytes .../Editor/Icons/Tasks/EventBusy.png.meta | 112 ++++++++++++++++++ .../Editor/Icons/Tasks/Repeat.png | Bin 0 -> 224 bytes .../Editor/Icons/Tasks/Repeat.png.meta | 112 ++++++++++++++++++ .../Runtime/Decorators/RepeatForever.cs | 2 + .../Runtime/Decorators/RepeatUntilFailure.cs | 2 + .../Runtime/Decorators/RepeatUntilSuccess.cs | 2 + 9 files changed, 342 insertions(+) create mode 100644 Assets/FluidBehaviorTree/Editor/Icons/Tasks/EventAvailable.png create mode 100644 Assets/FluidBehaviorTree/Editor/Icons/Tasks/EventAvailable.png.meta create mode 100644 Assets/FluidBehaviorTree/Editor/Icons/Tasks/EventBusy.png create mode 100644 Assets/FluidBehaviorTree/Editor/Icons/Tasks/EventBusy.png.meta create mode 100644 Assets/FluidBehaviorTree/Editor/Icons/Tasks/Repeat.png create mode 100644 Assets/FluidBehaviorTree/Editor/Icons/Tasks/Repeat.png.meta diff --git a/Assets/FluidBehaviorTree/Editor/Icons/Tasks/EventAvailable.png b/Assets/FluidBehaviorTree/Editor/Icons/Tasks/EventAvailable.png new file mode 100644 index 0000000000000000000000000000000000000000..ae9c8daa3945391f0a23a9fe0bad9a548163776c GIT binary patch literal 279 zcmV+y0qFjTP)Ds=Qc`xCRVjC1R9I~8M18^;Ey%670%b9|2%AOB(NQO)mWH~7)YDL(kn9ga);NZJ1P#6s zqRE`>+YoJzz$h3J<^(Lsy@G~n(99}f+#xdbDazJKn7lE*&=lBEN|>`S-cXeTu%)aR zKS-$km01hp0I4CNVy0kBASBdIm>@`^B1|ZxN*{`dTVNe;L0qJv1|czJ--y9w3oDQUk7oha$F3Y{w{ z{y`{)%)~nA;0mKCPe|XW#XIJa P00000NkvXXu0mjf=5T&s literal 0 HcmV?d00001 diff --git a/Assets/FluidBehaviorTree/Editor/Icons/Tasks/EventBusy.png.meta b/Assets/FluidBehaviorTree/Editor/Icons/Tasks/EventBusy.png.meta new file mode 100644 index 00000000..77b5cf19 --- /dev/null +++ b/Assets/FluidBehaviorTree/Editor/Icons/Tasks/EventBusy.png.meta @@ -0,0 +1,112 @@ +fileFormatVersion: 2 +guid: 94595d6a4757a0ca2a7dd224e672524d +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 10 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: WebGL + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/FluidBehaviorTree/Editor/Icons/Tasks/Repeat.png b/Assets/FluidBehaviorTree/Editor/Icons/Tasks/Repeat.png new file mode 100644 index 0000000000000000000000000000000000000000..d2b0b8f6cf5d6e413b08ab372646dbb1e621651f GIT binary patch literal 224 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBmV3H5hEy;nNw7AQy?(&rAi=R{ zMQz0f(P%-P6z|QVinTS|68XZC{J#~yv(MJ4T*=Ir@K<<6Lv&!IKo?hYj>rb))_Oe# zX;u;Wr7LVQ7-lo?`ZH1U7~|B+m8`<7oNBy6J`yEONi_jxkv-L?E`EKn+@3FiwNJ*w z&^*9$LehyQk;$x@X|KL7uHmWU%V1`!oUll(Z%v8euN6^?G`$=Xr!*Z}QG9XNJH~5S W5vr Date: Mon, 10 Jun 2019 18:06:58 -0600 Subject: [PATCH 7/7] refactor(decorators): removed duplicate test --- .../Tests/Editor/Decorators/DecoratorTest.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/DecoratorTest.cs b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/DecoratorTest.cs index cfb3655e..cb3fc8aa 100644 --- a/Assets/FluidBehaviorTree/Tests/Editor/Decorators/DecoratorTest.cs +++ b/Assets/FluidBehaviorTree/Tests/Editor/Decorators/DecoratorTest.cs @@ -50,13 +50,6 @@ public void It_should_return_failure_if_a_child_is_missing () { _decorator.Children.RemoveAt(0); Assert.AreEqual(TaskStatus.Failure, _decorator.Update()); } - - [Test] - public void Does_not_crash_if_no_child () { - _decorator.Children.RemoveAt(0); - - Assert.DoesNotThrow(() => _decorator.Update()); - } } public class EndMethod : DecoratorTest {