{"id":119216,"date":"2020-10-12T15:20:00","date_gmt":"2020-10-12T15:20:00","guid":{"rendered":"http:\/\/www.gamasutra.com\/view\/news\/371728"},"modified":"2020-10-12T15:20:00","modified_gmt":"2020-10-12T15:20:00","slug":"behavior-trees-and-the-future-of-intelligent-control","status":"publish","type":"post","link":"https:\/\/sickgaming.net\/blog\/2020\/10\/12\/behavior-trees-and-the-future-of-intelligent-control\/","title":{"rendered":"Behavior trees and the future of intelligent control"},"content":{"rendered":"<p> <!-- Google Tag Manager --> <!-- End Google Tag Manager --> &lt;!&#8211;  &#8211;&gt;  <title>Gamasutra: Thibaud de Souza&#8217;s Blog &#8211; Behavior trees and the future of intelligent control<\/title>   <!--[if lt IE 9]&gt; <a href=\"http:\/\/html5shim.googlecode.com\/svn\/trunk\/html5.js\">http:\/\/html5shim.googlecode.com\/svn\/trunk\/html5.js<\/a> &lt;![endif]--> <!-- CSS -->                    <!-- link href=\"https:\/\/twimgs.com\/gamasutra\/css\/minified.css\" rel=\"stylesheet\" type=\"text\/css\" \/ -->    <!-- Mobile Specific Metas -->  <!-- Start Visual Website Optimizer Asynchronous Code --> <!-- End Visual Website Optimizer Asynchronous Code --> <!-- Start HeatMap.me Code --> <!-- End HeatMap.me Code --> <!-- Start: GPT Sync --> <!-- End: GPT -->    <!-- Eloqua tracking code --> <!-- End Eloqua tracking code -->  <!-- Google Tag Manager (noscript) -->  <!-- End Google Tag Manager (noscript) --> <!--Cookie banner code starts here --> <!--Cookie banner code ends here --> <!-- Informa Branding code goes here--> <\/p>\n<div id=\"iribbon-container\" class=\"content-body-wrapper\"> <button id=\"iribbon-title\" title=\"show\/hide\" class=\"inactive\">Informa<\/button> <\/p>\n<div id=\"iribbon-detail\" class=\"ribbon-hide\">\n<div id=\"iribbon-left\">\n<p>Gamasutra is part of the Informa Tech Division of Informa PLC<\/p>\n<\/p><\/div>\n<div id=\"iribbon-right\">\n<p>This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC&#8217;s registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.<\/p>\n<\/p><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<p> <!-- Informa Branding code goes here--> <!-- Beginning Sync AdSlot 19 for Ad unit Gamasutra\/ ### size: [[2,2]] --> <!-- End AdSlot 19 --> <!-- Beginning Sync AdSlot 20 for Ad unit Gamasutra\/ ### size: [[7,7]] --> <!-- End AdSlot 20 --> <\/p>\n<div class=\"container\">\n<div id=\"container-main\" class=\"content-body-wrapper\"> <!-- Google Prestitial Ads start here--> <!-- Google Prestitial Ads end here--> <\/p>\n<div class=\"container bottom3\">\n<div class=\"span-7\"> <a href=\"https:\/\/www.gamasutra.com\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/10\/behavior-trees-and-the-future-of-intelligent-control.png\" alt=\"Gamasutra: The Art &amp; Business of Making Games\" width=\"243\" height=\"77\" border=\"0\"><\/a><img decoding=\"async\" alt=\"spacer\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/10\/behavior-trees-and-the-future-of-intelligent-control.gif\" width=\"27\"> <\/div>\n<\/p><\/div>\n<div class=\"span-20\"> <!--end show phone--> <!--end showphone--> <!--end nav--> <\/p>\n<div class=\"span-20 last content_bg\">\n<div class=\"hide-phone\">\n<div class=\"span-4\">\n<div class=\"content_box_left\">\n<div class=\"leftcol\"> <!--member login--> <!--end memberlogin--> <!--begin social icons--> <!--begin social icons--> <!--end social icons--> <!--end social icons--> <!--begin page numbers--> <!--end page numbers--> <!--begin leftnav--> <!--end leftnav--> <!-- Beginning Sync AdSlot 3 for Ad unit Gamasutra\/ ### size: [[164,59]] --> <!-- End AdSlot 3 --> <!-- Beginning Sync AdSlot 4 for Ad unit Gamasutra\/ ### size: [[164,59]] --> <!-- End AdSlot 4 --> <!-- Beginning Sync AdSlot 5 for Ad unit Gamasutra\/ ### size: [[164,409]] --> <!-- End AdSlot 5 --> <!-- Beginning Sync AdSlot 9 for Ad unit Gamasutra\/ ### size: [[164,177]] --> <!-- End AdSlot 9 --> <!-- Beginning Sync AdSlot 11 for Ad unit Gamasutra\/ ### size: [[164,177]] --> <!-- End AdSlot 11 --> <!-- begin event tickers --> <!-- end event tickers --> <!--begin jobs--> <!--end jobs--> <!--begin blogs--> <!--end blogs--> <!--begin press releases--> <!--end press releases--> <!--begin calendar--> &lt;!&#8211; <\/p>\n<div class=\"header\"><img decoding=\"async\" alt=\"arrow\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/10\/behavior-trees-and-the-future-of-intelligent-control-1.png\" width=\"22px\" height=\"20px\" \/><a href=\"http:\/\/www.gamasutra.com\/calendar\/calendar.php\">Calendar<\/a><\/div>\n<div class=\"leftnav bottom2\"> <a href=\"http:\/\/www.gamasutra.com\/calendar\/calendar.php\"><strong>View All<\/strong><\/a> &nbsp;&nbsp;&nbsp; <a href=\"http:\/\/www.gamasutra.com\/calendar\/calendar_submit.php\"><strong>Submit Event<\/strong><\/a> <\/p>\n<hr>\n<ul> <\/ul>\n<\/div>\n<p> &#8211;&gt; <!--end calendar--> <!--begin about--> <\/p>\n<div class=\"bottom2\"> <a href=\"https:\/\/www.gamasutra.com\/advertise\"> <img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/10\/behavior-trees-and-the-future-of-intelligent-control.jpg\" alt=\"Sponsor\" border=\"0\" class=\"whiteTop\" width=\"177px\" height=\"60px\"> <\/a>\n<\/div>\n<p> <!--end about--> <!--begin network--> <\/p>\n<div class=\"leftnav_network bottom2\"> If you enjoy reading this site, you might also want to check out these UBM Tech sites: <\/p>\n<hr>\n<hr>\n<p> <br class=\"clear\">\n<\/div>\n<p> <!--end network--> <!--begin store--> <!--end store--> <\/div>\n<p><!--end leftcol--> <\/div>\n<\/div><\/div>\n<div class=\"span-16 last\">\n<div class=\"content_box_middle\"> <!-- InstanceBeginEditable name=\"BodyContent\" --> <\/p>\n<div class=\"page_item\">\n<div><a name=\"twitter_share\" href=\"http:\/\/twitter.com?status=RT @gamasutra: Behavior trees and the future of intelligent control http:\/\/www.gamasutra.com\/blogs\/ThibaudDeSouza\/20201012\/371528\/\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/10\/behavior-trees-and-the-future-of-intelligent-control-1.gif\" alt=\"Share on Twitter\" border=\"0\" height=\"20\"><\/a>  <span id=\"edit_post_link\"><\/span>&nbsp;&nbsp; <a href=\"https:\/\/www.gamasutra.com\/blogs\/rss\/\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/10\/behavior-trees-and-the-future-of-intelligent-control-2.gif\" width=\"15\" height=\"15\" border=\"0\" alt=\"RSS\"><\/a> <\/div>\n<hr>\n<div class=\"item_body mobile_image_transform\"> <strong><i><small> The following blog post, unless otherwise noted, was written by a member of Gamasutra\u0092s community.<br \/>The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company. <\/small><\/i><\/strong> <\/p>\n<hr>\n<p><em>Since <a href=\"https:\/\/www.gamasutra.com\/view\/feature\/130663\/gdc_2005_proceeding_handling_.php\">Isla&#8217;s seminal article<\/a>, behavior trees (BT) have become a well recognized framework for designing and managing game AIs.<\/em><\/p>\n<p><em>Even so, a game logic programmer may not immediately perceive their usefulness, and&nbsp;AI engineers may occasionally tell you that they aren&#8217;t really game AI. Are GOAP, HTN and Utility AI the next big thing?<\/em><\/p>\n<p><em>Shopping for AI solutions, we&nbsp;experimented with state machines, behavior trees and GOAP; this helped crystallize long standing intuitions about game logic and intelligent control. I discuss stateless vs stateful control and the key decisions which informed the design of our BT library.<\/em><\/p>\n<p>Behavior Trees partake intelligent control. Compared with AI solutions of like vintage (such as GOAP) BT is more control, less problem solving. You may read <a href=\"https:\/\/www.gamasutra.com\/blogs\/ChrisSimpson\/20140717\/221339\/Behavior_trees_for_AI_How_they_work.php\">Chris Simpson&#8217;s comprehensive introduction<\/a>, but I&#8217;ll give you a quick run-down anyway:<\/p>\n<ul>\n<li>With BT, the unit of work is a <strong>task<\/strong>; a task is always <em>running<\/em>, <em>failing<\/em>, or <em>complete<\/em>.<\/li>\n<li>BT composes tasks using <strong>sequences<\/strong>&nbsp;and <strong>selectors<\/strong>. A sequence iterates children, until the first non-successful task is encountered; a selector iterates until a non-failing task is found.<\/li>\n<\/ul>\n<p>BT advocates emphasize modularity and responsiveness. This perhaps makes sense when comparing BT with finite state machines (FSMs). To the skeptical game logic programmer, however, that is no selling point: computer programs are modular, update loops are responsive.<\/p>\n<p>In game programming&nbsp;there is a long standing intuition that timely activities may be expressed using imperative forms, much as we write (immediate, functional) conventional program code; this intuition trips game programming hopefuls. Humming to the tune of &#8220;hey, my logic is not working&#8221; here is a variant of what is commonly seen in game programming forums:<\/p>\n<hr>\n<p><tt>void Snipe(){<br \/>&nbsp;&nbsp; &nbsp;Load(gun);<br \/>&nbsp;&nbsp; &nbsp;Aim(at: target);<br \/>&nbsp;&nbsp; &nbsp;Shoot();<br \/>}<\/tt><\/p>\n<hr>\n<p>Running counter to functional programming does not invalidate this intuition: action queues, co-routines and (syntactic sugars over) event-driven programming, all in some degree answer this. With BT, sequences&nbsp;and the running&nbsp;state address the same problem.<\/p>\n<p>In engaging BT, however, we acknowledge that a better solution to modeling timely activities without pain requires intelligent control. So here&#8217;s a couple of&nbsp;things BT does implicitly, which are well beyond the grasp of action queues and co-routines:<\/p>\n<ul>\n<li>A task &#8220;up the tree&#8221; will interrupt lower priority work. In the above example, this could&nbsp;mean&nbsp;avoiding a grenade while aiming, or loading a gun.&nbsp;<\/li>\n<li>Failed tasks re-iterate,&nbsp;complete tasks will skip;&nbsp;this means both resilience and, quite often, the illusion of purposeful, mindful behavior.<\/li>\n<\/ul>\n<p><strong>BT&nbsp;offers&nbsp;a concise, effective framework for managing timely activities &#8211; associating intuitive task descriptions with a flexible (switch\/skip\/reiterate) execution model<\/strong><\/p>\n<p>Looking at the big picture, BT stands the middle ground between smarter AIs (HTN, GOAP, Evolutionary, ML) and traditional control; it may be used on its own, or in combination with other techniques.<\/p>\n<p>In all we decided to focus on BT because we wanted to fix, enhance, condense and clarify &#8220;everyday game AIs&#8221;. Game AIs which, being mostly rule based, are not conceptually involved, and a standard fare to game logic programmers.<\/p>\n<p>BT may be implemented as a stateless control strategy; modern iterations, however, have become increasingly stateful. In the next section I discuss the affinity between stateful control and logic hell.<\/p>\n<p><strong>In a dynamic (game\/simulation) environment, responsiveness and correctness are not achieved by storing state<\/strong>. Stored state is a by-product of circumstance (world state). Provided world state changes fast enough, caches get out of sync, game logic breaks down.<\/p>\n<p>Wanting&nbsp;a yardstick to evaluate game logic frameworks?&nbsp;Question&nbsp;control strategies that&nbsp;<em>systematically<\/em>&nbsp;create, store and manage (or require the programmer to manage) control state.<\/p>\n<p>With this yardstick in hand, let&#8217;s revisit a few well accepted gadgets in the game logic programmer&#8217;s toolkit:<\/p>\n<ul>\n<li><em>Event driven programming<\/em>&nbsp;is stateful: handlers are registered and stored. This style of programming does not scale to complex game AI.<\/li>\n<li><em>Co-routines<\/em>&nbsp;are stateful&nbsp;in that program stacks are stored and restored at every frame. The resulting agents commit (blindly) to action courses that a changing environment will soon invalidate (keep reloading, grenade headed your way).<\/li>\n<li><em>Unity&#8217;s&nbsp;component architecture<\/em>&nbsp;is inherently stateful (moving parts), and biases towards parallel execution: running components in parallel is easy (and useful), ensuring they will not is often desirable and it is&nbsp;(too much) work.<\/li>\n<li>Staggering and reducing frame rate requires <em>less<\/em> control state. As such running sub-systems (such as apperception, or control) at a lower frame rate is a (relatively) safe optimization.<\/li>\n<\/ul>\n<p>This distinction, between stateless and stateful control, informed the design of our BT library; to put things in perspective, we spent perhaps 80% of development time working on stateful constructs, and recommend their use in perhaps&nbsp;15% of use cases.<\/p>\n<p>As a rule of thumb, bugs caused by stateful control are caught in QC (including after release). Bugs caused by stateless control are caught by functional testing, and QC aren&#8217;t going to see them.<\/p>\n<p>Now that we have covered the distinction between stateless and stateful control, let&#8217;s consider BT from a game AI&nbsp;point of view, as we should like our logic to handle&nbsp;complex, believable agents.<\/p>\n<p>STRIPS orientated approaches (think GOAP) emphasize planning intelligence; this is problem solving. A GOAP agent searches through available action courses;&nbsp;a plan is generated;&nbsp;as with path-finding, frequent re-planning is advised.<\/p>\n<p>With BT, a static plan is manually crafted (or perhaps synthesized &#8211; as with ML or evolutionary techniques); thus, in composing tasks the designer specify &#8220;good behavior&#8221;.<br \/>This approach isn&#8217;t altogether restrictive: plans are branching constructs; BT agents are allowed to drop, switch between, and re-iterate tasks.<\/p>\n<p>This is intelligent control closely resembling how humans acquire and utilize knowledge. We share &#8216;recipes&#8217; about how to do X. In performing (applying the recipes) we do not mind being interrupted (prioritize tasks) or re-doing failed steps. Also&nbsp;we are not ordinarily bothered by <em>not knowing<\/em>&nbsp;why or how the recipes actually work.<\/p>\n<p>GOAP, then, partakes planning intelligence; whereas BT provides intelligent control.&nbsp;Atomizing problems into component actions and their expected outcomes (GOAP) is science; encoding &#8220;good behavior&#8221; (be it a winning strategy, a cooking recipe or the life cycle of dragonflies) is (technical) design.<\/p>\n<p>BT is computationally cheap (no search)&nbsp;and bears a close affinity to how both designers and software engineers approach domain knowledge.<\/p>\n<p>There is a wealth of BT solutions available. Many focus on visual scripting; others use (embedded) domain specific languages (EDSLs). Finally, some provide ad-hoc scripting languages.<\/p>\n<p>What do these solutions have in common? In all cases&nbsp;developers have determined that integrating with a general purpose language (such as C#, C++ or Python) is unpractical or perhaps undesirable. The development effort then, is on par with building&nbsp;a separate runtime. Conversely&nbsp;users are tied to a proprietary system involving custom constructs and abstractions.<\/p>\n<p>Visual solutions often&nbsp;overlook&nbsp;tools that, from a programmer&#8217;s point of view, are indispensable &#8211;&nbsp;such as being version control, testing or search friendly.&nbsp;Bearing in mind that visual solutions are not without merit, we simply wanted a robust engineering foundation.<\/p>\n<p>With DSLs&nbsp;you are not throwing the host language away: it is more like carrying its corpse in your arms. Less graphically: skimping&nbsp;on the effort of writing a proprietary parser (or forking an existing compiler), DSLs also do not readily interface with the host language. Consistently, BT literature (which mainly covers DSLs and visual solutions)&nbsp;features:<\/p>\n<ul>\n<li>Articles about parameterizing behavior trees (reinvent functions)<\/li>\n<li>Conditional nodes (reinvent control flow)<\/li>\n<li>Custom reuse (such as linking a behavior tree from another)<\/li>\n<\/ul>\n<p>Across the board, DSLs also&nbsp;lead to&nbsp;confusing compiler errors, confusing debug traces and&nbsp;degraded performance.<\/p>\n<p>Necrophilia aside (put the corpse down).<\/p>\n<p>After reviewing existing solutions (notably for Unity and C#), our overall conclusion was that a library scaling from the nitty gritty details of procedural animation to high level behaviors was <em>missing. <\/em><\/p>\n<p>Conceptually&nbsp;we started thinking of behavior trees as a clever, elegant approach to coding update loops (no more, no less) but there was not a library &#8220;out there&#8221; providing seamless integration with&nbsp;C# or another object language.<\/p>\n<p>Control in OOP languages is relatively inflexible;&nbsp;perhaps this library could not be engineered?<\/p>\n<p>Our goal was to avail BT everywhere timely tasks are involved. For this to happen <em>Status<\/em>&nbsp;needed to be small and mighty (as the Mighty Bool) and our composites&nbsp;more nimble than if-elses.<\/p>\n<h2>Core library<\/h2>\n<p>The smallest unit of work in our library&nbsp;is a <em>status expression<\/em>&nbsp;(not an object, function reference or lambda).&nbsp;Where expressions go, anything goes:<\/p>\n<ul>\n<li>Parameterisation is built-in (use functions),<\/li>\n<li>Statefulness is possible (use objects)<\/li>\n<li>Conventional programming is okay (conversions from bools, statements, traditional control flow)<\/li>\n<\/ul>\n<p>The library does not centralize control; we can use our own, dedicated update loops and tickers or <tt>MonoBehaviour<\/tt>&#8216;s <code>Update()<\/code>&nbsp;&#8211;&nbsp;even the upstream ticker&nbsp;built into a pre-existing visual solution.<\/p>\n<p>To make this possible, we designed a calculus:<\/p>\n<ul>\n<li><strong>Sequences<\/strong> overload the conditional logical AND (&amp;&amp;)<\/li>\n<li><strong>Selectors<\/strong> overload the conditional logical OR (||)<\/li>\n<li><strong>Parallel execution<\/strong> is implemented via PLUS (+) and MUL (*).&nbsp;<\/li>\n<\/ul>\n<p>Implementing sequences and selectors in this way is possible in C#&nbsp;because overloading preserves the short-circuiting behavior of the conditional operators (three cheers to SQL, 3VL and enterprise computing).<\/p>\n<p>An example using a sequence:<\/p>\n<hr>\n<p><tt>status Snipe() =&gt; Load(gun) &amp;&amp; Aim(at: target) &amp;&amp; Shoot();<\/tt><\/p>\n<hr>\n<p>And another using a selector:<\/p>\n<hr>\n<p><tt>status Step() =&gt; Attack() || Defend() || Retreat();<\/tt><\/p>\n<hr>\n<p>Although we often&nbsp;abuse the expression bodied notation (<tt>=&gt;<\/tt>),&nbsp;this of course is optional since any function returning <em>status<\/em> may partake the behavior tree(s):<\/p>\n<hr>\n<p><tt>status Grab(){<br \/>&nbsp; &nbsp; if(!inProgress){<br \/>&nbsp; &nbsp; &nbsp; &nbsp; if(!target) &nbsp; &nbsp;return fail(log &amp;&amp; \"No target\");<br \/>&nbsp; &nbsp; &nbsp; &nbsp; if(isGrabbing) return done();<br \/>&nbsp; &nbsp; }<br \/>&nbsp; &nbsp; return MoveTo(target)<br \/>&nbsp; &nbsp; &nbsp; &nbsp; &amp;&amp; Play(\"Grab\", Effect, delay)<br \/>&nbsp; &nbsp; &nbsp; &nbsp; &amp;&amp; isGrabbing;<br \/>}<\/tt><\/p>\n<hr>\n<p>NOTE: <em>A perceptive reader might question why fail() and done() are functions. This hides debugging information injected at compile time, and provides a hook for logging\/tracing APIs.<\/em><\/p>\n<p>In all, <a href=\"https:\/\/github.com\/eelstork\/BehaviorTrees\/blob\/master\/cs\/src\/Status.cs\">the library core fits 100 loc, and is MIT-licensed<\/a>.<\/p>\n<h2>Decorators and stateful composites<\/h2>\n<p>With all reservations about stateful control, there are situations where you want a cooldown or timer; stateful composites&nbsp;are also useful, notably when steps are performative (such as a ritual or dance) or later steps&nbsp;appear&nbsp;to undo prior steps.<\/p>\n<p>Similar to&nbsp;co-routines, stateful composites&nbsp;impose an ordering on tasks &#8211;&nbsp;the idea here is <em>once done&nbsp;is done&nbsp;<\/em>(whereas stateless composites go by <em>if undone, do it over again<\/em>).<\/p>\n<p>The next example implements the main controller in a simple&nbsp;shooting game using a stateful sequence. In this case the controller fully owns the flow of interaction so there is no interference&nbsp;and stateful control is safe.<br \/>The same&nbsp;example also demonstrates decorator syntax (<tt>After<\/tt>&nbsp;inserts a two seconds delay) and shows mixing stateful and stateless composites:<\/p>\n<hr>\n<p><tt>override public status Step() =&gt; Sequence()[<br \/>&nbsp; &nbsp; &nbsp; and ? DisplayMenu &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br \/>&nbsp; &nbsp; : and ? (Exit || StartPlay) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br \/>&nbsp; &nbsp; : and ? Play &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<br \/>&nbsp; &nbsp; : and ? After(2)?[ DisplayScore &amp;&amp; Reset ]<br \/>&nbsp; &nbsp; : loop &nbsp;\/\/ \"end\" if you'd rather not loop over.<br \/>];<\/tt><\/p>\n<hr>\n<p>NOTE: <em>the ternary switch pattern is less elegant than conditional operators, however we do need hooks for tracking state, and we still avoid computationally expensive alternatives (var-args and closures allocate on the heap).<\/em><\/p>\n<p>Finally, a&nbsp;self contained example to emphasize&nbsp;the decorator syntax:<\/p>\n<hr>\n<p><tt>Shoot() =&gt; Button(\"Fire1\") &amp;&amp; Cooldown(0.1f)?[ Fire() ] )<\/tt><\/p>\n<hr>\n<p>Under the hood, decorators leverage the <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/csharp\/language-reference\/operators\/member-access-operators#null-conditional-operators--and-\">null conditional operators<\/a>&nbsp;and abuse the diagnostics API (works on iOS too) to create site bound objects (so you can, but need not declare a field for every cooldown\/timer).<\/p>\n<p>With a year of hindsight&nbsp;and some,&nbsp;<em>Active Logic<\/em>&nbsp;is a fairly stable library. It is tightly integrated with the C# language, features visual tracing\/logging and does not dictate how an engineer should organize their code&nbsp;or generate significant overheads.<\/p>\n<p>My purpose in writing this article was part introducing the library, part encouraging others to more seriously consider BT&#8217;s benefits.<\/p>\n<p>Object oriented and functional languages have not been designed with intelligent control in mind. In this sense&nbsp;our library&nbsp;perhaps&nbsp;should not exist. In C#, we relied on a dependable, yet&nbsp;unlikely combination of obscure, newer and accidental language features.<\/p>\n<p>Compared with conditional operators,&nbsp;the ternary syntax is lesser. It is&nbsp;portable (think C++, Python) but may only support stateful&nbsp;composites(*).<\/p>\n<p>The take home message here, is that intelligent control matters; by-passing DSLs, it may be&nbsp;implemented today in&nbsp;object oriented and functional languages;&nbsp;with minor, non breaking changes to the target lingo,&nbsp;small performance overheads and syntactic quizziness&nbsp;may be smoothed over; concerted efforts will make this happen.<\/p>\n<p><small><em>(*) Edit: I previously wrote that the ternary switch notation could support stateless composites. Although I keep my eyes on the prize,&nbsp;that is&nbsp;<\/em><em>very probably a <\/em>no<\/small><em><small>.<\/small><\/em><\/p>\n<p>Designing and implementing Active Logic has been a peculiar journey, and I am hoping to see delightfully crafted AIs utilizing this tool.&nbsp;<\/p>\n<p>The <a href=\"https:\/\/github.com\/active-logic\/activelogic-cs\">core library is engine agnostic, available&nbsp;on Github<\/a> (AGPL), and there is also a commercial license (<a href=\"https:\/\/assetstore.unity.com\/packages\/tools\/ai\/active-logic-151850\">via the Unity Asset Store<\/a>).<\/p>\n<p>Dramatic improvements to the&nbsp;library would require extensive usage, extensive feedback, or groundbreaking improvements to the C# language; with this in mind I am interested in hearing from (and perhaps contributing to) projects that may take advantage of this technology.<\/p>\n<p>This has been a fairly top-down overview; I may follow up with a hands-on article.&nbsp;<\/p>\n<p><em>The <\/em>Active Logic <em>library&nbsp;stemmed from our independant game&nbsp;project, Antistar. Antistar is a real time adventure game, and the range of applications we originally envisionned&nbsp;includes ecosystem&nbsp;behavior, squad AIs and less rigid approaches to conversation management. While the game&#8217;s codebase largely predates our BT library, not crediting the darling project that started it all may be a bit uncouth.&nbsp;Antistar will be presented at Tapei Game Show in&nbsp;2021.<\/em><\/p>\n<p><em><a href=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/10\/behavior-trees-and-the-future-of-intelligent-control-1.jpg\"><img loading=\"lazy\" decoding=\"async\" alt height=\"282\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/10\/behavior-trees-and-the-future-of-intelligent-control-1.jpg\" width=\"500\"><\/a><\/em><\/p>\n<p>Until then. My encouragement goes to the skeptical game logic programmer: behaviors tree are a silver bullet &#8211; here&#8217;s a gun, go shoot werewolves.<\/p>\n<\/p><\/div>\n<hr>\n<div class=\"hide-phone\">\n<h3>Related Jobs<\/h3>\n<div class=\"stories_item\">\n<div class=\"thumb\"><a href=\"https:\/\/jobs.gamasutra.com\/job\/lead-gameplay-programmer-burbank-california-34607\"><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/10\/behavior-trees-and-the-future-of-intelligent-control-2.jpg\" alt=\"Insomniac Games\" width=\"120\"><\/a><\/div>\n<\/p><\/div>\n<div class=\"stories_item\">\n<div class=\"thumb\"><a href=\"https:\/\/jobs.gamasutra.com\/job\/lead-engine-programmer-burbank-california-34606\"><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/10\/behavior-trees-and-the-future-of-intelligent-control-2.jpg\" alt=\"Insomniac Games\" width=\"120\"><\/a><\/div>\n<\/p><\/div>\n<div class=\"stories_item\">\n<div class=\"thumb\"><a href=\"https:\/\/jobs.gamasutra.com\/job\/graphics-programmer-burbank-california-34605\"><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/10\/behavior-trees-and-the-future-of-intelligent-control-2.jpg\" alt=\"Insomniac Games\" width=\"120\"><\/a><\/div>\n<\/p><\/div>\n<div class=\"stories_item\">\n<div class=\"thumb\"><a href=\"https:\/\/jobs.gamasutra.com\/job\/experienced-game-developer-tokyo-31908\"><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/10\/behavior-trees-and-the-future-of-intelligent-control-3.jpg\" alt=\"Square Enix Co., Ltd.\" width=\"120\"><\/a><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<hr><\/div>\n<p> <!-- InstanceEndEditable --> <\/div>\n<p><!--end contentbox-->\n<\/div>\n<p><!--end span-16--> <\/div>\n<p> <br class=\"clear\"> <\/div>\n<p><!--end span-21--> <!--begin right sidebar--> <!--end right sidebar--> &lt;!&#8211; <\/div>\n<p> Extra Div &#8211;&gt; <!-- Beginning Sync AdSlot 21 for Ad unit Gamasutra\/ ### size: [[8,2]] --> <!-- End AdSlot 21 --> <!-- Beginning Sync AdSlot 22 for Ad unit Gamasutra\/ ### size: [[8,4]] --> <!-- End AdSlot 22 --> <!-- Beginning Sync AdSlot 23 for Ad unit Gamasutra\/ ### size: [[4,4]] --> <!-- End AdSlot 23 --> <br class=\"clear\"><\/p><\/div>\n<p><!--end content-body-wrapper--> <\/div>\n<p><!--end container--><br \/>\n<!--begin footer--> <!--end footer--> <!-- SiteCatalyst code version: H.21.\nCopyright 1996-2010 Adobe, Inc. All Rights Reserved\nMore info available at http:\/\/www.omniture.com --> <a href=\"http:\/\/www.omniture.com\" title=\"Web Analytics\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/10\/behavior-trees-and-the-future-of-intelligent-control-3.gif\" height=\"1\" width=\"1\" border=\"0\" alt><\/a><!--\/DO NOT REMOVE\/--><br \/>\n<!-- End SiteCatalyst code version: H.21. --> <!-- Begin ADSNATIVE Code --> <!-- End ADSNATIVE Code --> <!--Begin Ad script for pixel --> <!--END Ad script for pixel --><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&lt;!&#8211; &#8211;&gt; Gamasutra: Thibaud de Souza&#8217;s Blog &#8211; Behavior trees and the future of intelligent control Informa Gamasutra is part of the Informa Tech Division of Informa PLC This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC&#8217;s registered office is 5 Howick Place, [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":119217,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20],"tags":[],"class_list":["post-119216","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news"],"_links":{"self":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/119216","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/comments?post=119216"}],"version-history":[{"count":0,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/119216\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media\/119217"}],"wp:attachment":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media?parent=119216"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/categories?post=119216"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/tags?post=119216"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}