Search Unity

[AI SCRIPTING] Panda BT: Behaviour Tree scripting

Discussion in 'Assets and Asset Store' started by ericbegue, Feb 26, 2016.

  1. Crouching-Tuna

    Crouching-Tuna

    Joined:
    Apr 4, 2014
    Posts:
    82
    Hi all. I wanna ask if it's viable to use BT for player movement.
    I have a custom Character Controller (2D) from an old project and it's a mess. Mainly due to the many if()return; checks like grounded, onLadder, isCrouching, etc.
    It seems separating it by State (FSM) is a much more common way to do it.
    But if we're just talking about organizational purpose, can BT also do it? And if so, in what way?

    1. C# PlayerInput: contains the local player's raw input.
    2. BT layer: using sequence (as input check), calls #3
    3. PlayerMotor: takes move input axis and apply them depending on its state.

    This option is pointless because PlayerMotor will have states too. Like if(!onLadder), ApplyGravity()

    Another option:
    1. C# PlayerInput: player's raw input, but straight away send to PlayerMotor
    2. BT Layer: calls PlayerMotor's functions (that's already made modular). sequence (as state check) like sequence not onLadder then ApplyGravity.
    3. PlayerMotor contains modular functions. ApplyGravity, ApplyInputToHorizontalMovement, ApplyJump, ApplyDash

    This way, the BT layer serves as the "condition" checks(as opposed to a more solid "state" checks). The advantage is it's not bound to just 1 state and each modular function have their set of checks.
    If done in C# then it's again similar to if(grounded && canMove && !dashing), but i guess this is done in BT, and PlayerMotor doesn't need to know the details of what a "condition" can or can't do.

    So.. is this viable? Or i'm just re-complicating things but in a fancier way?
     
  2. scottbass47

    scottbass47

    Joined:
    Jun 8, 2019
    Posts:
    1
    How do you pause the execution of a BT?

    I've tried setting the tickOn field to Manual and then calling Tick() myself, but everytime I set it to Manual in the inspector it automatically reverts to Update. I'm pulling my hair out, this should be very easy but it isn't.
     
  3. duckburger

    duckburger

    Joined:
    Dec 7, 2016
    Posts:
    9
    Hi, just had a quick question for the maker of this asset. I am working on a BT system of my own and want it to do the same thing as Panda where it looks up methods and uses them as nodes in the tree. I've got the looking up of the methods down, but I am struggling to implement the portion where each method is attached to a runtime instance of a node so it can call the "Task.curren.Succeed()/Fail() on it.

    Would you mind giving me some pointers on how that's done using custom method attributes? (or using something else)
    Thanks!
     
  4. StormPooper

    StormPooper

    Joined:
    Mar 17, 2019
    Posts:
    2
    Hi, I have a question that could be dumb for most of you: what is the syntax of the comments in the tree file?
    I saw on the documentation that comments are displayed as grey text in the inspector, but there isn't written how to add comments
     
  5. Zinev

    Zinev

    Joined:
    Feb 8, 2017
    Posts:
    14
    Use an ordinary syntax for comments in C++ or C#: double slash. For examle:

    Code (CSharp):
    1. //commented line in the PandaBT tree
     
    StormPooper likes this.
  6. Swiggies

    Swiggies

    Joined:
    Mar 28, 2014
    Posts:
    11
    Hi, big fan of this asset. I use it in just about all my projects but I've run into a problem with Unity 2019.3f1 and Panda BT 1.4.3

    The BTs aren't run unless the gameobject has been selected in the editor. This also means that it doesn't work in a build at all. I've made sure that it isn't running and put logs everywhere I can but it doesn't even run the first task in the tree. Even moving all my tasks into a separate component didn't fix it.
     
  7. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    417
    @ericbegue Are you planning on updating this package to be compatible Unity's new Input System? Right now using any of the input tasks would cause runtime errors
     
    Zinev likes this.
  8. digitj

    digitj

    Joined:
    Jul 29, 2019
    Posts:
    2
    Hey I just started using pro version of BT panda and was wondering if it is console port friendly?
     
  9. BanzBowinkel

    BanzBowinkel

    Joined:
    Jun 17, 2015
    Posts:
    16
    Dear Eric,
    thanks for this great tool! We 've been playing around with it for some time now and it is really growing on us.
    May we ask for an example of how the Property "Task.current.item" can be implemented? We did not find much documentation on that.

    Another question is if one can find out which tree a Task is running in. Since we guess you can use Tasks in different trees we would like to customize their behaviour depending on what trees they are used in. Is that possible?

    Please keep up the good work and best, Friedemann
     
    Last edited: Mar 31, 2020
  10. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,363
    He doesn't have internet under his rock ;)
     
  11. mtdev01

    mtdev01

    Joined:
    May 17, 2017
    Posts:
    10
    Can someone help with an issue I hope is just me missing something obvious?

    Code (CSharp):
    1. tree("Logger")
    2.     repeat(5)
    3.         sequence
    4.             SetDestinationToEmployer
    5.             MoveToDestination
    6.             DropOffResources
    7.             repeat(10)
    8.                 sequence
    9.                     GetClosestResource
    10.                     SetDestinationToClosestResource
    11.                     MoveToDestination
    12.                     sequence
    13.                         FaceDestination
    14.                         HarvestResource
    15.                         Wait(1.0)
    The character completes the tree 1 time and then stops after DropOffResources succeeds the 2nd time. It never moves on to the repeat(10). Any thoughts?

    NVM - it was an error in my quadtree removal functions. Thanks
     
    Last edited: Apr 8, 2020
  12. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    417
    I wrote a simple editor script that simplifies adding very large numbers of PandaBT assets to a PandaBT script. It works by searching the same GameObject for BehaviorTreeBaseAILinker implementations and extracting their TextAssets, then adding them to the PandaBT script. However, ever since I began using it I've consistently run into my entire scene becoming corrupted, with "missing script" on all of my custom scripts. I think I implemented the editor script in a faulty way - can anyone with internal knowledge of PandaBT chime in and see what's wrong with my editor scripts?

    Code (CSharp):
    1. [RequireComponent(typeof(BehaviorTreeAILinkerAggregator))]
    2. public abstract class BehaviorTreeBaseAILinker : MonoBehaviour, IBehaviorTreeAILinker
    3. {
    4.     [SerializeField]
    5.     private TextAsset ai;
    6.  
    7.     public TextAsset GetAI()
    8.     {
    9.         return ai;
    10.     }
    11. }
    Code (CSharp):
    1.  
    2. [RequireComponent(typeof(PandaBehaviour))]
    3. public class BehaviorTreeAILinkerAggregator : MonoBehaviour
    4. {
    5.     public void ImportAILinkers()
    6.     {
    7.         var ai = GetComponent<PandaBehaviour>();
    8.  
    9.         var aiLinkers = GetComponents<IBehaviorTreeAILinker>();
    10.         var numAILinkers = aiLinkers.Length;
    11.         ai.scripts = new TextAsset[numAILinkers];
    12.         for (var i = 0; i < numAILinkers; i++)
    13.         {
    14.             var aiLinker = aiLinkers[i];
    15.             ai.scripts[i] = aiLinker.GetAI();
    16.         }
    17.     }
    18. }
    Code (CSharp):
    1. [CustomEditor(typeof(BehaviorTreeAILinkerAggregator))]
    2. public class BehaviorTreeAILinkerAggregatorEditor : Editor
    3. {
    4.     public override void OnInspectorGUI()
    5.     {
    6.         DrawDefaultInspector();
    7.  
    8.         BehaviorTreeAILinkerAggregator script = (BehaviorTreeAILinkerAggregator)target;
    9.         if (GUILayout.Button("Import AI Linkers"))
    10.         {
    11.             script.ImportAILinkers();
    12.         }
    13.     }
    14. }
     
  13. Thunderik

    Thunderik

    Joined:
    Apr 28, 2020
    Posts:
    32
    Hi!

    Is it possible to have a repeat node with a dynamic number of iterations?
     
    laurentlavigne likes this.
  14. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,363
    Guys, What's your experience regarding GC?


    Code (CSharp):
    1. repeat
    2.     sequence
    3.         ....
    4.         RepeatCondition
    RepeatCondition is a [task] that checks an internal counter inside your class
    it returns false when the counter has reached the dybamic number that could be assigned by another [task]
    or
    Code (CSharp):
    1. while RepeatCondition
    2.      repeat
    3.         .....
     
  15. Crouching-Tuna

    Crouching-Tuna

    Joined:
    Apr 4, 2014
    Posts:
    82
    upload_2020-6-13_0-50-32.png
    I can't seem to make the repeat node work. It's blue, when ticked, HasPendingAction and AxieDoAction doesn't get called again, both on their Task.isStarting and outside of it

    Actually tried the other variant (while HasPendingAction, repeat DoAction) and it's the same

    If RepeatRoot is ticked, then the tick after that just starts over. The repeat is like not there and only the sequence is in effect
     
    Last edited: Jun 12, 2020
  16. oskarious

    oskarious

    Joined:
    May 26, 2011
    Posts:
    6
    Hello,

    I am just getting started with panda (and AI programming in general), and I was wondering if it's possible to define tasks in a inherited class and have a script derive from it (and be able to override tasks if needed)? My tests so far leads me to belive it is not possible, and it might be a design choice I just haven't grasped yet.

    What I would like to do is to have a parent class define some shared idle tasks and have the child classes implement for example it's fighting behaviours. I could, of course, just have something like a BaseAI monobehaviour and a SpecificAI monobehaviour on the gameobject, but it would be nice to be able to consolidate it into one script.

    Tried searching through the thread and looking through the examples but couldn't find anything.

    Cheers!
     
    s_marcell and laurentlavigne like this.
  17. nutversion1

    nutversion1

    Joined:
    Oct 6, 2015
    Posts:
    1
    Panda Behaviour has only random fallback (selector) composite. How to use random sequence composite ?
     
  18. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    417
    I'd like to show my appreciation for how you designed PandaBehaviour to allow for OOP patterns
    • Mimic polymorphism by having a PandaBehaviour script depend on a tree that hasn't been implemented yet. Reuse the script on different GameObjects, each of which implement the missing tree their own way.
    • Mimic abstraction by hiding each Task behind a tree definition, and having other scripts depend on the tree instead of the Task. Now you can modify the contents of the tree, including switching out to an entirely different Task, without breaking anything
    • Simulate if, while, and, and or statements through creative combinations of built-in Tasks
    I'm still discovering new ways to utilize PandaBehaviour. Kudos to you for this wonderful asset!
     
    ericbegue likes this.
  19. petera1980

    petera1980

    Joined:
    Jan 29, 2016
    Posts:
    55
    Hello,
    I'm using Panda from the beginning of my project since Unity 2017 but In Unity 2019.3 I realized that my characters in game that use Panda do not execute the Tree. On pc is fine, but on Android I get this error :

    Code (CSharp):
    1. ArgumentException: [U]method arguments are incompatible[/U]
    2.   at [B]System.Delegate.CreateDelegate[/B] (System.Type type, System.Object firstArgument, System.Reflection.MethodInfo method, System.Boolean throwOnBindFailure, System.Boolean allowClosed) [0x00000] in <00000000000000000000000000000000>:0
    3.   at System.Delegate.CreateDelegate (System.Type type, System.Object firstArgument, System.Reflection.MethodInfo method) [0x00000] in <00000000000000000000000000000000>:0
    4.   at [B]Panda.BTRuntimeBuilder.Bind[/B] (Panda.BTTask task, Panda.TaskImplementation implementation) [0x00000] in <00000000000000000000000000000000>:0
    5.   at [B]Panda.BTRuntimeBuilder.Bind[/B] (Panda.BTProgram program, System.Object[] implementers) [0x00000] in <00000000000000000000000000000000>:0
    6.   at Panda.BehaviourTree.CreateProgramAndBind () [0x00000] in <00000000000000000000000000000000>:0
    7.   at Panda.BehaviourTree.Compile () [0x00000] in <00000000000000000000000000000000>:0
    8.   at Panda.BehaviourTree.Awake () [0x00000] in <00000000000000000000000000000000>:0
    What it can be ? Maybe in new .Net some Panda code is incompatible ?
     
    laurentlavigne likes this.
  20. petera1980

    petera1980

    Joined:
    Jan 29, 2016
    Posts:
    55
    I still can not find the solution. If it is possible can someone tell me if his Panda Tree works on Android ?
     
  21. Gladyon

    Gladyon

    Joined:
    Sep 10, 2015
    Posts:
    389
    I think it's coming from the fact that 'firstArgument' is null.

    You should check in debug, or add a few logs to check if it's the problem.
    If it is, and if on PC 'firstArgument' is not null, then you'll have more clues about the problem because finding out why it's null in one case and not in the other should provide the answer.
     
  22. Thunderik

    Thunderik

    Joined:
    Apr 28, 2020
    Posts:
    32
    Hey, that ought to work, thank you!
     
  23. petera1980

    petera1980

    Joined:
    Jan 29, 2016
    Posts:
    55

    As I understand the problem is that Panda call function CreateDelegate with one Boolean extra (System.Boolean allowClosed)

    Code (CSharp):
    1. System.Delegate.CreateDelegate (System.Type type, System.Object firstArgument, System.Reflection.MethodInfo method, System.Boolean throwOnBindFailure, System.Boolean allowClosed)
    2.  
    But according to Microsoft Docs no overload method with two booleans are exists for :
    static Delegate CreateDelegate(Type type, object firstArgument, MethodInfo method, bool throwOnBindFailure);
     
  24. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,363
    Solution?
     
  25. Gladyon

    Gladyon

    Joined:
    Sep 10, 2015
    Posts:
    389
    Well, it wouldn't compile if there was a signature problem.
    I think it's null on Android but not on PC; if it's the case then you can try to find why it's null.
    I think you should add some logs in Panda, in order to debug the parameter 'firstArgument'.
    If it is called too often then add a test to see if 'firstArgument' is null, and log only in that case.

    Also, what .NET version are you using? It seems that 'allowClosed' is only in Mono (I may be wrong, I only made a very quick search).
    Are you compiling Panda's code or are you using a pre-compiled dll?
    Does it happen in the editor or only in standalone?


    Note that I had some trouble with 'CreateDelegate' and similar methods when using them on a type/code I created on the fly, but obviously that was only on PC as you cannot do that on mobile.
     
  26. petera1980

    petera1980

    Joined:
    Jan 29, 2016
    Posts:
    55
    Gladyon thank you for your replay.

    I'm using free dll version.
    It is happens only in android builds. I have tried android versions from 6.0 to 8.1 in the beginning.

    I still cannot indentify the source of the error.

    In Logcat I get:

    Error Unity ArgumentException: method arguments are incompatible

    Not Null but wrong arguments.

    The problem is that is not happens to all objects with Panda component and not always.

    I have as say 80 Panda enemies on scene and only 4-5 throw error in random manner.
     
  27. Gladyon

    Gladyon

    Joined:
    Sep 10, 2015
    Posts:
    389
    Maybe the dll is compiled with a different .NET version than your project.
    If the dlls used for PC and Android are different it may not link properly in one case and properly in the other case.
    It's hard to tell if it can be that or not, I don't even know what .NET version Panda free is using.

    You could try to change the API compatibility of your project to see what happen (switching between .NET 2.0 and .NET 4.x).
    Be careful, if you're not using a versioning tool (SVN, GIT, etc.), before doing that you should backup your project.
     
  28. petera1980

    petera1980

    Joined:
    Jan 29, 2016
    Posts:
    55
    After 4 days I solve this problem. I don't know why, but for some reason Panda throw this exception on Tasks that are overridden from base class (but not for all)

    I have base class Enemy where I have about 20 tasks common for all enemies like :

    Code (CSharp):
    1.  
    2. [Task]
    3.     protected virtual void Walk()
    4.     {
    5.         movetype = MOVETYPE.WALK;
    6.         Task.current.Succeed();
    7.     }
    If I override this function in one of my enemies as say :

    Code (CSharp):
    1. protected override void Walk()
    2.     {
    3. //Enemy specific code
    4.  
    5.         movetype = MOVETYPE.WALK;
    6.         Task.current.Succeed();
    7.     }

    I got exception. But in other hand if I rewrite this function without "override" as new like

    Code (CSharp):
    1.  
    2. public class BigKnight : Enemy {
    3. [Task]
    4. void Walk()
    5.     {
    6.         movetype = MOVETYPE.WALK;
    7.         Task.current.Succeed();
    8.  }
    9.  }
    It works. As usual I make base class to avoid writing the same functions many times. But Panda don't like this.
    Some functions works as overridden but some not, so I have to to write the same function in derived class.

    After making tons of tests, finally I don't got the source of the problem.
     
    laurentlavigne likes this.
  29. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,363
    In general you don't want inheritance, you want composition.
    So you add a component per action instead. And let panda do the logic stitching. Much easier to maintain.

    Anyway, this is not a documented limitation so this is a bug. under the hood panda uses reflection. maybe eric set the flag to go only one level deep. he's not answering his email so I'll have a look in the pro code. if this works I'll only be able to help pro owners.
     
  30. petera1980

    petera1980

    Joined:
    Jan 29, 2016
    Posts:
    55
    laurentlavigne, please make this check if it worked I will get the pro version.
     
  31. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,363
    it'll take a while so in the meantime implement the base method in your override then once the compile errors are gone, comment these out... somehow it works...
    upload_2020-8-14_9-43-45.png
     
  32. petera1980

    petera1980

    Joined:
    Jan 29, 2016
    Posts:
    55
    It
    It works for me. But, in this case there is a need to write extra code , something I wanted to avoid.
    This is why I had the most used [Tasks] in the base class.

    This is my fault, I knew about this bug from be beginning when I had created my first enemy.
    Panda tree worked in the PC but in Android, character was always in Idle state due to this exception.
    I leave it for debugging at the end of game creation. Now, I have about 64 enemies.
    But I solved this problem as I told above, with rewriting all "virtual" functions in base class as new in derived class, without override tag.
    I took for me about 4 days to understand where the problem is, because it was not clear at all.
     
  33. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,363
    Ok and it only happens on android... any other platform this happens on?
    I looked in the code,here is the change and this should work, since I always want the inheritor to explicitly show what [tasks] it's capable off i never want to even test that, would encourage bad practice.
    Code (CSharp):
    1.                 {
    2.                     var typeTaskList = new List<Task>();
    3.                     var members = implementer.GetType().GetMembers(bindingFlags);
    4.                     foreach (var m in members)
    5.                     {
    6.                         var attributes = m.GetCustomAttributes(typeof(Task), true);
    7.                         foreach (var attr in attributes)
    8.                         {
    9.                             var implementationAttribute = attr as Task;
    10.                             if (implementationAttribute != null)
    11.                             {
    12.                                 implementationAttribute._memberInfo = m;
    13.                                 typeTaskList.Add(implementationAttribute);
    14.                             }
    15.                         }
    16.                     }
    17.                     // do a pass for those lazy programmers who only implement tasks only in the base class ;)
    18.                     var membersFromBase = implementer.GetType().BaseType.GetMembers(bindingFlags);
    19.                     foreach (var m in members)
    20.                     {
    21.                         var attributes = m.GetCustomAttributes(typeof(Task), true);
    22.                         foreach (var attr in attributes)
    23.                         {
    24.                             var implementationAttribute = attr as Task;
    25.                             if (implementationAttribute != null)
    26.                             {
    27.                                 implementationAttribute._memberInfo = m;
    28.                                 // find matching attr
    29.                                 bool matching = false;
    30.                                 foreach (var tt in typeTaskList)
    31.                                 {
    32.                                     if (tt._task == implementationAttribute._task)
    33.                                     {
    34.                                         matching = true;
    35.                                         break;
    36.                                     }
    37.                                 }
    38.                                 // if none then add the baseclass
    39.                                 if (!matching)
    40.                                     typeTaskList.Add(implementationAttribute);
    41.                             }
    42.                         }
    43.                     }
    44.                     typeTasks = typeTaskList.ToArray();
    45.                     taskCache[type] = typeTasks;
    46.                 }
     
  34. ratking

    ratking

    Joined:
    Feb 24, 2010
    Posts:
    350
    I have the very same problem. ("Repeat Root" also gets reset.)
    This is the Free version, and I consider buying the Pro version, but somehow it's sad that the developer is not active anymore it seems.
     
  35. Gladyon

    Gladyon

    Joined:
    Sep 10, 2015
    Posts:
    389
    True enough.
    That said, with the Pro version you'll have the source code, so you'll be able to fix the problems which may arise in the future.
    And there shouldn't be that many problems since the code isn't relying so much on Unity.
     
  36. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,363
    there are 2 problem: pro editor never worked right -> edit within rider, reflection caching happens on each instance instead of at edit time = on mobile you really feel the sting -> dunno how to serialize the result the reflection cache?
     
  37. Clavus

    Clavus

    Joined:
    Jun 6, 2014
    Posts:
    62
    Hi, I've got a question regarding garbage generation. I'm working on an external project that makes use of PandaBehaviour for its enemy npcs. We've got about 7 instances of a particular enemy in a scene and we see that BehaviourTree.Update (the closed-source class from which PandaBehaviour is derived) generates about 2.0kb of garbage every frame according to the profiler (attached to a build). The behaviour tree of this enemy has about 170 lines, I'm not too sure what to look for as to what could cause this in the tree design itself. Is there anything to look out for?
     
  38. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,363
    Last time I used it BT generated 0kb of garbage after init so deep profile it because it may come from your custom nodes.
    And wow 170 lines of BT is a lot for an enemy AI, what do they do?
     
  39. dARTillery

    dARTillery

    Joined:
    May 14, 2020
    Posts:
    7
    Hi
    I would like for my tree to wait a random value, I used a tree like
    Code (CSharp):
    1. random
    2.                     Wait(5.0)
    3.                     Wait(6.0)
    4.                     Wait(7.0)
    5.                     Wait(8.0)
    6.                     Wait(9.0)
    7.                     Wait(10.0)
    but what if I want to be able to dynamically change that, between a min and max value, that I can easily change in the editor?

    thanks.
     
  40. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,363
    you cannot inject variable within panda as it has no blackboard, all injection is done through c# so you'll need to make your own waitrandom class
     
  41. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    417
    Is recursion possible in Panda BT? For example, the following

    tree Attack
    sequence
    tree Right
    tree Left​

    tree Right
    sequence
    tree Valid
    tree Attack​

    tree Left
    sequence
    tree Valid
    tree Attack​


     
  42. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,363
    no, BT don't allow cycles. what you do is simply let the sub tree exit
     
    Abbrew likes this.
  43. jnbbender

    jnbbender

    Joined:
    May 25, 2017
    Posts:
    487
    Is anyone using Panda these days? It looks like a great asset. I know it's not being developed any longer and maybe the author might consider licensing it under MIT ;). But if anyone is interested on finding support and sharing plugins I've setup a Discord channel. https://discord.gg/Ppgjn6An
     
  44. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,363
    Also the dev added GOAP to Panda! I only use FSM nowadays.
     
  45. jnbbender

    jnbbender

    Joined:
    May 25, 2017
    Posts:
    487
    Yeah. I emailed him about putting a Discord link on his Asset Store page and heard nothing. I also ran one of this Demo scenes, patrollers vs you and the system couldn't keep up. A lot of lag & stuttering. I don't think Panda is an option anymore.
     
  46. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,363
    off memory the demo scenes bombard physix with an unreasonable amount of overlap raycast queries. performance hit wasn't panda as much as something you never ever do in AI: tick every frame
     
    jnbbender likes this.
  47. Thunderik

    Thunderik

    Joined:
    Apr 28, 2020
    Posts:
    32
    What? Where is the GOAP system?
     
  48. ratking

    ratking

    Joined:
    Feb 24, 2010
    Posts:
    350
    The invite link became invalid.
     
  49. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,363
    It's a separate module that sits on top of GOAP. Should be in the official asset. If not, ping me and I'll see with him.
     
  50. mtdev01

    mtdev01

    Joined:
    May 17, 2017
    Posts:
    10
    Is there a way to get in contact with the asset owner?