NodeCanvas Forums › General Discussion › Task Initialization
Hey! I have a questions regarding the Behavior Tree
Which method do i have to override in an ConditionTask or ActionTask to set it up in the moment the whole graph is loaded. I tried onInit, but this seems to be called when the node is used the first time and not when the graph is loaded
Hello!
An alternative to the OnInit, which is what I used for all my tasks, you can also use OnValidate, but this is called both in editor and runtime, when the graph is loaded (as well as when the task is created or duplicated). You can however of course, do a simple check for if (Application.isPlaying)
🙂
Please let me know if OnValidate works for you, or not.
Thanks!
Join us on Discord: https://discord.gg/97q2Rjh
I also tried that out before, but the function was not called correctly. I think i had problems with subtrees, but i can try it again
Hey! I played around with OnValidate. The problem that i have that the agent is always null. So its called for template and not for instance belonging to a prefab
Hello again,
This is exactly why OnInit exists 🙂 That is because the agent is only correctly set right before the OnInit call, since it may have been overridden in the task inspector to be using a Blackboard Variable (instead of just “Self”). As such, in case of using a blackboard variable for the “agent”, we need to fetch the variable’s value right before the task is executed.
So, it’s really either OnValidate for things that are “agent agnostic”, or OnInit, for things that require the agent to already have been set.
Could you please share what you want to do more specifically?
Thanks!
Join us on Discord: https://discord.gg/97q2Rjh
I need several things
1.) At editor time a want to validate if everything is setup correctly. This is only possible if you think of the behavior tree and the agents prefab as a union. This leads to the problem i descriobed above that i need a valid agent in OnValidate or some other method that i could override. Isn´t it possible to change the code, that a valid agent is passed into OnValidate in the case when i selected the Prefab with the BehaviorTreeOwneer and not the BehaviorTree asset in unity?
In OnCreate the agent is correctly set
2.) In the moment when the graph is loaded at runtime i need to setup some MonoBehaviors. Those are working like sensors communicating with the rest of the application and updating Blackboard viarables. Think about it like “PlayerIsInRangeSensor” which is a MonoBehavior and communicates with our Game, e.g. receiving events. It´s not enough to do that OnInit, because this is only called when the state is entered, which will never happen because, the sensor is not created and the blackboard is not updated
What i also don´t want to do is to add those sensors in the editor, because then you forget to add them or if you automatically add them you forget to delete them if not needed anymore.
3.) Im currently trying to figure out how the error output/console works. Sadly there is not documentation about it. What i want to have is: When OnValidate is called at editor time and detects an error, it should be displayed in the console of node canvas. Once the error is fixed it should dissapear from the console. While a node has an error it should be somehow visual highlighted, e.g. drawn with red tint or showing some error icon.
4.) I want to have a script that is executed from our build pipeline and checks all existing graphs (calls OnValidate). If one has an error it should return “Error” and the build fails
It´s no problem for me to make minor changes to your codebase, if you give me a hint where i have to look at
Thx for any help
Hello again and very sorry for the late reply!
Some of the things you want to achieve will require few or more changes. Some of them I am willing to do for the next version as I find interesting.
– OnValidate is called from various locations and could be called more than once in the same frame. OnValidate is basically called from within Graph.OnEnable as well as (in case of bound graphs), GraphOwner.OnValidate. A few changes that could be made to ensure the agent is set during those calls would be open up GraphOwner.cs and in it’s ‘Validate’, change the order of boundGraphInstance.UpdateReferencesFromOwner
to be, before the boundGraphInstance.Validate
call as such:
1 2 3 4 |
boundGraphInstance.UpdateReferencesFromOwner(this); boundGraphInstance.Validate(); |
Another change to complement this, would be to change the Graph.OnEnable to this:
1 2 3 4 5 6 7 |
protected void OnEnable(){ if (hasDeserialized){ Validate(); } } |
This will make sure to only call OnValidate after the graph has serialized, thus avoid an OnValidate call simply because a graph has just been instantiated (since OnEnable is called when a graph is instanted too).
As a result to the above changed, you will receive a OnValidate call with the agent set correctly (if any) in the editor, but you might get more that one OnValidate calls, thus you will have to check for null agent.
– To “post” a log in the NodeCanvas Console, you can do so by using the custom logger like this:
ParadoxNotion.Services.Logger.Log(string message, string tag, object contextObject)
. Thus from within a Task.OnValidate, the ‘contextObject’, would most probably be itself (this).
Any log logged with this custom logger, will be shown in the NodeCanvas Console and will be possible to click-to-select the relevant node.
With that said though, it is not dynamic like in what you want to achieve, meaning that it will not remove itself automatically if the error is fixed. For that, I will probably need to change the OnValidate, to return a string, similar to how the OnInit does, but this will require a lot of changes to post here.
Please let me know if the above were helpful, or what other code places you might want me to point to you at regarding the things you want to achieve.
Thank you.
Join us on Discord: https://discord.gg/97q2Rjh