Skip to content

BT window shows all tasks as inactive when EditorApplication.isPaused #94

Closed
@JeremyVansnick

Description

@JeremyVansnick

When I pause the editor, the behavior tree shows all the nodes as inactive.
This is unpractical because we want to ideally be able to pause and see exactly what our AI is doing at that particular frame.
image

(I am using Unity 2022.3.22f1)
I am surprised this issue hasn't been observed before, since when I look at the code it seems quite logical that there would be a bug there. I don't think it's Unity version related.

The state of activation of visual tasks is set to false inside of the OnGUI() method.
This works fine so long as the game is running. But the moment, the game is paused, the OnGUI() method is still running, which means all nodes become inactive.

The solution is to update the state of nodes in a method that runs at the same rate as the Update() function, in this case the EditorApplication.onUpdate. We can't do it in OnGUI because OnGUI() runs many times per frame and is completely unrelated to when the EditorApplication.isPaused is set properly.

=> This snippet is to show the first thing I tried and it doesn't work.
It's because EditorApplication.isPaused is not set to true before OnGUI has had the time to run several times already, so the nodes are set to false.

        public void Print ()
        {
            _printer.Print(_taskActive);

            if (!EditorApplication.isPaused)
                 _taskActive = false;
            

            foreach (var child in _children) {
                child.Print();
            }
        }

Anyway... here's the proper approach:
We print things in OnGUI. But we update values in EditorApplication.onUpdate... And we don't update values when the game is paused.

In BehaviorTreeWindow.cs

        void OnEnable() {
            EditorApplication.update += OnEditorUpdate;
        }

        void OnDisable() {
            EditorApplication.update -= OnEditorUpdate;
        }

        private void OnEditorUpdate() {
            if (!EditorApplication.isPaused)
                _printer?.UpdateValues();
        }

In BehaviorTreePrinter.cs

        public void UpdateValues()
        {
            _root.UpdateValues();
        }

In VisualTask.cs

      public void Print ()
        {
            _printer.Print(_taskActive);

            // _taskActive = false; // <= comment this out

            foreach (var child in _children) {
                child.Print();
            }
        }

        public void UpdateValues()
        {
            _printer.UpdateValues(_taskActive);
            _taskActive = false;
        
            foreach (var child in _children) {
                child.UpdateValues();
            }
        }

In NodePrinterController.cs

      public void UpdateValues(bool _taskIsActive)
        {
            _faders.Update(_taskIsActive);
        }

Now our GUI logic is separated from our value updating logic, and the nodes are keeping their active state even when the game is paused!
image

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions