You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: Doc/QuickStart-Unity.md
+75-40Lines changed: 75 additions & 40 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,13 +1,35 @@
1
1
2
-
*Reading time: 12 minutes - Last Updated: 2020.11.13*
2
+
*Reading time: 12 minutes - Last Updated: 2020.11.27*
3
3
4
-
# Active Logic for Unity - quick start Guide
4
+
# Active Logic for Unity - Quick start guide
5
5
6
-
Be welcome! Here is a hands-on introduction to Active Logic. Let's get started.
6
+
Be welcome! Here is a hands-on introduction to Active Logic. This guide is suitable for the following distributions:
7
+
-[Active Logic](PENDING_URL)
8
+
-[Active-LT](https://github.com/active-lt)
9
+
10
+
Features only available in Active Logic are marked with the [PRO] label; if you are upgrading from Active-LT, [read here](Upgrading.md).
11
+
12
+
This guide assumes some familiarity with Behavior Trees. For a gentle introduction follow the [Frogger tutorial](https://github.com/active-logic/active-lt-demos/tree/main/Frogger).
13
+
For a comprehensive introduction to behavior trees, we recommend [this book](https://btirai.github.io).
14
+
15
+
*Reading offline? You may be looking at an out of date version of the guide; for up to date, comprehensive documentation, visit*
16
+
https://github.com/active-logic/activelogic-cs
17
+
18
+
## Namespaces and scopes
19
+
20
+
- Avail Active Logic `using Active.Core`
21
+
- For keywords use either `static Active.Raw` or `static Active.Status`
22
+
23
+
```cs
24
+
usingActive.Core;
25
+
usingstaticActive.Raw; // using static Active.Status;
26
+
27
+
// ...
28
+
```
7
29
8
30
## Status expressions
9
31
10
-
Throughout this guide we'll consider the example of a basic 'soldier' AI or agent. A soldier may attack, defend or retreat; in AL this is modeled using a *status expression*:
32
+
Throughout this guide we consider the example of a basic 'soldier' AI or agent. A soldier may attack, defend or retreat; in AL this is modeled using a *status expression*:
11
33
12
34
```cs
13
35
statuss=Attack() ||Defend() ||Retreat();
@@ -23,7 +45,7 @@ otherwise, retreat.
23
45
24
46
A `status` may be `complete`, `failing` or `running` (for 'continue'). a value of *running* causes execution to *yield* until the next iteration.
25
47
26
-
Status expressions are invoked *frequently* - usually, within update loops. The next example shows using status expressions within a vanilla`MonoBehaviour` (a base class for behaviors in the Unity game engine):
48
+
Status expressions are invoked *frequently*; below, status expresssions are used via`MonoBehaviour`:
27
49
28
50
```cs
29
51
usingUnityEngine;
@@ -49,9 +71,7 @@ public class Soldier : MonoBehaviour{
49
71
50
72
The above iterates frame by frame until `state` changes to *failing* or *complete*.
51
73
52
-
The Active Logic calculus is not restricted to Unity or `MonoBehaviour`, so this may be considered a sketch for your own integration.
53
-
54
-
Indeed AL does provide powerful base classes advantageously replacing `MonoBehaviour`:
74
+
Instead of `MonoBehaviour`, we recommend using `UGig` or `UTask`:
55
75
56
76
```cs
57
77
publicclassSoldier : UGig{ // or `Gig`
@@ -63,12 +83,10 @@ public class Soldier : UGig{ // or `Gig`
63
83
}
64
84
```
65
85
66
-
**NOTE**: `UGig` and `UTask` partake the integration available from the [Unity Asset Store](https://assetstore.unity.com/packages/tools/ai/active-logic-151850). If you are using another engine, `Gig` and `Task` provide a template/starting point for your own integration.
67
-
68
86
When assigning or returning a status, use `done()`, `fail()` or `cont()`:
69
87
70
88
```cs
71
-
statusAttack() =>hasWeapon?fail():Play("Strike");
89
+
statusAttack() =>hasWeapon?fail:Play("Strike");
72
90
```
73
91
74
92
AL does not restrict status expressions to sequences and selectors
@@ -108,13 +126,13 @@ Initially, mixing `&&` and `||` may be confusing. If so, write simple status exp
108
126
109
127
```cs
110
128
statusDoSomething(){
111
-
if( CANNOT_DO ) returnfail(); // guard A
112
-
if( ALREADY_DONE ) returndone(); // guard B
129
+
if( CANNOT_DO ) returnfail; // guard A
130
+
if( ALREADY_DONE ) returndone; // guard B
113
131
returnREALLY_DO_SOMETHING;
114
132
}
115
133
```
116
134
117
-
While perhaps surprising, *over-exercising* (ticking a done task) and *over-checking* (ticking a failing task) are integral to BT, ensuring *responsiveness*.
135
+
*Over-exercising* (ticking a done task) and *over-checking* (ticking a failing task) are integral to BT, ensuring *responsiveness*.
118
136
119
137
Let's say a soldier dropped their sword. In BT, how would the following sequence handle this?
120
138
@@ -130,8 +148,8 @@ Status expressions implement *stateless* control. In our toy model/example this
130
148
131
149
```cs
132
150
statusAttack(){
133
-
if(health<25) returnfail();
134
-
if(!threat) returnfail();
151
+
if(health<25) returnfail;
152
+
if(!threat) returnfail;
135
153
returnMoveTo(threat) &&Strike(threat);
136
154
}
137
155
```
@@ -146,9 +164,23 @@ More generally, selectors and sequences are known as *composites*.
146
164
147
165
In all, status expressions and status functions combine to form behavior trees.
148
166
149
-
## Decorators
167
+
## Status keywords
168
+
169
+
Status keywords include `done`, `cont` and `fail`. Throughout documentation and examples you will see either of the following:
170
+
171
+
- The raw, unadornated form such as `done`
172
+
- Logging calls, such as `done()` or `done(log && "For no reason")`
173
+
174
+
Raw constants are slightly faster, and require using *Active.Raw*. Logging calls are available via *Active.Status*, and capture useful debugging information, along with custom messages.
175
+
176
+
Within the same project, you may use either *Active.Raw* or *Active.Status*. Ordinarily, logging calls are recommended, unless one of the following is true:
150
177
151
-
In the above example, we've hinted at a `Strike()` task. Effective control requires a variety of small 'utilities' used to modulate behavior. A staple of video game design, the cooldown is one such thing:
178
+
- You are running AL in a physics loop and/or really need to maximise performance
179
+
- You are using a test oriented workflow (then perhaps you do not need the logging/visual history features)
180
+
181
+
## Decorators [PRO]
182
+
183
+
In the above example we hinted at a `Strike()` task. Effective control requires a variety of small 'utilities' used to modulate behavior. A staple of video game design, the cooldown is one such thing:
152
184
153
185
```cs
154
186
statusAttack(){
@@ -157,15 +189,15 @@ status Attack(){
157
189
}
158
190
```
159
191
160
-
This literally is AL magic. Normally you would declare a variable to store a time stamp for the cooldown. AL manages this data (aka control state) on your behalf.
192
+
AL magic lets you invoke stateful decorators without explicitly allocating storage (With a cooldown for instance, a date stamp is stored, so we know when the cooldown has expired).
161
193
162
-
`Gig`, `UGig` (and `MonoBehaviour`) do not support the above syntax. This only works within a class inheriting from `Task` or `UTask` ('stateful context').
194
+
With the above syntax, decorators are supported via `Task`and `UTask` (aka "stateful contexts"); if you are not using decorators, prefer `Gig` and `UGig`.
163
195
164
196
AL offers several [built-in decorators](Reference/Decorators-Builtin.md) and you may also [craft your own](Reference/Decorators-Custom.md).
165
197
166
-
## Ordered Composites
198
+
## Ordered Composites[PRO]
167
199
168
-
Stateless control encourages you to leverage world/agent state as the primary drive for agent behavior. This works well, and often reduces bugs.
200
+
Stateless control encourages you to leverage world/agent state as the primary drive for behavior. This works well, and often reduces bugs.
169
201
170
202
However some design problems do not fit this approach; consider this:
171
203
@@ -201,14 +233,15 @@ status s = Sel()
201
233
-/* ... */ ;
202
234
```
203
235
204
-
**NOTE**: *decorators and ordered composites add control state to your logic. However useful, control state is by nature* error prone*. Abusing decorators will reduce the responsiveness and resilience of your agents, whereas responsive, environment-aware agents draw current information from world state.*
236
+
**NOTE**: *decorators and ordered composites add control state to your logic. Overusing stateful control reduces the responsiveness and resilience of your agents, whereas responsive, environment-aware agents draw current information from world state.*
205
237
206
238
## Tasks and frame agents
207
239
208
240
We have already encountered `UTask`. In Active Logic, `UTask` is a handy base class derived from `MonoBehaviour`. Let's define a task for the `Soldier` role:
209
241
210
242
```cs
211
243
usingActive.Core;
244
+
usingstaticActive.Raw;
212
245
213
246
publicclassSoldier : UTask{
214
247
@@ -219,30 +252,29 @@ public class Soldier : UTask{
Because `Soldier` inherits from `UTask`, it is also a Unity component which may be added to the Unity inspector. In the same way that `Update()` is present in many subclasses of `MonoBehaviour`, `Step()` is our entry point for BT-style update loops.
264
+
Because `Soldier` inherits from `UTask`, it is also a Unity component which may be added to the Unity inspector. In the same way that `Update()` is present in many subclasses of `MonoBehaviour`, `Step()` is our entry point for BT-styled update loops.
232
265
233
-
A task, however,**does not run on its own**.
266
+
A task **does not run on its own**.
234
267
235
268
To make the above runnable, add an `Agent`. Then, in the agent inspector, add `Soldier` as root (if you forget, this happens automatically).
236
269
237
-
**NOTE**: *`undef()` denotes an unimplemented status function. While debugging, undef randomizes its return value, which is useful for testing incomplete models; undef() is only allowed in debug mode.*
238
-
239
270
**Uses of task objects**
240
271
241
272
in AL, task objects are used in several ways:
242
273
243
-
When writing a low level module (such as locomotion, or simple actions), prefer `Task` or `Gig` to `UTask`, `UGig` (even when using Unity). Then you do not override the `Step()` function. Instead you provide a collection of status functions such as `status Walk(...)` and `status Jump(...)`; another task will then invoke these functions directly.
274
+
When writing a low level module (such as locomotion, or a collection of game actions), prefer `Task` or `Gig` to `UTask`, `UGig` (even when using Unity).
275
+
Then you do not override the `Step()` function. Instead you provide a collection of status functions such as `status Walk(...)` and `status Jump(...)`; another task will then invoke these functions directly.
244
276
245
-
When designing higher level behaviors, such as *roles* (say `Farmer` or `Soldier`), override `status Step()` and perhaps expose the task in the inspector via `UTask` (for parameterization). In such cases there is no need to *invoke* the step function:
277
+
When designing high level behaviors, such as *roles* (say `Farmer` or `Soldier`), override `status Step()` and perhaps expose the task in the inspector via `UTask` (for parameterization). In such cases there is no need to explicitly invoke the step function:
246
278
247
279
```cs
248
280
classCitizen : UGig{
@@ -257,7 +289,7 @@ class Citizen : UGig{
257
289
}
258
290
```
259
291
260
-
In the above example, `UGig` is used since neither decorators, nor any ordered composite(s) are needed.`UTask` would be fine but does allocate (a little) memory, even when no stateful constructs are used.
292
+
In the above example, `UGig` is used since neither decorators, nor any ordered composite(s) are needed.
261
293
262
294
The above example also suggests how you compose versatile agents by assembling ever larger BTs, combining OOP's delegation pattern with BT's modular control paradigm.
263
295
@@ -271,34 +303,36 @@ For useful output, we annotate the soldier script:
271
303
272
304
```cs
273
305
usingActive.Core;
306
+
usingstaticActive.Status; // Active.Status for logging calls
@@ -313,8 +347,9 @@ This example illustrates everything you need to know to get started with logging
313
347
-`done()`, `cont()` and `fail()` may receive a custom log message as argument.
314
348
- You may attach a custom message to any status, like so: `status[log && $"Custom"]`
315
349
- String interpolation is preferred.
316
-
- The `log && message` idiom ensures logging does not decrease performance in production builds; as such, you need not remove log messages before shipping.
350
+
- The `log && message` idiom ensures logging does not decrease performance in production builds; as such, you may not need to remove log messages before shipping, and the logging annotations also help documenting your logic.
317
351
318
352
## Going further
319
353
320
-
The quick start guide is intended as a short introduction to AL; to learn more, check the [API reference](Reference/Overview.md).
354
+
The quick start guide is intended as a short introduction to AL; to learn more, check the API reference at
Copy file name to clipboardExpand all lines: Doc/Reference/Unity/Logging.md
+13-1Lines changed: 13 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,7 +10,7 @@ The logging feature solves three problems commonly associated with logging:
10
10
-**Performance** - the API provides safe idioms ensuring minimal overheads, so that you needn't remove traces before shipping.
11
11
-**Best practice** - the logging API helps you design self-explanatory control programs with minimal semantic overheads.
12
12
13
-
## Logging within Gigs and tasks
13
+
## Logging within gigs and tasks
14
14
15
15
### Logging statuses
16
16
@@ -76,6 +76,18 @@ public status Defend(){
76
76
}
77
77
```
78
78
79
+
***Why 'Eval' is necessary***
80
+
81
+
As your code executes, the AL library accumulates logging information pertaining to status expressions. As an example consider the following function:
82
+
83
+
public ABC() => A && B && C;
84
+
85
+
Upon evaluating `C`, A && `B` have already evaluated, and the associate logging information is preserved. However, without `Eval`, AL cannot determine that we are exiting ABC.
86
+
87
+
Because of that, although you might get output without using `Eval`, the structure of such output may be incorrect.
88
+
89
+
If you do not consistently use `Eval` the log-tree view will display partial/incorrectly structured output.
90
+
79
91
## Logging using `Via`
80
92
81
93
*[DOC REVIEW NOTE] in recent versions of AL, it appears that Eval is now a static keyword.*
First, license the Active Logic package [from the Unity Asset Store](http://u3d.as/1AZ8).
4
+
5
+
Your upgrade path depends on whether you are using the UPM package (Github) or the UAS Active-LT asset (from the Unity Asset Store).
6
+
7
+
Before upgrading, backup or commit your project.
8
+
9
+
### 1. Remove Active-LT
10
+
11
+
**If using Active-LT via UPM/Github** -
12
+
Open your project and display the Unity Package Manager. Find and select Active-LT, then choose "Remove" in the bottom right corner.
13
+
14
+
**If using Active-lT via the Unity Asset Store** - Open your project and display the project window. Delete the *ActiveLogic* directory.
15
+
16
+
After removing the package, you will probably see errors in the console; this is normal and these errors may be safely ignored.
17
+
18
+
### 2. Install Active Logic
19
+
20
+
From the Unity Asset Store window, download and import the Active Logic Package. In some versions of AL, you may see warnings in the console window; these warnings may be safely ignored.
21
+
22
+
### 3. Retest your project
23
+
24
+
Press "Play" to retest your project.
25
+
26
+
In some cases, your agents may not run. If this happens, you only need to reassign the "root" task in the matching Agent, Ticker or PhysicsAgent.
0 commit comments