From b4652da0a6c05e6585f5ce2990e928affcd55e6b Mon Sep 17 00:00:00 2001
From: Lucas Rafael <joaolucasrafael@gmail.com>
Date: Sat, 2 Dec 2023 13:15:19 +0000
Subject: [PATCH 1/3] Implement a customizable tick rate to improve perf
 (closes #255).

---
 addons/beehave/nodes/beehave_tree.gd | 29 +++++++++++++++++++++-------
 1 file changed, 22 insertions(+), 7 deletions(-)

diff --git a/addons/beehave/nodes/beehave_tree.gd b/addons/beehave/nodes/beehave_tree.gd
index abaaae90..9fd7ae0a 100644
--- a/addons/beehave/nodes/beehave_tree.gd
+++ b/addons/beehave/nodes/beehave_tree.gd
@@ -19,7 +19,7 @@ signal tree_enabled
 signal tree_disabled
 
 
-## Wether this behavior tree should be enabled or not.
+## Whether this behavior tree should be enabled or not.
 @export var enabled: bool = true:
 	set(value):
 		enabled = value
@@ -35,6 +35,11 @@ signal tree_disabled
 		return enabled
 
 
+## How often the tree should tick, in frames. The default value of 1 means 
+## tick() runs every frame.
+@export var tick_rate: int = 1
+
+
 ## An optional node path this behavior tree should apply to.
 @export_node_path var actor_node_path : NodePath:
 	set(anp):
@@ -90,6 +95,7 @@ signal tree_disabled
 
 var actor : Node
 var status : int = -1
+var last_tick : int = 0
 
 var _internal_blackboard: Blackboard
 var _process_time_metric_name : String
@@ -127,19 +133,28 @@ func _ready() -> void:
 		BeehaveGlobalDebugger.register_tree(self)
 		BeehaveDebuggerMessages.register_tree(_get_debugger_data(self))
 
+	# Randomize at what frames tick() will happen to avoid stutters
+	last_tick = randi_range(0, tick_rate - 1)
+
 
-func _physics_process(delta: float) -> void:
-	_process_internally(delta)
+func _physics_process(_delta: float) -> void:
+	_process_internally()
 	
 	
-func _process(delta: float) -> void:
-	_process_internally(delta)
+func _process(_delta: float) -> void:
+	_process_internally()
 
 
-func _process_internally(delta: float) -> void:
+func _process_internally() -> void:
 	if Engine.is_editor_hint():
 		return
 
+	if last_tick < tick_rate - 1:
+		last_tick += 1 
+		return
+	
+	last_tick = 0
+
 	# Start timing for metric
 	var start_time = Time.get_ticks_usec()
 
@@ -245,7 +260,7 @@ func _exit_tree() -> void:
 
 # Called by the engine to profile this tree
 func _get_process_time_metric_value() -> int:
-	return _process_time_metric_value
+	return int(_process_time_metric_value)
 
 
 func _get_debugger_data(node: Node) -> Dictionary:

From 3c27fbc85830f0e52414ee39ecce995fdd2f9e67 Mon Sep 17 00:00:00 2001
From: Lucas Rafael <joaolucasrafael@gmail.com>
Date: Sun, 3 Dec 2023 14:03:22 +0000
Subject: [PATCH 2/3] Add unit test.

---
 runtest.sh                |  0
 test/beehave_tree_test.gd | 20 ++++++++++++++++++++
 2 files changed, 20 insertions(+)
 mode change 100644 => 100755 runtest.sh

diff --git a/runtest.sh b/runtest.sh
old mode 100644
new mode 100755
diff --git a/test/beehave_tree_test.gd b/test/beehave_tree_test.gd
index 3e990175..96cff056 100644
--- a/test/beehave_tree_test.gd
+++ b/test/beehave_tree_test.gd
@@ -17,6 +17,26 @@ func test_normal_tick() -> void:
 	scene.beehave_tree._physics_process(1.0)
 	assert_that(scene.beehave_tree.status).is_equal(BeehaveNode.SUCCESS)
 
+func test_low_tick_rate() -> void:
+	var scene = create_scene()
+	scene_runner(scene)
+	scene.beehave_tree.tick_rate = 3
+	scene.beehave_tree._physics_process(1.0)
+	assert_that(scene.beehave_tree.status).is_equal(-1)
+	scene.beehave_tree._physics_process(1.0)
+	assert_that(scene.beehave_tree.status).is_equal(-1)
+	scene.beehave_tree._physics_process(1.0)
+	assert_that(scene.beehave_tree.status).is_equal(BeehaveNode.SUCCESS)
+
+func test_low_tick_rate_last_tick() -> void:
+	var scene = create_scene()
+	scene_runner(scene)
+	scene.beehave_tree.tick_rate = 3
+	scene.beehave_tree.last_tick = 1
+	scene.beehave_tree._physics_process(1.0)
+	assert_that(scene.beehave_tree.status).is_equal(-1)
+	scene.beehave_tree._physics_process(1.0)
+	assert_that(scene.beehave_tree.status).is_equal(BeehaveNode.SUCCESS)
 
 func test_nothing_running_before_first_tick() -> void:
 	var scene = create_scene()

From 530a2988078a9929067880f28b17a900a7e7396e Mon Sep 17 00:00:00 2001
From: Lucas Rafael <joaolucasrafael@gmail.com>
Date: Sun, 3 Dec 2023 14:06:17 +0000
Subject: [PATCH 3/3] Add test reports to gitignore.

---
 .gitignore | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.gitignore b/.gitignore
index 04fe9d0a..bab2f09f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,5 @@ export_presets.cfg
 .mono/
 data_*/
 .godot/
+
+reports/
