Yes, That would be better but I could not find a good place to insert the event registration, Thanks!
Hya Gavalakis, thanks for the quick response,
1. Great 🙂 Cant wait – another option would be to resize the group itself when the nodes are collapsed, as today it stays in the original size like so:
2. I was sure I tried that :O, but yes that does work! thanks
3. Yes, here is a small gif to show the issue:
Works great, thanks Gavalakis, any chance this comes bundled in the next version (I dont want to remember adding it everytime I upgrade)
BTW, I was able to make OnSceneGUI Work by adding these changes, dont know if this is the best way to do that with the graph structure, let me know if you think it’s fine and if you can add it
GraphOwner class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
protected void Start() { if ( firstActivation == FirstActivation.OnStart ) { if ( !isRunning && enableAction == EnableAction.EnableBehaviour ) { StartBehaviour(); } } InvokeStartEvent(); startCalled = true; // Not sure if this is the right place to do this, but it works for now #if UNITY_EDITOR SceneView.duringSceneGui += OnSceneGUISelected; #endif } protected void OnDestroy() { if ( ParadoxNotion.Services.Threader.applicationIsPlaying ) { StopBehaviour(); } foreach ( var instanceGraph in instances.Values ) { foreach ( var subGraph in instanceGraph.GetAllInstancedNestedGraphs() ) { Destroy(subGraph); } Destroy(instanceGraph); } #if UNITY_EDITOR SceneView.duringSceneGui -= OnSceneGUISelected; #endif } ///<summary>Forward Scene GUI callback</summary> void OnSceneGUISelected(SceneView view) { if ( Editor.GraphEditorUtility.activeElement != null ) { var rootElement = Editor.GraphEditorUtility.activeElement.graph.GetFlatMetaGraph().FindReferenceElement(Editor.GraphEditorUtility.activeElement); if ( rootElement != null ) { foreach ( var task in rootElement.GetAllChildrenReferencesOfType<Task>() ) { task.OnSceneGUISelected(); } } } } |
Task class
1 2 3 |
virtual public void OnSceneGUISelected() { } |
That is what I’ve been doing as a workaround (I’ve said that in a previous comment here)
Is that really a good way of implementing this? I’m worried about performance issues (from reading other posts here) and it seems that this would still be running extra checks on the main root node, considering this is going to be a large tree that I am going to run this on about 100~ agents I’m worried it will add up.
Yes, I would like some way to run code when the inspector values change (validate them)
This is odd as from my experience the native onValidate does trigger on editor value changes.
Actually a quick check in the unity docs verifies that https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnValidate.html
First line states it should fire when inspector values change.
I can only assume that the task inspector is somehow “disconnected” from the main graph
In my case I dont really need to entire graph to ever reset, which is way I set it to on first failure, my reset point is the switch node (represented by the dynamic node)
The idea here is to allow running additional events in the graph without interrupting the rest of the running graph, hence using the parallel, this is the only way I found of simulating events that don’t change the current state of the graph, if this is an anti pattern and there is a better way to run multiple branches at the same time in case of events let me know.
In this case I would want the parallel node to act like a game loop or an infinite while loop
Hya Gavalakis, thanks for the answer, The behavior you are describing is not what is documented in the docs
I also dont think it makes much sense, if the node policy is to only be finished on first failure than it should only finish on first failure, what you are describing is on first failure or success, which has its own policy, so this kinda makes both policies moot when “repeat” is selected.
Regardless, if you are not willing to fix, can you suggest a better way to achieve this?
For now I’ve added a “repeat forever” decorator over the sequencer which prevents the child from ever returning and thus prevents this, it feels like a workaround rather then an actual correct way.
I strongly urge you to rethink if this makes sense.
It seems to me like if the node says it will keep running until the first failure then it should do that.
Hya Glvalakis, thanks for the replay,
I tried calling validate where you suggested
1 2 3 4 |
protected void OnValidate() { Validate(); } |
And then I added a log to my action OnValidate method like so:
1 2 3 4 |
public override void OnValidate(ITaskSystem ownerSystem) { Debug.Log("log"); } |
This does not seem to work, did I misunderstood?
Gavalakis, I took me a few hours but I was able to create a minimal graph that does reproduce this issue using only native nodecanvas components,
here is a gif of the issue and an explanation on how to reproduce it.
So, this is a bit complicated and I did not dive into the graph code so I have no idea why this is happening but,
To reproduce this you need
1. A parallel root
2. A selector leading to a DYNAMIC conditional node that is set to return failure on first run, I’l call this condition A
3. A sequencer that leads from the parallel root and is waiting until a different condition, We will call this one condition B
To reproduce this, it is very important that the conditional node (A) will first return failure on the first time.
Then, switch it’s condition (A) so it returns true.
Now that the A node is engaged (In this case I just wait for ever) switch condition B to be true too.
This will cause a graph reset (only on the first time!)
Hya Gavalakis, glad to see you’re alive 😉
Sure, here is the code for the custom tasks:
isTalking just checks the current value on another class, I know I can do this via the checkBoolean task but for now I prefer doing it like so:
1 2 3 4 5 6 7 8 9 10 |
public class IsTalking : ConditionTask { [GetFromAgent] protected MBActor actor; protected override bool OnCheck() { return actor.IsTalking; } } |
SetMoving is also very simple:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class SetMoving : ActionTask { [GetFromAgent] private MBActorMovement actorMovement; public BBParameter<bool> value; protected override void OnExecute() { actorMovement.MovementEnabled = value.value; EndAction(); } } } |
FollowPath is a bit more complex and uses the A* package and generally it just sets the next point in a path for the npc to follow.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
public class FollowPath : ActionTask { [Location] public int LocationReference = -1; public Vector2[] Path; [GetFromAgent] private FollowerEntity followerEntity; private int currentIndex = 0; private Location location; protected override void OnUpdate() { if (followerEntity.reachedDestination) { currentIndex += 1; if (currentIndex >= Path.Length) { EndAction(); return; } followerEntity.destination = location.worldPosition + (Vector3)Path[currentIndex]; } } protected override void OnStop() { followerEntity.destination = followerEntity.transform.position; } protected override void OnExecute() { location = (Location)Vault.Get(LocationReference); followerEntity.updateRotation = false; followerEntity.destination = location.worldPosition + (Vector3)Path[0]; } } |
I am using the latest version (3.29), and it does look like this:
1 2 3 4 |
protected override void OnReset() { for ( var i = 0; i < finishedConnections.Length; i++ ) { finishedConnections<em class="d4pbbc-italic"></em> = false; } finishedConnectionsCount = 0; } |
I will try and replicate the issue again on a different tree.
@Gavalakis
I debugged the code of the parallel node, it seems that you are not clearing the finishedConnections variable which causes you to count the same connection twice on two different runs of OnExecute
As you can see in the attached image right after the loop that counts the finished connections you have 2 connections marked as finished, but when inspecting the outConnections you can clearly see that one of them is still with status=running
So, this node thinks both of it’s children are done (you can also see in the gif that that is not the case) and then calls
ResetRunning in the check for finishedConnectionsCount == outConnections.Count
For what ever reason, either the node starts off with one connection counted as finished, or there is another bug with clearing the the finished connections, in either case you can see the frustrating result in the gif above.
It has been a while so I dont have the “corrupted” json file anymore, if it happens again I’l make sure to do so and update here
Hya, yes it is in the project own assembly
Here is a video of me fixing the issue, as you can see the variable is just stuck, I need to “change” it back to its original type, and then rebind the variable..
It happened again but not just for a blackboard variable, this time it happened on a simple script recompile, something you do a hundred times a day.
It is getting increasingly frustrating having to rebind everything every few days.
As you can see from the image the variable for the animationController just stopped working, forgot what it is and its binding.