Search Unity

NodeCanvas - (Behaviour Trees | State Machines | Dialogue Trees)

Discussion in 'Assets and Asset Store' started by nuverian, Feb 8, 2014.

  1. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64

    Hello again,

    I have commented 2 lines of code:

    in ConditionList
    Code (csharp):
    1. finalText += conditions[i].taskInfo + (i == conditions.Count -1? "" : "\n" );
    in ActionList
    Code (csharp):
    1. finalText += (actions[i].isRunning? "► " : "") + actions[i].taskInfo + (i == actions.Count -1? "" : "\n" );
    And the graph as finally loaded. The FSM and nested FSMs struture is intact, but all actions and conditions have dissapeared, so it's not the best outcome but it is not the worst either. Upon "touching" every state and condition and saving the FSM, I have restored those previous lines and now I can open it without problems.

    I don't know what caused this: either moving the custom scripts to other files or changing their category. Now everything works again and I'm assigning all the actions and conditions again.

    Thanks and sorry for the trouble :p
     
  2. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Yes that is correct but I am thinking of adding a type selection for Component variables so that a reference doesn't have to be assigned. I will see to it though. Can't say for sure :)

    You are welcome. That's why I am here ;)


    Hello again,

    Just renaming the category couldn't be the cause of this. Did you deleted or renamed a condition class name? It seems that some condition in a list somehow became null. Of course all these errors shouldn't come up and that's on me.
    I've fixed those errors comming up now and the editor to open as it should, although it won't fix if the actual script was renamed.
    It's very weird that you lost ALL your actions and conditions. Did you maybe renamed all of them or did something else?

    :(

    Hello there,
    Unfortunately, it's not totaly up to us the authors as of when our asset can/will go on sale, so I can't see it coming on sale any time soon again. Sorry about it :)
     
  3. cAyouMontreal

    cAyouMontreal

    Joined:
    Jun 30, 2011
    Posts:
    315
    Alright thanks for the really quick answer, I didn't know that you guys can't decide when go on sales...
    I don't really need this plugin immediately, I'll keep an eye on the next sales ;)
    I can't wait to replace my current own state machine system with this one :p
     
  4. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Sure. Lets hope it goes on one again soon :)

    Best regards
     
  5. bkw

    bkw

    Joined:
    Sep 20, 2013
    Posts:
    49
    Nuverian, I sent you a PM about me trying to add a custom type to the blackboard. I didn't want to flood this thread with code.

    What I have so far seems to work, but since I don't know the intricacies of NC, it might be broken elsewhere. It definitely doesn't deal with serialization at all, but I don't think I'm going to use that feature. (I don't think serializing my class actually works with the way I have things setup in my game.)

    If the code looks ok, then at worst I can wrap all my custom data into custom classes if i wanted them on the BB. (Like instead of GetDataValue<List<Player>>(); , I create a PlayerList class that holds a public List<Player>. Not sure if this will make things easier or more complicated though. =D )
     
  6. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
    I found the error, I got enthusiastic with the custom actions and at the end, without realizing it, I rearranged them in Monodevelop. Meaning Unity and thus NC had no idea where my classes where now, and I have lots of "The referenced script on this Behaviour is missing!" in a lot of FSMState_Node.

    I won't ever forget this again :)

    Sorry for the trouble!
     
  7. nixter

    nixter

    Joined:
    Mar 17, 2012
    Posts:
    320
    I'm testing changing Blackboard strings with BTActions. I've found the Interop:SetBoolian and Interop:SetFloat actions. I can't find any Interop:SetString action.

    How are we supposed to change strings in the Blackboard? :confused:
     
  8. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Thanks for keeping it clean :)
    I've read the PM. It looks like you've found your way around the code :) Yes that's prety much correct overal, although as the code I've posted a couple of posts above the BBValue will be much easier in next version. The rest are probably going to stay the same for now.
    My personal opinion is that it's going to make things more complicated :p, but I guess it will show. Maybe it works for you.

    Oh, I think I understand. Dont mention it. That's why I am here :)


    Hey again,
    I've omited adding such an action. Here is action to set a string as well as a simple condition to check if 2 string are the same just in case :) :

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using NodeCanvas.Variables;
    4.  
    5. namespace NodeCanvas.Actions{
    6.  
    7.     [ScriptCategory("Interop")]
    8.     public class SetString : ActionTask {
    9.  
    10.         public BBString stringA = new BBString{blackboardOnly = true};
    11.         public BBString stringB;
    12.  
    13.         protected override string actionInfo{
    14.             get {return "Set " + stringA + " = " + stringB;}
    15.         }
    16.  
    17.         protected override void OnExecute(){
    18.             stringA.value = stringB.value;
    19.             EndAction();
    20.         }
    21.     }
    22. }
    23.  
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using NodeCanvas.Variables;
    4.  
    5. namespace NodeCanvas.Conditions{
    6.  
    7.     [ScriptCategory("Interop")]
    8.     public class CheckString : ConditionTask {
    9.  
    10.         public BBString stringA;
    11.         public BBString stringB;
    12.  
    13.         protected override string conditionInfo{
    14.             get {return stringA + " == " + stringB;}
    15.         }
    16.  
    17.         protected override bool OnCheck(){
    18.             return stringA.value == stringB.value;
    19.         }
    20.     }
    21. }
    22.  
    Here is a .zip as well
    View attachment $StringTasks.zip

    You can place them anywhere you like, but preferably the action in the NodeCanvas/Tasks/Actions
    and the condition in the NodeCanvas/Tasks/Conditions folders for convenience :)
     
    Last edited: May 15, 2014
  9. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Please redownload if you had any issues. I fixed the typos. I am so asleep :)
     
  10. nixter

    nixter

    Joined:
    Mar 17, 2012
    Posts:
    320
    Thank you very much for that quick response with the necessary code! :)

    Seeing as how the Billboard Component is such an important part of the NodeCanvas system, it would make sense to have Get/Set Conditions/Actions for each of the datatypes. Perhaps you could make Bilboard nodes their own category as well: Blackboard:Set[Datatype] Actions and Blackboard:Get[Datatype] Conditions. Interop could then be reserved for dealing with scripts outside of NodeCanvas.

    Just a suggestion.
     
  11. vidjo

    vidjo

    Joined:
    Sep 8, 2013
    Posts:
    97
    This may be a bug:

    In an FSM, if i add a nested BT then make it the start node, the previous start node just becomes ane empty box graphically.
     
  12. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Im sure you mean Blackboard :)
    Yes, I will do that. Sounds correct.

    Thanks for suggestions.

    Hey there,

    Hmm. I can't seem to reproduce that. Here is what I do:

    1. Create an FSM
    2. Add a state (which is automaticaly marked Start)
    3. Add a NestedBT
    4. Mark NestedBT as Start

    Yes if it's shown as empty box it might be a UI bug there. Are you able to reproduce that?

    Thanks!
     
  13. bkw

    bkw

    Joined:
    Sep 20, 2013
    Posts:
    49
    To clarify, what does [RequiredField] on a BBValue actually require? It's not the BBValue referencing valid "data" (or variable) on the blackboard, but rather the "data value" IN the BB variable right?
     
  14. bkw

    bkw

    Joined:
    Sep 20, 2013
    Posts:
    49
    This is probably more a generic BT question, but are conditions on a connection, accessor decorator, interruptor decorator, and condition node (along with say a sequence composite), all really achieving the same thing?

    Is there performance/usage advantages and disadvantages for each?

    I currently have conditions on connections, but that seems to be the least flexible, since I can not duplicate them and they disappear when I delete the connection (thus I can't re-wire things as easily). Though it does make things cleaner visually in the editor and is looks a little more intuitive since they appear more like "transition conditions" (a la FSMs).
     
  15. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    The [RequiredField] requires the .value of that BB field to not be null, either the one on the blackboard or the one 'inside', depending on where it is set to read/write from, either in the editor or from code.
    If it is set to to to read/write from the blackboard then it requires the varialble of the blackboard to not be null.
    If it is set to read/write the direct value, then the direct not to be null.

    So when you get .value it will not be null in any case.

    This is a nice question :)
    While all are there to change the flow of the BT based on some condition, they do so in a somewhat different manner.

    An Interruptor will interrupt it's child node if it's running and return Failure immediately when it's condition is/becomes true.
    So the condition here is checked whenever the Interruptor is executed. Resting or Running.

    In the contrary...
    An Accessor will execute it's child node if the condition is true. If the condition becomes false while the node is still running it will wait for it to end though.
    So the condition here is checked when the Accessor is Resting, NOT Running already.

    $ExampleInterruptor.png
    In this example, when the tree is running, we will see 'hello' and then 'world'. If while the 'hello' is running we press Space, the action will be interrupted immediately then we will again see 'hello'.

    $ExampleAccessor.png
    In this example, when the tree is running, we will see nothing, because the accessor's condition is false (thus returns Failure). When we press Space we will see 'hello' and then 'world'. Even if the condition is no longer true in the next frame from which we pressed Space, the 'hello' will not be interrupted and show up for 1 second.
    The same can be achieved with a Condition Node at the start of a non-dynamic Sequencer.

    The condition on connections is still there mostly for backwards compatibility from before the above said nodes were in there. It's mostly like an interruptor.
    Of course you can use them, but it's not that flexible as you've noticed.

    I would strongly recomend that you work with Condition Nodes and Interruptors only, until you get a good hang of the Behaviour Trees.
    By the way, you can achieve most things with Sequencers, Selectors, Condition Nodes and Action Nodes alone.

    I hope I didn't confuse you :)
     
  16. bkw

    bkw

    Joined:
    Sep 20, 2013
    Posts:
    49
    Great explanation. Thanks!
     
  17. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    I'm glad it wasn't confusing. You are welcome :)
     
  18. bkw

    bkw

    Joined:
    Sep 20, 2013
    Posts:
    49
    Are action lists exactly the same as sequencers that only have action nodes as children? (minus dynamic/random functionality)
     
  19. RagingJacob

    RagingJacob

    Joined:
    Jun 19, 2013
    Posts:
    72
    I'm convinced Node Canvas is the better FSM available on the asset store,
    not to mention pretty to look at as well in comparison to other Node based plugins.

    However, Nuverian, could we please get some more examples,
    things that quickly come to mind :
    -Game modes (TDM, CTF, LMS, etc. etc.)
    -Game types (RTS, FPS, Stealth, etc. etc.)
    - etc. etc.

    Obviously these would be very very simple examples to get people warmed up, perhaps even do these in conjunction with tutorial videos.
    It doesn't have to be my suggestions but anything you think could be useful and could ease the user into using Node Canvas.

    Thanks again for this beautiful peace of software!

    Good luck and more power to you ;)

    Kind Regards
     
  20. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Yes, that is correct. The actions in the list will play in sequence. It's nice if you want to group up some actions.

    Hello,

    Thank you for considering NC as such :)
    I know such examples are missing, but the TODO list of NodeCanvas is always swarmed with imrpovements, fixed and features.
    I will see to add some game examples as soon as possible. I know that is something needed.

    Thanks and best regards,
    Gavalakis Vaggelis
     
  21. bkw

    bkw

    Joined:
    Sep 20, 2013
    Posts:
    49
    Is using the keyboard the only way to delete FSM connections?
     
  22. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Yep, Sorry.
    I could add a small "X" button on the connection inspector though.
     
  23. tomi-trescak

    tomi-trescak

    Joined:
    Jul 31, 2013
    Posts:
    78
    Gavalakis, amazing job with NodeCanvas, students at University of Western Sydney love it!

    We have a question, is there a possibility to run two branches in parallel? The "parallel" control is not behaving the way we need.
    We have an NPC that is throwing stones at people (not very nice I know).

    In the BT I need that NPC is constantly turning towards the player and in the other branch I solve the throwing logic, i.e. playing animation, releasing the stone a.s.o.

    Currently, the only way we have it working, that NPC turns towards player right before the stone is released, what does not look good.

    Any idea?
    Thanks!
     
  24. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Hello Tomi,

    Thanks! I'm glad to hear that :)

    You can force a child node to repeat like so:

    $ParallelRepeat.png

    So here the Parallel is set to First Success which means that it will return Success as soon as the first child returns Success.
    In the end the Parallel will return Success when the 'throw stones' returns Success and the LookAt will be repeatedly executed.

    Thinking of this, I will add a Repeat Forever option in the Repeater Decorator.

    Let me know if this works for you.

    Best regards
     
  25. bkw

    bkw

    Joined:
    Sep 20, 2013
    Posts:
    49
    What's an elegant way to do this...

    Say I have three long-running action branches, idle, patrol, and attack. While in the idle or patrol branch, I want to trigger an immediate switch the the attack branch on an event. Initially I thought of putting the three branches under a dynamic selector, then with the attack branch being the "first" branch, it has an accessor that checks for the event. This doesn't work though, because once the accessor fails, it'll always be in failed state until it gets reset.

    I guess my misunderstanding is that I expected composites to reset a child after the child has returned success or failure. Currently nodes only get reset when an entire tree traversal is complete right?
     
  26. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Hey,

    Nodes that need reset do so after a tree traversal yes, but certain nodes also reset their child under circumstances like for example Repeater and Interruptor. Dynamic Selectors and Sequencers also reset the current running child based on the return of a higher priority children.

    Events are a bit tricky to handle because the condition returns true only for one frame. Indeed the best candicates for using events would be an Accessor or an Interruptor.

    I suppose this is what you are after?

    $Accessor.png

    Your way of thinking is totaly correct and thankfuly led down to a mistake I had in the Accessor. I've fixed that now and what you are after to do will indeed happen. I PMed you the fix as well.


    The exact opposite would be to use an Interruptor above both Patrol and Idle branches (possibly under a Selector) and interrupt them if the event takes place, but that will lead to a bit unothodoxal design since you will have to have the Attack branch on the right, whereas it is supposed to be of higher priority.

    So if you definetely want to use events, your initial though is a good way to go.
    PM send ;)
     
  27. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    So I'm about to submit new version 1.4.4
    Here is what's new/changed:

    • It's now possible to select an Override Agent from the blackboard for tasks, instead of only direct assignment. Allows for much flexibility.
    • List<T> will now show up for inspection in the editor. You can also use List<BBFloat> for example.
    • Behaviour Tree Repeater now has an option to Repeat Forever.
    • Behaviour Tree Probability Selector can now be assigned probability values from the blackboard. This allows to change probability dynamicaly.
    • Action/Condition Tasks can now be copy/pasted.
    • Nested BT and Nested FSM Graph Name in FSMs, will get their name from the state name.
    • FSM Transition can now be prioratized.
    • FSM. Alt + Click on a state will debug enter that state in the editor.
    • FSMs will now store their last state. ( access with previousStateName property )
    • Blackboard Component variables can now be set to a specific Component derived type.
    • Made much easier to add custom BBTypes.
    • Improved Action Condition Lists to take up minimum space. The compact list is kept but only one Task is shown full at a time.
    • Nested graphs can now be opened with Double Click on the node.
    • Dialogue MultipleChoice. Choices will no longer get removed when disconnecting a child node.
    • Removed BB value information that was shown bellow such a control in the inspector, to clear up things.
    • Added small "X" button on connection inspector to remove connections.
    • Fixed Behaviour Tree Accessor Decorator.
    • Fix bug with override agent when graph was cloned.
    • Fix List editor window.
    • Fixed move actions.
    • Cleaned up some code.
    • Added agent speed and keep distance to move actions.
    • CheckTrigger CheckCollision can optionaly save the other gameobject.
    • Added some more Tasks.

    Moreover I've added two very simple Expression Condition and Action Tasks in which you can write things like so to check or set blackboard float, int and boolean variables:

    "myFloat += myOtherFloat"
    "myFloat >= 14"
    "myBool != false"
    etc...

    I hope I didn't miss any important request
    If so, let me know. Maybe there is time :)
     
  28. yankijp

    yankijp

    Joined:
    Dec 10, 2012
    Posts:
    12
    Hiya,

    Unfortunately without being able to build to that platform I don't think will be able to fix the issue(s) with windows app store as the API changes of what is supported really should be tested against.

    First error when building:

    Assets\NodeCanvas\Scripts\Core\Blackboard\Blackboard.cs(8,36): error CS0234: The type or namespace name 'Formatters' does not exist in the namespace 'System.Runtime.Serialization' (are you missing an assembly reference?)

    So I edited the code just to get around the error. Then I get a bunch of other errors including:

    Assets\NodeCanvas\Scripts\Core\Blackboard\Blackboard.cs(161,51): error CS1061: 'System.Type' does not contain a definition for 'IsAssignableFrom' and no extension method 'IsAssignableFrom' accepting a first argument of type 'System.Type' could be found (are you missing a using directive or an assembly reference?)

    Assets\NodeCanvas\Scripts\Core\Graph\NodeBase.cs(46,41): error CS1928: 'System.Type' does not contain a definition for 'GetCustomAttributes' and the best extension method overload 'System.Reflection.CustomAttributeExtensions.GetCustomAttributes(System.Reflection.MemberInfo, System.Type, bool)' has some invalid arguments


    Assets\NodeCanvas\Scripts\Core\Graph\NodeBase.cs(46,41): error CS1929: Instance argument: cannot convert from 'System.Type' to 'System.Reflection.MemberInfo'


    Assets\NodeCanvas\Scripts\Core\Graph\NodeBase.cs(238,47): error CS1061: 'System.Type' does not contain a definition for 'GetFields' and no extension method 'GetFields' accepting a first argument of type 'System.Type' could be found (are you missing a using directive or an assembly reference?)



    Assets\NodeCanvas\Scripts\Core\Tasks\Task.cs(69,46): error CS1928: 'System.Type' does not contain a definition for 'GetCustomAttributes' and the best extension method overload 'System.Reflection.CustomAttributeExtensions.GetCustomAttributes(System.Reflection.MemberInfo, System.Type, bool)' has some invalid arguments


    Assets\NodeCanvas\Scripts\Tasks\Actions\ExecuteFunction.cs(54,121): error CS0117: 'System.Type' does not contain a definition for 'EmptyTypes'


    Assets\NodeCanvas\Scripts\Core\Tasks\Task.cs(269,44): error CS1929: Instance argument: cannot convert from 'System.Type' to 'System.Reflection.MemberInfo'

    Assets\NodeCanvas\Scripts\Tasks\Conditions\CheckCSharpEvent.cs(25,46): error CS0117: 'System.Delegate' does not contain a definition for 'CreateDelegate'

    I was testing it as non of the behavior tree solutions in the asset store support Windows store and I need a solution.

    Thanks!
     
  29. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Hello,

    Thanks for the errors on building for Window App Store. They gave a base point to research against.
    I will see what I can do to make it compatible. If these are the only errors, or form of errors, then I think it should be possible from what I've read until now.
     
    Last edited: May 22, 2014
  30. msl_manni

    msl_manni

    Joined:
    Jul 5, 2011
    Posts:
    272
  31. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
  32. msl_manni

    msl_manni

    Joined:
    Jul 5, 2011
    Posts:
    272
    I suppose I would need an Enemy Manager who keeps track of all enemies and allows only a certain no of enemies who can attack. All enemies will have their own behavior tree which will encircle the player, then register with Enemy Manager as attacker, and only attack when Enemy Manager lets them do.

    Enemy Manager should have a ListOfAttackers, to which Enemies can register as Attacker.
    Enemy Manager mantains ListOfAttackers, to which Enemies can register/unregister as Attacker.
    Enemy Manager can choose certain no of random enemies who can attack.
    Enemy Manager will unregister an Enemy Attacker when Enemy Attacker dies.

    I would like to know how to implement the Enemy Manager - ListOfAttackers and Enemies register/unregister from that List.
     
  33. bkw

    bkw

    Joined:
    Sep 20, 2013
    Posts:
    49
    When I try to add a remapped decorator, the node is broken. Any idea what's up?

    $Screen Shot 2014-05-23 at 11.30.48 AM.png
     
  34. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Hello,
    Sorry for late reply.

    Here are 2 ideas that may get you started.

    The first is to control all enemies from within that EnemyManager. That manager can hold a gameobject list blackboard variable of all the enemies and iterate each one. By using a Setter decorator under the Iterator, we can change the target agent within the tree dynamicaly. So everything under the Setter will be performed by that new set agent, which in this case is each enemy.
    In this example there is no sophisticated register/unregister in the list. We rather just set that list by getting all gameobject of tag 'Enemy', but do this every 2 seconds for performance since GetObjectOfTag is slow, by using a Limiter decorator.
    The Sequencer under the Setter simply checks a probability, does a distance check of the (new) agent towards the 'target' gameobject variable (player) and finaly there is a placeholder action there. That action will be performed by the enemy since it's also under the Setter branch.
    So this is the starting point of a way to control all enemies within one BT.

    $Manager.png


    Another way to do this would indeed be to have a Behaviour Tree for each Enemy gameobject. In this case we will need to inform that enemy's Behaviour Tree that is eligable to attack for example. Here I've replace the placeholder action with a modified SendEvent action (code bollow) . Because the Action is under the Setter, the event will be send to the new agent's tree instead of this Behaviour Tree. I've also modified the tree a bit so that that all enemies in the list are iterrated every 1 sec.
    So in a few words, Every 1 sec, all enemies will be iterated. If an enemy pass the condition checks then an event 'ATTACK' will be send to the BT of that enemy.

    $ManagerEvent.png

    And here is the BT of the enemy. The condition here checks if the event 'ATTACK' is received.

    $Enemy.png

    Alternatively you could use more self contained custom Action/Condition tasks specific to your design goals.

    Here is the modified SendEvent action. I will keep this one, so feel free to replace the current included one that you have :) :
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using NodeCanvas.Variables;
    4.  
    5. namespace NodeCanvas.Actions{
    6.  
    7.     [ScriptCategory("Interop")]
    8.     [AgentType(typeof(GraphOwner))]
    9.     public class SendEvent : ActionTask {
    10.  
    11.         [RequiredField]
    12.         public BBString eventName;
    13.         public BBFloat delay;
    14.  
    15.         protected override string actionInfo{
    16.             get{ return "Send [" + eventName + "]" + (delay.value > 0? " after " + delay + " sec." : "" );}
    17.         }
    18.  
    19.         protected override void OnUpdate(){
    20.  
    21.             if (elapsedTime > delay.value){
    22.                 (agent as GraphOwner).SendEvent(eventName.value);
    23.                 EndAction();
    24.             }
    25.         }
    26.     }
    27. }
    28.  
    I hope this helped you. Let me know if you have any questions or clarifications.


    Indeed, there is an issue in NON icon mode and some nodes with no info.
    Please replace NodeBase.cs line 420 with:
    Code (csharp):
    1.  
    2. nodeRect = GUILayout.Window (ID, nodeRect, NodeWindowGUI, nodeName, "window", GUILayout.MinWidth(minSize.x), GUILayout.MinHeight(minSize.y));
    3.  
    Thanks.
     
  35. bkw

    bkw

    Joined:
    Sep 20, 2013
    Posts:
    49
    Thanks for the quick reply. Line 420 is an empty line. Perhaps there are changes in version 1.4.4 that I don't have? I tried replacing the line:
    Code (csharp):
    1. nodeRect = GUILayout.Window (ID, nodeRect, NodeWindowGUI, nodeName, "window");
    but that didn't seem to fix it. Good to know that it's just a non-icon mode problem though. I can at least switch to icon mode to select it.
    Is 1.4.4 with Unity now?
     
  36. bkw

    bkw

    Joined:
    Sep 20, 2013
    Posts:
    49
    Is the issue with "clicking through" the node inspector fixed in the upcoming update? That one gets in the way a bit.

    Is there a way to hide task from being used? I made a base action task class that has no meaningful functionality on its own and I'd like to prevent it from being used in the graph editor somehow.
     
  37. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Yeah, it might not be in line 420 due to changes I've made for the new version, but that is the correct line to replace. Weird that it doesn't fix the Remapper UI in Text mode. I'll PM you a temporary fix for it.
    1.4.4 is not yet approved no. I hope it soon will :)

    If a Task is abstract it won't show up for selection at all. Same goes for nodes, just in case you make your own.

    In the new version the 'click through' is fixed as well as the middle mouse button that was panning a node if on top of one instead of the whole canvas :)
    I didnt list those in the post before because I've resubmited afterwards.
     
    Last edited: May 23, 2014
  38. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    The new version is live on the Asset Store. The change log can always be found HERE or in the first post of this thread.
    Enjoy :)
     
  39. msl_manni

    msl_manni

    Joined:
    Jul 5, 2011
    Posts:
    272
    Only the modified SendEvent action is able to send events properly. I have renamed it to SendEventTo. Thanks.

    I have one more request - GetObjectsOfTag with a conditional check. GetObjectsOfTag which can have additional condition check, that would be added to the list on condition = true. This would make graph bit shorter and easy to maintain.
     
  40. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Hello,

    The old SendEvent did work, but was only able to send an event to it's own graph.
    If you wanted to GetObjectOfTag only if a condition is true, you can always use a Sequencer with a Condition first and the GetObjectOfTag second, thus it will only do so, if the first condition is true. :)
     
  41. msl_manni

    msl_manni

    Joined:
    Jul 5, 2011
    Posts:
    272
    Thats true. Had tough time with it. :rolleyes: Finally got it.

    I dont get it. :confused:

    Say a boolean -> canAttack is on Enemy BlackBoard. How can I read it in Manager BT?

    How do you read / write to any variable of Enemy from the variable List on Manager BT.
     
  42. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    A Sequencer executes it's children nodes in order from left to right. If a child node returns Failure then the Sequencer will not continue to the next child. Thus if you have a Condition on the left that returns Failure, then the Sequencer will return Failure as well thus will not execute the next children. That's how BTs work :)

    Right now, visually meaning through the editor, existing tasks can only read/write to the blackboard assigned to the graph they live in. So if 2 different graphs, have 2 different blackboards assigned you can't read/write from one graph to the other graph's blackboard. I am working on allowing this through the editor in a convenient way for possibly the next update.

    But, you can read/write to any blackboard you wish so from code by using:
    GetDataValue<T>(string name)
    SetDataValue(string name, object value)

    For example here is a simple action that sets any blackboard's boolean variable specified by it's name. The value to set it to can be though read from this task's graph's blackboard.

    Code (csharp):
    1.  
    2. using NodeCanvas;
    3. using NodeCanvas.Variables;
    4.  
    5. public class SetOtherBlackboardBool : ActionTask {
    6.  
    7.     [RequiredField]
    8.     public Blackboard targetBlackboard;
    9.     [RequiredField]
    10.     public string targetVariableName;
    11.     public BBBool setTo;
    12.  
    13.     protected override void OnExecute(){
    14.  
    15.         targetBlackboard.SetDataValue(targetVariableName, setTo.value);
    16.         EndAction();
    17.     }
    18. }
    19.  
    So you can use this to set a boolean variable from one BT to another.
    And here is a similar Condition task:

    Code (csharp):
    1.  
    2. using NodeCanvas;
    3. using NodeCanvas.Variables;
    4.  
    5. public class CheckOtherBlackboardBool : ConditionTask {
    6.  
    7.     [RequiredField]
    8.     public Blackboard targetBlackboard;
    9.     [RequiredField]
    10.     public string targetVariableName;
    11.     public BBBool checkValue;
    12.  
    13.     protected override bool OnCheck(){
    14.  
    15.         return targetBlackboard.GetDataValue<bool>(targetVariableName) == checkValue.value;
    16.     }
    17. }
    18.  
    You can use these until the feature is in place.
     
  43. msl_manni

    msl_manni

    Joined:
    Jul 5, 2011
    Posts:
    272
    Thanks very much for the code. I have changed it so that it can work on a variable type too.

    SetOtherBlackboardBool :
    Code (csharp):
    1.  
    2. using NodeCanvas;
    3. using NodeCanvas.Variables;
    4.  
    5. namespace NodeCanvas.Actions{
    6.    
    7.     [ScriptCategory("Interop")]
    8.     [AgentType(typeof(GraphOwner))]
    9.  
    10.     public class SetOtherBlackboardBool : ActionTask {
    11.  
    12.         [RequiredField]
    13.         public string targetVariableName;
    14.         public BBBool setTo;
    15.  
    16.         protected override void OnExecute(){
    17.  
    18.             (agent as GraphOwner).blackboard.SetDataValue(targetVariableName, setTo.value);
    19.             EndAction();
    20.         }
    21.     }
    22. }
    23.  
    CheckOtherBlackboardBool :
    Code (csharp):
    1.  
    2. using NodeCanvas;
    3. using NodeCanvas.Variables;
    4.  
    5. namespace NodeCanvas.Actions{
    6.    
    7.     [ScriptCategory("Interop")]
    8.     [AgentType(typeof(GraphOwner))]
    9.  
    10.     public class CheckOtherBlackboardBool : ConditionTask {
    11.  
    12.         [RequiredField]
    13.         public string targetVariableName;
    14.         public BBBool checkValue;
    15.  
    16.         protected override bool OnCheck(){
    17.             return  (agent as GraphOwner).blackboard.GetDataValue<bool>(targetVariableName) == checkValue.value;
    18.         }
    19.     }
    20. }
    21.  
     
  44. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    You are welcome :)
    Yes that can certainly also work and could be more flexible :)
    Thanks for sharing.
     
    Last edited: May 24, 2014
  45. msl_manni

    msl_manni

    Joined:
    Jul 5, 2011
    Posts:
    272
    DialogueDemo is not working in current update. Please check.
     
  46. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Indeed, my mistake. Please comment out line # 151 of NodeGraphContainer.cs. I will fix that.
    Thanks
     
  47. msl_manni

    msl_manni

    Joined:
    Jul 5, 2011
    Posts:
    272
    SetOtherBlackboardBool and CheckOtherBlackboardBool works between DialogueTree and BehaviourTree. But its by value only. I would need a Setter for DialogueTree to make it work with variable type too.

    I suppose I make myself clear here.
     
  48. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    Can you please explain more? I don't get what you are after :)
     
  49. msl_manni

    msl_manni

    Joined:
    Jul 5, 2011
    Posts:
    272
    Think of it as a DTShop, an automatic shop. The shop spits some dialogues and also gives some health/energy/object etc to the visitors.

    A BTManager is responsible for checking relation between the - Visitors and DTshop. It passes the Visitor as a variable to DTShop to act upon.

    Still dont know if you get it ..............................

    I tried to code something like following

    Code (csharp):
    1.  
    2. using NodeCanvas;
    3. using NodeCanvas.Variables;
    4.  
    5. namespace NodeCanvas.Actions{
    6.  
    7.     [ScriptCategory("Interop")]
    8.    
    9.     [AgentType(typeof(GraphOwner))]
    10.  
    11.     public class SetOtherBlackboardBool : ActionTask {
    12.  
    13.         [RequiredField]
    14.         public BBGameObject agentToSet= new BBGameObject();
    15.  
    16.         public string targetVariableName;
    17.        
    18.         public BBBool setTo;
    19.  
    20.        
    21.        
    22.         protected override void OnExecute(){
    23.  
    24.             if (agentToSet.value != null)   agent = agentToSet.value.transform;
    25.             (agent as GraphOwner).blackboard.SetDataValue(targetVariableName, setTo.value);
    26.            
    27.             EndAction();
    28.            
    29.         }
    30.        
    31.     }
    32.    
    33. }
    34.  
    I suppose you can find some solution.
     
  50. nuverian

    nuverian

    Joined:
    Oct 3, 2011
    Posts:
    2,087
    I think I get what you are after. So you are saving the visitor as a GameObject variable and pass it to the DTShop and you want from the DTShop to set a variable on the visitor at some point (?)
    Considering the blackboard is on the same game object as the visitor, then you would be best to use something like this:

    Code (csharp):
    1.  
    2. public class SetOtherBlackboardBool : ActionTask {
    3.  
    4.     [RequiredField]
    5.     public BBGameObject target;
    6.     [RequiredField]
    7.     public string targetVariableName;
    8.     public BBBool setTo;
    9.  
    10.     protected override void OnExecute(){
    11.  
    12.         target.value.GetComponent<Blackboard>().SetDataValue(targetVariableName, setTo.value);
    13.         EndAction();
    14.     }
    15. }
    16.  
    I've used a BBGameObject here because I presume you are saving visitor into a gameobject variable and thus you are able to select that visitor variable this way (or directly assign a gameobject)

    Is that what you want?