Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

[Updated] DecisionFlex: AI toolkit for emergent and human-like decision making

Discussion in 'Assets and Asset Store' started by andrew-fray, Nov 18, 2014.

  1. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    This is minor, but I noticed in the update's timeslice demo, the ship never takes a shot at the UFOs. That demo worked in the previous release. (I'm on 5.5.0p1 if it matters.)
     
  2. andrew-fray

    andrew-fray

    Joined:
    Jul 19, 2012
    Posts:
    149
    @MV10 Huh interesting - cuz it was always broken before and this update was meant to fix it! I clean-installed it on 5.5.2 and it worked. Can you try nuking your demos folder and re-importing the updated package?
     
  3. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    Weird. Re-import fixed it. However, it did work for me in the previous release... oh well.
     
    andrew-fray likes this.
  4. betaFlux

    betaFlux

    Joined:
    Jan 7, 2013
    Posts:
    110
    Hello, I have a question about DFlex's usage.


    In my scenario I'm trying to get the ai to decide when to reload a gun:

    Code (CSharp):
    1. public class CombatContextFactory : SingleContextFactory {
    2.  
    3.     Weapon drawnWeapon;
    4.  
    5.     public override IContext SingleContext(Logging loggingSetting) {
    6.  
    7.         ContextDictionary context = new ContextDictionary();
    8.  
    9.         if(drawnWeapon.isReloadable) { // Set reload specific context
    10.  
    11.             context.SetContext("ammoCountInWeapon", AmmoCountInWeapon());
    12.             context.SetContext("ammoCountInInventory", AmmoCountInInventory());
    13.         }
    14.         return context;
    15.     }
    16. }
    My problem is, that the code above results in a "KeyNotFound" Exception. Probably because the actual considerations in the hierarchy can't find the "reload" specific stuff, if the agent has a melee weapon equipped.

    Now, if the NPC equips a reloadable weapon afterwards (so the "isReloadable" succeeds), the error keeps appearing every frame.

    Is there a more convenient way to selectively enable/disable specific context content? How do you people handle it?

    Even the slightest advise would be very welcome!
     
    Last edited: Feb 24, 2018
  5. andrew-fray

    andrew-fray

    Joined:
    Jul 19, 2012
    Posts:
    149
    @betaFlux I would push a isReloadable bool to the context, and _always_ push your ammo counts, setting them to 0 when ignorable. Then use a bool consideration in your action to score 0 when isReloadable is false. Hope this helps, let me know if you get it working or have further questions.
     
    betaFlux likes this.
  6. betaFlux

    betaFlux

    Joined:
    Jan 7, 2013
    Posts:
    110
    That works. Thanks for your answer, Andrew!

    I have another question:

    I'm trying to do certain things exactly once inside the Action.Perform function.
    So I try to do that using a flag:

    Code (CSharp):
    1. bool flag;
    2. public override void Perform(IContext context) {
    3.    
    4.             if(flag == false) {
    5.  
    6.                 flag = true;
    7.              
    8.                 PickUpObject();
    9.             }
    10.     }
    Where would I best reset or initialize stuff before the action runs every frame, or where would I best call an Init() function if I wanted to create one?
     
    Last edited: Feb 24, 2018
  7. andrew-fray

    andrew-fray

    Joined:
    Jul 19, 2012
    Posts:
    149
    Huh that's a good request, @betaFlux! Is it possible to refactor the problem to not need the flag? Maybe by subscribing to DecisionFlex.OnNewAction? If not, maybe you could hack something into DecisionFlex.PerformAction() to send an init message or similar? foreach(var actionGroup in m_actions) { foreach(var action in actionGroup.Actions) { action.Reset(); } }?
     
  8. betaFlux

    betaFlux

    Joined:
    Jan 7, 2013
    Posts:
    110
    @andrew-fray, thanks for the suggestion! I had it all wrong I guess. In my scenario (using RegularDecisionTicker) PerformAction() and thus OnNewAction are called in quick succession, so resetting makes no sense. I have to find another way to handle actions that take longer and should only be re-invoked after a reasonable delay.

    If I may ask another question:

    Creating one huge ContextFactory and mixing everything together seems like bad practice. That's why I would like to have multiple DFlex hierarchies, one for each main state (combat, sandbox, etc.). Is this ok to do or is there any drawback other than decrease in performance?
     
  9. andrew-fray

    andrew-fray

    Joined:
    Jul 19, 2012
    Posts:
    149
    There's no drawback to multiple hierarchies - you just can't nest them. They're not even that inefficient. Your preference depends very much on what "everything" means for you. If it's all one decision, "what do I do next", then put it together. If it's multiple decisions - "what cover do I want", "which enemy is the best to shoot" - split it up.
     
    betaFlux likes this.
  10. betaFlux

    betaFlux

    Joined:
    Jan 7, 2013
    Posts:
    110
    Thanks @andrew-fray, that's good news!

    I'm currently thinking about creating a reusable hierarchy, accessible to all AIs in the scene. Some kind of Master Object that carries all the necessary DFlex (i.e. profession) behaviours. AIs with certain professions would register to their respective behaviour. This way one would avoid duplicating DF trees for each individual AI.

    Anyone ever took this approach using DecisionFlex? How did it go?
     
    Last edited: Feb 28, 2018
  11. andrew-fray

    andrew-fray

    Joined:
    Jul 19, 2012
    Posts:
    149
    Not personally, but I don't see why it wouldn't work. This could be a good approach for runtime tweaking, because you can just edit one hierarchy and affect all entities in the scene!
     
  12. betaFlux

    betaFlux

    Joined:
    Jan 7, 2013
    Posts:
    110
    For anyone interested in doing certain variable assignments only once a different Action is chosen: I added a virtual Reset() function to IAction and added the following to DecisionFlex.cs inside PerformAction():

    Code (CSharp):
    1.  
    2.  
    3. // Added another ActionSelection class member called 'prevActionSel'
    4.  
    5. ActionSelection winningAction = ChooseBestAction();
    6.  
    7. if (winningAction.IsValid == false) {
    8.  
    9.       return ActionSelection.Invalid;
    10. }
    11.  
    12. if(prevActionSel.Actions != null
    13.                 && prevActionSel.Actions.Equals(winningAction.Actions) == false) {
    14.  
    15.  
    16.  
    17.       for(int i = 0; i < prevActionSel.Actions.Count; ++i) {
    18.  
    19.  
    20.  
    21.             prevActionSel.Actions[i].Reset();
    22.  
    23.       }
    24.  
    25. }
    26.  
    27. prevActionSel = winningAction;
    I'm doing this, because the OnNewAction() callback by itself is called everytime PerformAction() is called, which is very often when using EveryFrame Ticker or Regular Ticker with short intervals. But I really only want to call an event once a different action is chosen. This kind of works, but sometimes Reset() is still called a few more times than expected.

    If anyone knows a more elegant way, please let me know!
     
  13. andrew-fray

    andrew-fray

    Joined:
    Jul 19, 2012
    Posts:
    149
    Nice work! I wonder if it's being inconsistent because you're not clearing the prevActionSel when the winning action is invalid?
     
    betaFlux likes this.
  14. betaFlux

    betaFlux

    Joined:
    Jan 7, 2013
    Posts:
    110
    @andrew-fray Not able to test this soon but it sounds like this will solve the issue. Thanks again!
     
    andrew-fray likes this.
  15. andrew-fray

    andrew-fray

    Joined:
    Jul 19, 2012
    Posts:
    149
    DecisionFlex is currently 20% off for Pro and Plus subscribers, until May 31st!
     
  16. RendCycle

    RendCycle

    Joined:
    Apr 24, 2016
    Posts:
    330
    Is this fully compatible with Unity 2018.1? Can it handle swimming/flying creatures without the need for Navmesh? Or maybe even flocks/swarm?
     
  17. andrew-fray

    andrew-fray

    Joined:
    Jul 19, 2012
    Posts:
    149
    @RendCycle DecisionFlex is a generic tool for making better decisions. Unfortunately not a steering framework. But if you already had a steering framework, you could maybe use DFlex to make state changes or (with some hacking) weight behaviours against one another.
     
  18. RendCycle

    RendCycle

    Joined:
    Apr 24, 2016
    Posts:
    330
    Alright, thanks for that info! :)
     
  19. Remixful

    Remixful

    Joined:
    Jan 12, 2013
    Posts:
    7
    What do I do about context that does not exist yet? For example, items that aren't in the inventory yet.
     
  20. andrew-fray

    andrew-fray

    Joined:
    Jul 19, 2012
    Posts:
    149
    @Remixful I can help but can you give me a more concrete example? If you want (eg) an action that chooses to glug a potion, but only if that potion is in the inventory, your context can store "potion: 0" and then you can use a BinaryContextConsideration to score that action with 0 if there's no potions.
     
  21. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    596
    so this is supported?
    its been over a year since the last update.

    also how does this compare to Apex Utility AI?
    What are the major differences?

    it seems apex is more advanced with visual graphs and stuff, but also more expensive.
     
    Last edited: Jan 17, 2019
  22. andrew-fray

    andrew-fray

    Joined:
    Jul 19, 2012
    Posts:
    149
    @luniac it's definitely "supported"; I will fix bugs and compatability problems, there just haven't been any for a while. Which is a good thing!

    The main difference between DFlex and Apex (apart from the price) is that Apex bills itself as a foundational framework - you build your whole game AI around it. DFlex is merely a tool to make individual decisions. Think of DFlex like a really really good hammer, for when you have bang in some juicy nails. Maybe you have a lot of nails in your project, or maybe there's just one big stubbon nail. DFlex will work either way.
     
    luniac likes this.
  23. Remixful

    Remixful

    Joined:
    Jan 12, 2013
    Posts:
    7
    Let's take the UFO example. What if we wanted to make the "enemy" ship controlled by DFlex to switch weapons and stuff like in the Weapon Selection Example. How do we make the enemy ship consider UFOs that are not in the scene yet?
     
  24. andrew-fray

    andrew-fray

    Joined:
    Jul 19, 2012
    Posts:
    149
    @Remixful the enemy ship would return a list of Contexts from its ContextFactory, one for each UFO. In each context it could have data about the distance to and the health of the UFO. Since the context list is generated every time the enemy ship wants to make a decision, it would include new UFOs that had appeared since last time, and not include UFOs that had been destroyed. It would be very similar to how the weapon selection demo makes one context per enemy. Hope that helps, happy to keep answering questions.
     
  25. Remixful

    Remixful

    Joined:
    Jan 12, 2013
    Posts:
    7
    @andrew-fray Thanks for the quick reply! The problem I have with that is let's say no UFOs are in the scene, the considerations throw an error since distance and health do not exist.
     
  26. andrew-fray

    andrew-fray

    Joined:
    Jul 19, 2012
    Posts:
    149
    @Remixful if your context factory is returning an empty list of contexts, because there's no UFOs, then DecisionFlex.PerformAction() will return ActionSelection.Invalid. It shouldn't throw any errors. Can you post what your context factory looks like?
     
  27. Remixful

    Remixful

    Joined:
    Jan 12, 2013
    Posts:
    7
    @andrew-fray My project has more than just the enemies in the context factory. Like ammo and health, so it's not empty.
     
    andrew-fray likes this.
  28. andrew-fray

    andrew-fray

    Joined:
    Jul 19, 2012
    Posts:
    149
    It sounds to me like you're just describing the soldier/weapon demo. There's one context per enemy, each including info about the enemy as well as ammo counts for the soldier. Have a look at how that one works, and get back to me.
     
  29. DR_Studio

    DR_Studio

    Joined:
    Aug 4, 2018
    Posts:
    5
    How does your product fare when using it for boss behavior? I am looking for assets that can give the enemies options for attacking, knowing which ally to heal, and to perform certain attacks at certain HP percentages or attack differently depending on which objects are in the scene.

    So far this asset sounds like that great film that everyone has seen except me.