Skip to content

Commit 57b283b

Browse files
committed
Docs changed to demonstrate new extension system
1 parent 708bdda commit 57b283b

File tree

4 files changed

+54
-143
lines changed

4 files changed

+54
-143
lines changed

Assets/FluidBehaviorTree/Scripts/BehaviorTree/Builder/BehaviorTreeBuilder.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,22 @@ public BehaviorTreeBuilder (GameObject owner) {
2626

2727
public BehaviorTreeBuilder ParentTask<P> (string name) where P : ITaskParent, new() {
2828
var parent = new P { Name = name };
29-
AddNode(parent);
30-
_pointers.Add(parent);
3129

32-
return this;
30+
return AddNodeWithPointer(parent);
3331
}
3432

3533
public BehaviorTreeBuilder Decorator (string name, Func<ITask, TaskStatus> logic) {
3634
var decorator = new DecoratorGeneric {
3735
updateLogic = logic,
3836
Name = name
3937
};
40-
41-
AddNode(decorator);
42-
_pointers.Add(decorator);
38+
39+
return AddNodeWithPointer(decorator);
40+
}
41+
42+
public BehaviorTreeBuilder AddNodeWithPointer (ITaskParent task) {
43+
AddNode(task);
44+
_pointers.Add(task);
4345

4446
return this;
4547
}

Assets/FluidBehaviorTree/Scripts/BehaviorTree/Builder/Editor/BehaviorTreeBuilderExtensionActionTest.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@
66
namespace Adnc.FluidBT.Trees.Testing {
77
public static class BehaviorTreeExtensionActionExamples {
88
public static BehaviorTreeBuilder ExampleAction (this BehaviorTreeBuilder builder, string name, Action callback) {
9-
builder.AddNode(new BehaviorTreeBuilderExtensionActionTest.ExtensionAction {
9+
return builder.AddNode(new BehaviorTreeBuilderExtensionActionTest.ExtensionAction {
1010
Name = name,
1111
callback = callback,
1212
});
13-
14-
return builder;
1513
}
1614
}
1715

Assets/FluidBehaviorTree/Scripts/BehaviorTree/Builder/Editor/BehaviorTreeBuilderExtensionCompositesTest.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ public static BehaviorTreeBuilder CustomSequence (this BehaviorTreeBuilder build
1010
}
1111

1212
public class BehaviorTreeExtensionCompositesTest {
13-
public class ExtensionComposite : CompositeBase {
14-
}
15-
1613
[Test]
1714
public void It_should_run_the_custom_action () {
1815
var result = false;

README.md

Lines changed: 45 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ https://www.youtube.com/watch?v=YCMvUCxzWz8
8989
- [ReturnFailure](#returnfailure)
9090
* [Creating Reusable Behavior Trees](#creating-reusable-behavior-trees)
9191
* [Creating Custom Reusable Nodes](#creating-custom-reusable-nodes)
92-
+ [Your First Custom Node and Tree](#your-first-custom-node-and-tree)
92+
+ [Your First Custom Node and Tree](#your-first-custom-node-and-extension)
9393
+ [Custom Actions](#custom-actions)
9494
+ [Custom Conditions](#custom-conditions)
9595
+ [Custom Composites](#custom-composites)
@@ -317,11 +317,10 @@ public class MyCustomAi : MonoBehaviour {
317317

318318
## Creating Custom Reusable Nodes
319319

320-
What makes Fluid Behavior Tree so powerful is the ability to write your own nodes and extend the tree builder to inject
321-
custom parameters. For example we can write a new tree builder method like this that sets the target of your AI system.
320+
What makes Fluid Behavior Tree so powerful is the ability to write your own nodes and add them to the builder without editing any source. You can even create Unity packages that add new builder functionality. For example we can write a new tree builder method like this that sets the target of your AI system with just a few lines of code.
322321

323322
```C#
324-
var tree = new TreeBuilderCustom(gameObject)
323+
var tree = new BehaviorTreeBuilder(gameObject)
325324
.Sequence()
326325
.AgentDestination("Find Enemy", target)
327326
.Do(() => {
@@ -332,10 +331,9 @@ var tree = new TreeBuilderCustom(gameObject)
332331
.Build();
333332
```
334333

335-
### Your First Custom Node and Tree
334+
### Your First Custom Node and Extension
336335

337-
It should take about 10 minutes to setup your first custom
338-
action and extend the pre-existing behavior tree builder script.
336+
It should take about 3 minutes to create your first custom action and implement it. First create a new action.
339337

340338
```C#
341339
using Adnc.FluidBT.Tasks;
@@ -344,56 +342,36 @@ using UnityEngine;
344342
using UnityEngine.AI;
345343

346344
public class AgentDestination : ActionBase {
347-
public NavMeshAgent agent;
345+
private NavMeshAgent _agent;
348346
public Transform target;
349347

350348
protected override void OnInit () {
351-
agent = Owner.GetComponent<NavMeshAgent>();
349+
_agent = Owner.GetComponent<NavMeshAgent>();
352350
}
353351

354352
protected override TaskStatus OnUpdate () {
355-
agent.SetDestination(target.position);
353+
_agent.SetDestination(target.position);
356354
return TaskStatus.Success;
357355
}
358356
}
359357
```
360358

361-
New method added to the builder script. This is pretty simple and easy to customize since most of the overhead is
362-
abstracted away.
359+
Next we need to extend the `BehaviorTreeBuilder` script with our new AgentDestination action. For more information on C# class extensions see the [official docs](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods).
363360

364361
```C#
365362
using Adnc.FluidBT.Trees;
366-
using UnityEngine;
367363

368-
public class TreeBuilderCustom : BehaviorTreeBuilderBase<TreeBuilderCustom> {
369-
// This is always required for class extension reasons (will error without)
370-
public TreeBuilderCustom (GameObject owner) : base(owner) {
371-
}
372-
373-
public TreeBuilderCustom AgentDestination (Transform target) {
374-
_tree.AddNode(Pointer, new AgentDestination {
375-
Name = "Agent Destination",
376-
target = target
364+
public static class BehaviorTreeBuilderExtensions {
365+
public static BehaviorTreeBuilder AgentDestination (this BehaviorTreeBuilder builder, string name, Transform target) {
366+
return builder.AddNode(new AgentDestination {
367+
Name = name,
368+
target = target,
377369
});
378-
379-
return this;
380370
}
381371
}
382372
```
383373

384-
Be sure when you create trees that you use your new `TreeBuilderCustom` class. For example:
385-
386-
```C#
387-
_tree = new TreeBuilderCustom(gameObject)
388-
.Sequence()
389-
.AgentDestination("Find Target", target)
390-
...
391-
.End()
392-
.Build();
393-
```
394-
395-
And you're done! You've now created a custom action and extendable behavior tree builder. The following examples
396-
will be more of the same. But each covers a different node type.
374+
And you're done! You've now created a custom action and extendable behavior tree builder that's future proofed for new versions. The following examples will be more of the same. But each covers a different node type.
397375

398376
### Custom Actions
399377

@@ -427,22 +405,16 @@ public class CustomAction : ActionBase {
427405
}
428406
```
429407

430-
Add your new node to a custom tree builder.
408+
Add your new node to an extension.
431409

432-
```C#
410+
```c#
433411
using Adnc.FluidBT.Trees;
434-
using UnityEngine;
435412

436-
public class TreeBuilderCustom : BehaviorTreeBuilderBase<TreeBuilderCustom> {
437-
public TreeBuilderCustom (GameObject owner) : base(owner) {
438-
}
439-
440-
public TreeBuilderCustom CustomAction (string name = "Custom Action") {
441-
_tree.AddNode(Pointer, new CustomAction {
442-
Name = name
413+
public static class BehaviorTreeBuilderExtensions {
414+
public static BehaviorTreeBuilder CustomAction (this BehaviorTreeBuilder builder, string name = "My Action") {
415+
return builder.AddNode(new CustomAction {
416+
Name = name,
443417
});
444-
445-
return this;
446418
}
447419
}
448420
```
@@ -480,101 +452,53 @@ public class CustomCondition : ConditionBase {
480452

481453
Add the new condition to your behavior tree builder with the following snippet.
482454

483-
```C#
484-
using UnityEngine;
455+
```c#
485456
using Adnc.FluidBT.Trees;
486457

487-
public class TreeBuilderCustom : BehaviorTreeBuilderBase<TreeBuilderCustom> {
488-
public TreeBuilderCustom (GameObject owner) : base(owner) {
489-
}
490-
491-
public TreeBuilderCustom CustomCondition (string name = "My Condition") {
492-
_tree.AddNode(Pointer, new CustomCondition {
493-
Name = name
458+
public static class BehaviorTreeBuilderExtensions {
459+
public static BehaviorTreeBuilder CustomCondition (this BehaviorTreeBuilder builder, string name = "My Condition") {
460+
return builder.AddNode(new CustomCondition {
461+
Name = name,
494462
});
495-
496-
return this;
497463
}
498464
}
499465
```
500466

501467
### Custom Composites
502468

503469
Fluid Behavior Tree isn't limited to just custom actions and conditions. You can create new composite types with a fairly
504-
simple API. Here is an example of a new selector variation that randomly chooses an execution order.
470+
simple API. Here is an example of a basic sequence.
505471

506472
```C#
507473
using Adnc.FluidBT.TaskParents.Composites;
508474
using Adnc.FluidBT.Tasks;
509-
using Random = System.Random;
510475

511-
// Makes a selector randomize its order of running child tasks
512-
public class SelectorRandom : CompositeBase {
513-
private bool _init;
514-
515-
// Triggers each time this node is ticked
516-
protected override TaskStatus OnUpdate () {
517-
if (!_init) {
518-
ShuffleChildren();
519-
_init = true;
520-
}
521-
476+
public class CustomSequence : CompositeBase {
477+
protected override TaskStatus OnUpdate () {
522478
for (var i = ChildIndex; i < Children.Count; i++) {
523479
var child = Children[ChildIndex];
524480

525-
switch (child.Update()) {
526-
case TaskStatus.Success:
527-
return TaskStatus.Success;
528-
case TaskStatus.Continue:
529-
return TaskStatus.Continue;
481+
var status = child.Update();
482+
if (status != TaskStatus.Success) {
483+
return status;
530484
}
531485

532486
ChildIndex++;
533487
}
534488

535-
return TaskStatus.Failure;
536-
}
537-
538-
// Reset is triggered when the behavior tree ends, then runs again ticking this node
539-
public override void Reset (bool hardReset = false) {
540-
base.Reset(hardReset);
541-
542-
ShuffleChildren();
543-
}
544-
545-
private void ShuffleChildren () {
546-
var rng = new Random();
547-
var n = Children.Count;
548-
while (n > 1) {
549-
n--;
550-
var k = rng.Next(n + 1);
551-
var value = Children[k];
552-
Children[k] = Children[n];
553-
Children[n] = value;
554-
}
489+
return TaskStatus.Success;
555490
}
556491
}
557492
```
558493

559-
Adding custom composites to your behavior tree only takes a line of code. Below is a commented out chunk
560-
of code if you need more control over the parameters of your composite.
494+
Adding custom composites to your behavior tree is just as simple as adding actions. Just takes one line of code.
561495

562-
```C#
563-
using UnityEngine;
496+
```c#
564497
using Adnc.FluidBT.Trees;
565498

566-
public class TreeBuilderCustom : BehaviorTreeBuilderBase<TreeBuilderCustom> {
567-
public TreeBuilderCustom (GameObject owner) : base(owner) {
568-
}
569-
570-
public TreeBuilderCustom CustomComposite (string name = "My Custom Composite") {
571-
return ParentTask<CustomComposite>(name);
572-
573-
// Or you can code this manually if you need more specifics
574-
// var parent = new CustomComposite { Name = name };
575-
// _tree.AddNode(Pointer, parent);
576-
// _pointer.Add(parent);
577-
// return this;
499+
public static class BehaviorTreeBuilderExtensions {
500+
public static BehaviorTreeBuilder CustomSequence (this BehaviorTreeBuilder builder, string name = "My Sequence") {
501+
return builder.ParentTask<CustomSequence>(name);
578502
}
579503
}
580504
```
@@ -587,7 +511,7 @@ Decorators can also be custom written to cut down on repetitive code.
587511
using Adnc.FluidBT.Decorators;
588512
using Adnc.FluidBT.Tasks;
589513

590-
public class Inverter : DecoratorBase {
514+
public class CustomInverter : DecoratorBase {
591515
protected override TaskStatus OnUpdate () {
592516
if (Child == null) {
593517
return TaskStatus.Success;
@@ -610,25 +534,15 @@ public class Inverter : DecoratorBase {
610534
}
611535
```
612536

613-
Implementing decorators is similar to composites (alternative commented out code for more complex integration).
614-
See the commented area for more details.
537+
Implementing decorators is similar to composites. If you need to set arguments on the composite you'll want to take a loot at the method `BehaviorTreeBuilder.AddNodeWithPointer()`.
615538

616-
```C#
617-
using UnityEngine;
539+
```c#
618540
using Adnc.FluidBT.Trees;
619541

620-
public class TreeBuilderCustom : BehaviorTreeBuilderBase<TreeBuilderCustom> {
621-
public TreeBuilderCustom (GameObject owner) : base(owner) {
622-
}
623-
624-
public TreeBuilderCustom CustomDecorator (string name = "My Custom Decorator") {
625-
return ParentTask<CustomDecorator>(name);
626-
627-
// Or you can code this manually if you need more specifics
628-
// var parent = new CustomComposite { Name = name };
629-
// _tree.AddNode(Pointer, parent);
630-
// _pointer.Add(parent);
631-
// return this;
542+
public static class BehaviorTreeBuilderExtensions {
543+
public static BehaviorTreeBuilder CustomInverter (this BehaviorTreeBuilder builder, string name = "My Inverter") {
544+
// See BehaviorTreeBuilder.AddNodeWithPointer() if you need to set custom composite data from arguments
545+
return builder.ParentTask<CustomInverter>(name);
632546
}
633547
}
634548
```

0 commit comments

Comments
 (0)