Skip to content

Commit f50ea64

Browse files
committed
Added tests for selector conditional aborts on composites
1 parent f8b0ea0 commit f50ea64

File tree

3 files changed

+79
-26
lines changed

3 files changed

+79
-26
lines changed

Assets/FluidBehaviorTree/Editor/Testing/ParentTasks/SelectorTest.cs

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -225,57 +225,90 @@ public void Returns_continue_if_nested_sequence_condition_is_followed_by_failure
225225
}
226226

227227
public class ConditionalAbortLowerPrioritySelector {
228-
public class AbortTypeSelector : UpdateMethod {
229-
[Test]
230-
public void Revaluates_from_where_a_conditional_abort_goes_from_failure_to_success () {
231-
var sequenceSub = new Sequence();
228+
public class AbortTypeSequence : UpdateMethod {
229+
private Sequence sequenceSub;
230+
private ITask childFailure;
231+
private ITask endTask;
232+
233+
[SetUp]
234+
public void SetDefaults () {
235+
sequenceSub = new Sequence();
232236
sequenceSub.AbortType = AbortType.LowerPriority;
233-
234-
var childFailure = A.TaskStub()
237+
238+
childFailure = A.TaskStub()
235239
.WithAbortConditionSelf(true)
236240
.WithUpdateStatus(TaskStatus.Failure)
237241
.Build();
238242
sequenceSub.AddChild(childFailure);
239243
sequenceSub.AddChild(A.TaskStub().Build());
240244

245+
endTask = A.TaskStub().WithUpdateStatus(TaskStatus.Continue).Build();
246+
}
247+
248+
[Test]
249+
public void Revaluates_from_where_a_conditional_abort_goes_from_failure_to_success () {
241250
_selector
242251
.AddChild(sequenceSub)
243-
.AddChild(A.TaskStub().Build());
252+
.AddChild(endTask);
244253

245254
_selector.Update();
246255
childFailure.Update().Returns(TaskStatus.Success);
247256
_selector.Update();
248-
257+
249258
CheckUpdateCalls(sequenceSub, new List<int>{3, 1});
250259
CheckUpdateCalls(_selector, new List<int>{-1, 1});
251260
}
252261

253262
[Test]
254263
public void Returns_success_when_a_conditional_abort_goes_from_failure_to_success () {
255-
var sequenceSub = new Sequence();
256-
sequenceSub.AbortType = AbortType.LowerPriority;
257-
258-
var childFailure = A.TaskStub()
264+
_selector
265+
.AddChild(sequenceSub)
266+
.AddChild(endTask);
267+
268+
Assert.AreEqual(TaskStatus.Continue, _selector.Update());
269+
childFailure.Update().Returns(TaskStatus.Success);
270+
Assert.AreEqual(TaskStatus.Success, _selector.Update());
271+
}
272+
273+
[Test]
274+
public void Begins_revaluation_from_origin_of_the_conditional_abort () {
275+
_selector
276+
.AddChild(A.TaskStub().WithUpdateStatus(TaskStatus.Failure).Build())
277+
.AddChild(sequenceSub)
278+
.AddChild(endTask);
279+
280+
_selector.Update();
281+
childFailure.Update().Returns(TaskStatus.Success);
282+
_selector.Update();
283+
284+
CheckUpdateCalls(sequenceSub, new List<int>{3, 1});
285+
CheckUpdateCalls(_selector, new List<int>{1, -1, 1});
286+
}
287+
288+
[Test]
289+
public void Keeps_conditional_aborts_before_the_revaluated_abort () {
290+
var failSequence = new Sequence();
291+
failSequence.AbortType = AbortType.LowerPriority;
292+
failSequence.AddChild(A.TaskStub()
259293
.WithAbortConditionSelf(true)
260294
.WithUpdateStatus(TaskStatus.Failure)
261-
.Build();
262-
sequenceSub.AddChild(childFailure);
263-
sequenceSub.AddChild(A.TaskStub().Build());
295+
.Build());
264296

265297
_selector
298+
.AddChild(failSequence)
266299
.AddChild(sequenceSub)
267-
.AddChild(A.TaskStub().Build());
300+
.AddChild(endTask);
268301

269302
_selector.Update();
270303
childFailure.Update().Returns(TaskStatus.Success);
271-
272-
Assert.AreEqual(TaskStatus.Success, _selector.Update());
304+
_selector.Update();
305+
306+
Assert.AreEqual(1, _selector.AbortLowerPriorities.Count);
307+
Assert.IsTrue(_selector.AbortLowerPriorities.Contains(failSequence.children[0]));
273308
}
274-
275-
// @TODO Verify nested conditional abort runs from correct starting point (currently tests all children)
276309
}
277310

278-
public class AbortTypeComposite {
311+
public class AbortTypeSelector {
279312
// @TODO Add composite abort type tests
280313
}
281314
}

Assets/FluidBehaviorTree/Scripts/TaskParents/Composites/CompositeBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace Adnc.FluidBT.TaskParents {
55
public abstract class CompositeBase : TaskParentBase {
66
public ITask SelfAbortTask { get; protected set; }
77
public int ChildIndex { get; protected set; }
8-
public List<ITask> AbortLowerPriorities { get; } = new List<ITask>();
8+
public List<ITask> AbortLowerPriorities { get; protected set; } = new List<ITask>();
99

1010
public override ITaskParent AddChild (ITask child) {
1111
if (children.Count == 0 && child.Enabled) {

Assets/FluidBehaviorTree/Scripts/TaskParents/Composites/Selector.cs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,31 @@
1-
using Adnc.FluidBT.Tasks;
1+
using System.Collections.Generic;
2+
using Adnc.FluidBT.Tasks;
23

34
namespace Adnc.FluidBT.TaskParents {
45
public class Selector : CompositeBase {
6+
List<int> _lowerPriorityIndices = new List<int>();
7+
58
protected override TaskStatus OnUpdate () {
9+
// @TODO Consider abort self being able to revaluate any immediate child condition that has already been run
610
if (AbortSelf(TaskStatus.Success)) {
711
return Update();
812
}
9-
13+
1014
foreach (var abort in AbortLowerPriorities) {
1115
if (abort.GetAbortStatus() != TaskStatus.Success) continue;
1216
children[ChildIndex].End();
17+
18+
var abortIndex = AbortLowerPriorities.IndexOf(abort);
19+
var restoreIndex = _lowerPriorityIndices[abortIndex];
20+
var restoreAborts = AbortLowerPriorities.GetRange(0, abortIndex);
21+
var restoreAbortIndices = _lowerPriorityIndices.GetRange(0, abortIndex);
22+
1323
Reset();
14-
// @TODO Should use the abort's index to figure out what to revaluate (should not run entire branch)
24+
25+
ChildIndex = restoreIndex;
26+
AbortLowerPriorities = restoreAborts;
27+
_lowerPriorityIndices = restoreAbortIndices;
28+
1529
return Update();
1630
}
1731

@@ -28,8 +42,8 @@ protected override TaskStatus OnUpdate () {
2842
if (child.IsLowerPriority) {
2943
var abortCondition = child.GetAbortCondition();
3044
if (abortCondition != null) {
31-
// @TODO Abort must include the current child index
3245
AbortLowerPriorities.Add(abortCondition);
46+
_lowerPriorityIndices.Add(i);
3347
}
3448
}
3549

@@ -43,6 +57,12 @@ public override ITask GetAbortCondition () {
4357
return this;
4458
}
4559

60+
public override void Reset (bool hardReset = false) {
61+
_lowerPriorityIndices.Clear();
62+
63+
base.Reset(hardReset);
64+
}
65+
4666
// @TODO Cache the abort children on first run since they will never change
4767
public override TaskStatus GetAbortStatus () {
4868
foreach (var child in children) {

0 commit comments

Comments
 (0)