Skip to content

Commit 995e7f0

Browse files
committed
Decorator generic added to build tree commands
1 parent 8e39026 commit 995e7f0

File tree

12 files changed

+152
-72
lines changed

12 files changed

+152
-72
lines changed

Assets/FluidBehaviorTree/Scripts/BehaviorTree/BehaviorTreeBuilder.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using Adnc.FluidBT.Decorators;
34
using Adnc.FluidBT.TaskParents;
45
using Adnc.FluidBT.TaskParents.Composites;
56
using Adnc.FluidBT.Tasks;
@@ -30,6 +31,22 @@ public BehaviorTreeBuilder (GameObject owner) {
3031

3132
return this;
3233
}
34+
35+
public BehaviorTreeBuilder Decorator (string name, Func<ITask, TaskStatus> logic) {
36+
var decorator = new DecoratorGeneric {
37+
updateLogic = logic,
38+
Name = name
39+
};
40+
41+
_tree.AddNode(Pointer, decorator);
42+
_pointer.Add(decorator);
43+
44+
return this;
45+
}
46+
47+
public BehaviorTreeBuilder Decorator (Func<ITask, TaskStatus> logic) {
48+
return Decorator("decorator", logic);
49+
}
3350

3451
public BehaviorTreeBuilder Sequence (string name = "sequence") {
3552
return ParentTask<Sequence>(name);

Assets/FluidBehaviorTree/Scripts/BehaviorTree/Editor/BehaviorTreeBuilderTest.cs

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
using Adnc.FluidBT.TaskParents.Composites;
1+
using Adnc.FluidBT.Decorators;
2+
using Adnc.FluidBT.TaskParents.Composites;
23
using Adnc.FluidBT.Tasks;
34
using Adnc.FluidBT.Tasks.Actions;
45
using NUnit.Framework;
6+
using UnityEngine;
57

68
namespace Adnc.FluidBT.Trees.Testing {
79
public class BehaviorTreeBuilderTest {
@@ -239,5 +241,77 @@ public void It_should_add_an_action_without_a_name () {
239241
Assert.AreEqual(1, _invokeCount);
240242
}
241243
}
244+
245+
public class DecoratorMethod : BehaviorTreeBuilderTest {
246+
[Test]
247+
public void It_should_add_a_decorator () {
248+
var tree = _builder
249+
.Decorator("decorator", child => {
250+
_invokeCount++;
251+
child.Update();
252+
return TaskStatus.Failure;
253+
})
254+
.Do("action", () => {
255+
_invokeCount++;
256+
return TaskStatus.Success;
257+
})
258+
.Build();
259+
260+
var decorator = tree.Root.Children[0] as DecoratorGeneric;
261+
262+
Assert.IsNotNull(decorator);
263+
Assert.AreEqual(TaskStatus.Failure, tree.Tick());
264+
Assert.AreEqual(2, _invokeCount);
265+
}
266+
267+
[Test]
268+
public void It_should_add_a_decorator_without_a_name () {
269+
var tree = _builder
270+
.Decorator(child => {
271+
_invokeCount++;
272+
child.Update();
273+
return TaskStatus.Failure;
274+
})
275+
.Do("action", () => {
276+
_invokeCount++;
277+
return TaskStatus.Success;
278+
})
279+
.Build();
280+
281+
var decorator = tree.Root.Children[0] as DecoratorGeneric;
282+
283+
Assert.IsNotNull(decorator);
284+
Assert.AreEqual(TaskStatus.Failure, tree.Tick());
285+
Assert.AreEqual(2, _invokeCount);
286+
}
287+
288+
[Test]
289+
public void It_should_move_to_the_next_node_on_End () {
290+
var tree = _builder
291+
.Sequence()
292+
.Decorator(child => {
293+
_invokeCount++;
294+
child.Update();
295+
return TaskStatus.Success;
296+
})
297+
.Do("action", () => {
298+
_invokeCount++;
299+
return TaskStatus.Success;
300+
})
301+
.End()
302+
.Do("action", () => {
303+
_invokeCount++;
304+
return TaskStatus.Success;
305+
})
306+
.Build();
307+
308+
var sequence = tree.Root.Children[0] as Sequence;
309+
var decorator = sequence.Children[0] as DecoratorGeneric;
310+
311+
Assert.IsNotNull(decorator);
312+
Assert.AreEqual(TaskStatus.Success, tree.Tick());
313+
Assert.AreEqual(3, _invokeCount);
314+
}
315+
}
242316
}
243317
}
Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1-
using Adnc.FluidBT.Tasks;
1+
using System.Collections.Generic;
2+
using Adnc.FluidBT.TaskParents;
3+
using Adnc.FluidBT.Tasks;
24
using Adnc.FluidBT.Trees;
35
using UnityEngine;
46

57
namespace Adnc.FluidBT.Decorators {
6-
public abstract class DecoratorBase : ITask {
7-
public ITask child;
8+
public abstract class DecoratorBase : ITaskParent {
9+
public List<ITask> Children { get; } = new List<ITask>();
810

9-
private bool _enabled = true;
1011
public string Name { get; set; }
1112

12-
public bool Enabled {
13-
get { return child != null && child.Enabled && _enabled; }
14-
set { _enabled = value; }
15-
}
13+
public bool Enabled { get; set; } = true;
1614

1715
public GameObject Owner { get; set; }
1816
public BehaviorTree ParentTree { get; set; }
1917
public TaskStatus LastStatus { get; private set; }
2018

19+
public ITask Child => Children.Count > 0 ? Children[0] : null;
20+
2121
public TaskStatus Update () {
2222
var status = OnUpdate();
2323
LastStatus = status;
@@ -28,10 +28,18 @@ public TaskStatus Update () {
2828
protected abstract TaskStatus OnUpdate ();
2929

3030
public void End () {
31-
child.End();
31+
Child.End();
3232
}
3333

3434
public void Reset (bool hardReset = false) {
3535
}
36+
37+
public ITaskParent AddChild (ITask child) {
38+
if (Child == null) {
39+
Children.Add(child);
40+
}
41+
42+
return this;
43+
}
3644
}
3745
}

Assets/FluidBehaviorTree/Scripts/Decorators/DecoratorGeneric.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,18 @@
33

44
namespace Adnc.FluidBT.Decorators {
55
public class DecoratorGeneric : DecoratorBase {
6-
public Func<DecoratorBase, TaskStatus> updateLogic;
6+
public Func<ITask, TaskStatus> updateLogic;
77

88
protected override TaskStatus OnUpdate () {
9+
if (Child == null) {
10+
return TaskStatus.Success;
11+
}
12+
913
if (updateLogic != null) {
10-
return updateLogic(this);
14+
return updateLogic(Child);
1115
}
1216

13-
return child.Update();
17+
return Child.Update();
1418
}
1519
}
1620
}

Assets/FluidBehaviorTree/Scripts/Decorators/Editor/DecoratorGenericTest.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,23 @@ public class UpdateMethod {
88
[Test]
99
public void Can_invert_status_of_child () {
1010
var task = new DecoratorGeneric {
11-
child = A.TaskStub().Build(),
12-
updateLogic = (dec) => {
13-
if (dec.child.Update() == TaskStatus.Success) {
11+
updateLogic = (child) => {
12+
if (child.Update() == TaskStatus.Success) {
1413
return TaskStatus.Failure;
1514
}
1615

1716
return TaskStatus.Success;
1817
}
1918
};
19+
task.AddChild(A.TaskStub().Build());
2020

2121
Assert.AreEqual(TaskStatus.Failure, task.Update());
2222
}
2323

2424
[Test]
2525
public void Returns_child_status_without_update_logic () {
26-
var task = new DecoratorGeneric {
27-
child = A.TaskStub().Build()
28-
};
26+
var task = new DecoratorGeneric();
27+
task.AddChild(A.TaskStub().Build());
2928

3029
Assert.AreEqual(TaskStatus.Success, task.Update());
3130
}

Assets/FluidBehaviorTree/Scripts/Decorators/Editor/DecoratorTest.cs

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,16 @@ protected override TaskStatus OnUpdate () {
1616
public class EnabledProperty {
1717
[Test]
1818
public void Returns_true_if_child_is_set () {
19-
var decorator = new DecoratorExample { child = A.TaskStub().Build() };
20-
21-
Assert.IsTrue(decorator.Enabled);
22-
}
23-
24-
[Test]
25-
public void Returns_false_if_child_is_not_set () {
2619
var decorator = new DecoratorExample();
27-
28-
Assert.IsFalse(decorator.Enabled);
29-
}
30-
31-
[Test]
32-
public void Returns_false_if_child_is_disabled () {
33-
var decorator = new DecoratorExample { child = A.TaskStub().Build() };
34-
decorator.child.Enabled.Returns(false);
35-
36-
Assert.IsFalse(decorator.Enabled);
20+
decorator.AddChild(A.TaskStub().Build());
21+
22+
Assert.IsTrue(decorator.Enabled);
3723
}
3824

3925
[Test]
4026
public void Returns_false_if_child_is_set_but_set_to_false () {
41-
var decorator = new DecoratorExample { child = A.TaskStub().Build() };
27+
var decorator = new DecoratorExample();
28+
decorator.AddChild(A.TaskStub().Build());
4229
decorator.Enabled = false;
4330

4431
Assert.IsFalse(decorator.Enabled);
@@ -60,12 +47,12 @@ public void Sets_LastUpdate_to_returned_status_value () {
6047
public class EndMethod {
6148
[Test]
6249
public void Calls_end_on_child () {
63-
var task = A.TaskStub().Build();
64-
var decorator = new DecoratorExample { child = task };
50+
var decorator = new DecoratorExample();
51+
decorator.AddChild(A.TaskStub().Build());
6552

6653
decorator.End();
6754

68-
task.Received(1).End();
55+
decorator.Child.Received(1).End();
6956
}
7057
}
7158
}

Assets/FluidBehaviorTree/Scripts/Decorators/Editor/InverterTest.cs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,24 @@ public class InverterTest {
77
public class UpdateMethod {
88
[Test]
99
public void Returns_failure_when_child_returns_success () {
10-
var inverter = new Inverter {
11-
child = A.TaskStub().Build()
12-
};
10+
var inverter = new Inverter();
11+
inverter.AddChild(A.TaskStub().Build());
1312

1413
Assert.AreEqual(TaskStatus.Failure, inverter.Update());
1514
}
1615

1716
[Test]
1817
public void Returns_true_when_child_returns_false () {
19-
var inverter = new Inverter {
20-
child = A.TaskStub().WithUpdateStatus(TaskStatus.Failure).Build()
21-
};
18+
var inverter = new Inverter();
19+
inverter.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Failure).Build());
2220

2321
Assert.AreEqual(TaskStatus.Success, inverter.Update());
2422
}
2523

2624
[Test]
2725
public void Returns_continue_when_child_returns_continue () {
28-
var inverter = new Inverter {
29-
child = A.TaskStub().WithUpdateStatus(TaskStatus.Continue).Build()
30-
};
26+
var inverter = new Inverter();
27+
inverter.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Continue).Build());
3128

3229
Assert.AreEqual(TaskStatus.Continue, inverter.Update());
3330
}

Assets/FluidBehaviorTree/Scripts/Decorators/Editor/ReturnFailureTest.cs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,25 @@ public class ReturnFailureTest {
88
public class UpdateMethod {
99
[Test]
1010
public void Returns_failure_on_child_failure () {
11-
var returnSuccess = new ReturnFailure {
12-
child = A.TaskStub().WithUpdateStatus(TaskStatus.Failure).Build()
13-
};
11+
var returnSuccess = new ReturnFailure();
12+
returnSuccess.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Failure).Build());
1413

1514
Assert.AreEqual(TaskStatus.Failure, returnSuccess.Update());
1615
}
1716

1817
[Test]
1918
public void Returns_failure_on_child_success () {
20-
var returnSuccess = new ReturnFailure {
21-
child = A.TaskStub().WithUpdateStatus(TaskStatus.Success).Build()
22-
};
19+
var returnSuccess = new ReturnFailure();
20+
returnSuccess.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Success).Build());
2321

2422
Assert.AreEqual(TaskStatus.Failure, returnSuccess.Update());
2523
}
2624

2725
[Test]
2826
public void Returns_continue_on_child_continue () {
29-
var returnSuccess = new ReturnFailure {
30-
child = A.TaskStub().WithUpdateStatus(TaskStatus.Continue).Build()
31-
};
32-
27+
var returnSuccess = new ReturnFailure();
28+
returnSuccess.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Continue).Build());
29+
3330
Assert.AreEqual(TaskStatus.Continue, returnSuccess.Update());
3431
}
3532
}

Assets/FluidBehaviorTree/Scripts/Decorators/Editor/ReturnSuccessTest.cs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,24 @@ public class ReturnSuccessTest {
88
public class UpdateMethod {
99
[Test]
1010
public void Returns_success_on_child_failure () {
11-
var returnSuccess = new ReturnSuccess {
12-
child = A.TaskStub().WithUpdateStatus(TaskStatus.Failure).Build()
13-
};
11+
var returnSuccess = new ReturnSuccess();
12+
returnSuccess.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Failure).Build());
1413

1514
Assert.AreEqual(TaskStatus.Success, returnSuccess.Update());
1615
}
1716

1817
[Test]
1918
public void Returns_success_on_child_success () {
20-
var returnSuccess = new ReturnSuccess {
21-
child = A.TaskStub().WithUpdateStatus(TaskStatus.Success).Build()
22-
};
19+
var returnSuccess = new ReturnSuccess();
20+
returnSuccess.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Success).Build());
2321

2422
Assert.AreEqual(TaskStatus.Success, returnSuccess.Update());
2523
}
2624

2725
[Test]
2826
public void Returns_continue_on_child_continue () {
29-
var returnSuccess = new ReturnSuccess {
30-
child = A.TaskStub().WithUpdateStatus(TaskStatus.Continue).Build()
31-
};
27+
var returnSuccess = new ReturnSuccess();
28+
returnSuccess.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Continue).Build());
3229

3330
Assert.AreEqual(TaskStatus.Continue, returnSuccess.Update());
3431
}

Assets/FluidBehaviorTree/Scripts/Decorators/Inverter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
namespace Adnc.FluidBT.Decorators {
44
public class Inverter : DecoratorBase {
55
protected override TaskStatus OnUpdate () {
6-
if (child == null) {
6+
if (Child == null) {
77
return TaskStatus.Success;
88
}
99

10-
var childStatus = child.Update();
10+
var childStatus = Child.Update();
1111
var status = childStatus;
1212

1313
switch (childStatus) {

0 commit comments

Comments
 (0)