Demo: Add tutorial and improve UI

This commit is contained in:
Serhii Snitsaruk 2024-02-13 16:49:22 +01:00
parent 9eb7a9c346
commit 9443c50d94
32 changed files with 1294 additions and 26 deletions

View File

@ -31,10 +31,6 @@ texture = ExtResource("2_xd5s8")
[node name="HandR" parent="Root/Rig/Body" index="2"] [node name="HandR" parent="Root/Rig/Body" index="2"]
texture = ExtResource("2_xd5s8") texture = ExtResource("2_xd5s8")
[node name="WeaponNinjaStar" parent="Root" index="1"]
position = Vector2(-55, -76)
rotation = 0.0
[node name="Health" parent="." index="3"] [node name="Health" parent="." index="3"]
max_health = 4.0 max_health = 4.0

View File

@ -37,7 +37,7 @@ func _enter() -> void:
func _exit() -> void: func _exit() -> void:
hurtbox_collision.disabled = false hurtbox_collision.set_deferred(&"disabled", false)
func _update(p_delta: float) -> void: func _update(p_delta: float) -> void:

View File

@ -103,7 +103,7 @@ func play_summoning_effect() -> void:
summoning_effect.emitting = true summoning_effect.emitting = true
## Is specified position inside the arena (not inside obstacle)? ## Is specified position inside the arena (not inside an obstacle)?
func is_good_position(p_position: Vector2) -> bool: func is_good_position(p_position: Vector2) -> bool:
var space_state := get_world_2d().direct_space_state var space_state := get_world_2d().direct_space_state
var params := PhysicsPointQueryParameters2D.new() var params := PhysicsPointQueryParameters2D.new()

View File

@ -0,0 +1,36 @@
[gd_scene load_steps=5 format=3 uid="uid://dk67yawiu33jv"]
[ext_resource type="PackedScene" uid="uid://ooigbfhfy4wa" path="res://demo/agents/agent_base.tscn" id="1_2vrmp"]
[ext_resource type="Texture2D" uid="uid://b0oeqsc0xksto" path="res://demo/assets/agent_junior_pieces.png" id="2_3h4dj"]
[ext_resource type="BehaviorTree" uid="uid://b1mfh8yad7rmw" path="res://demo/ai/tutorial_trees/tutorial_01_welcome.tres" id="3_ilmgw"]
[sub_resource type="BlackboardPlan" id="BlackboardPlan_52mdk"]
var/speed/name = "speed"
var/speed/type = 3
var/speed/value = 400.0
var/speed/hint = 1
var/speed/hint_string = "10,1000,10"
[node name="TutorialWelcome" instance=ExtResource("1_2vrmp")]
[node name="LegL" parent="Root/Rig" index="1"]
texture = ExtResource("2_3h4dj")
[node name="LegR" parent="Root/Rig" index="2"]
texture = ExtResource("2_3h4dj")
[node name="Body" parent="Root/Rig" index="3"]
texture = ExtResource("2_3h4dj")
[node name="Hat" parent="Root/Rig/Body" index="0"]
texture = ExtResource("2_3h4dj")
[node name="HandL" parent="Root/Rig/Body" index="1"]
texture = ExtResource("2_3h4dj")
[node name="HandR" parent="Root/Rig/Body" index="2"]
texture = ExtResource("2_3h4dj")
[node name="BTPlayer" type="BTPlayer" parent="." index="5"]
behavior_tree = ExtResource("3_ilmgw")
blackboard_plan = SubResource("BlackboardPlan_52mdk")

View File

@ -0,0 +1,41 @@
[gd_scene load_steps=5 format=3 uid="uid://cw3yth564nhrw"]
[ext_resource type="PackedScene" uid="uid://ooigbfhfy4wa" path="res://demo/agents/agent_base.tscn" id="1_lia2k"]
[ext_resource type="Texture2D" uid="uid://b0oeqsc0xksto" path="res://demo/assets/agent_junior_pieces.png" id="2_4x2l4"]
[ext_resource type="BehaviorTree" uid="uid://b1i0xo0o676va" path="res://demo/ai/tutorial_trees/tutorial_02_introduction.tres" id="3_3esuy"]
[sub_resource type="BlackboardPlan" id="BlackboardPlan_52mdk"]
var/speed/name = "speed"
var/speed/type = 3
var/speed/value = 400.0
var/speed/hint = 1
var/speed/hint_string = "10,1000,10"
var/flank_speed/name = "flank_speed"
var/flank_speed/type = 3
var/flank_speed/value = 600.0
var/flank_speed/hint = 1
var/flank_speed/hint_string = "10,1000,10"
[node name="TutorialIntro" instance=ExtResource("1_lia2k")]
[node name="LegL" parent="Root/Rig" index="1"]
texture = ExtResource("2_4x2l4")
[node name="LegR" parent="Root/Rig" index="2"]
texture = ExtResource("2_4x2l4")
[node name="Body" parent="Root/Rig" index="3"]
texture = ExtResource("2_4x2l4")
[node name="Hat" parent="Root/Rig/Body" index="0"]
texture = ExtResource("2_4x2l4")
[node name="HandL" parent="Root/Rig/Body" index="1"]
texture = ExtResource("2_4x2l4")
[node name="HandR" parent="Root/Rig/Body" index="2"]
texture = ExtResource("2_4x2l4")
[node name="BTPlayer" type="BTPlayer" parent="." index="5"]
behavior_tree = ExtResource("3_3esuy")
blackboard_plan = SubResource("BlackboardPlan_52mdk")

View File

@ -0,0 +1,36 @@
[gd_scene load_steps=5 format=3 uid="uid://bx4iabilsv3rs"]
[ext_resource type="PackedScene" uid="uid://ooigbfhfy4wa" path="res://demo/agents/agent_base.tscn" id="1_p8nwq"]
[ext_resource type="Texture2D" uid="uid://b0oeqsc0xksto" path="res://demo/assets/agent_junior_pieces.png" id="2_hnwhw"]
[ext_resource type="BehaviorTree" uid="uid://cb0ybf24ahnc3" path="res://demo/ai/tutorial_trees/tutorial_03_types.tres" id="3_a31ka"]
[sub_resource type="BlackboardPlan" id="BlackboardPlan_52mdk"]
var/speed/name = "speed"
var/speed/type = 3
var/speed/value = 400.0
var/speed/hint = 1
var/speed/hint_string = "10,1000,10"
[node name="TutorialTypes" instance=ExtResource("1_p8nwq")]
[node name="LegL" parent="Root/Rig" index="1"]
texture = ExtResource("2_hnwhw")
[node name="LegR" parent="Root/Rig" index="2"]
texture = ExtResource("2_hnwhw")
[node name="Body" parent="Root/Rig" index="3"]
texture = ExtResource("2_hnwhw")
[node name="Hat" parent="Root/Rig/Body" index="0"]
texture = ExtResource("2_hnwhw")
[node name="HandL" parent="Root/Rig/Body" index="1"]
texture = ExtResource("2_hnwhw")
[node name="HandR" parent="Root/Rig/Body" index="2"]
texture = ExtResource("2_hnwhw")
[node name="BTPlayer" type="BTPlayer" parent="." index="5"]
behavior_tree = ExtResource("3_a31ka")
blackboard_plan = SubResource("BlackboardPlan_52mdk")

View File

@ -0,0 +1,36 @@
[gd_scene load_steps=5 format=3 uid="uid://bhtm8gnk5hsus"]
[ext_resource type="PackedScene" uid="uid://ooigbfhfy4wa" path="res://demo/agents/agent_base.tscn" id="1_oibr1"]
[ext_resource type="Texture2D" uid="uid://b0oeqsc0xksto" path="res://demo/assets/agent_junior_pieces.png" id="2_j52yc"]
[ext_resource type="BehaviorTree" uid="uid://dln8ywvtqedt7" path="res://demo/ai/tutorial_trees/tutorial_04_sequence.tres" id="3_feewj"]
[sub_resource type="BlackboardPlan" id="BlackboardPlan_52mdk"]
var/speed/name = "speed"
var/speed/type = 3
var/speed/value = 400.0
var/speed/hint = 1
var/speed/hint_string = "10,1000,10"
[node name="TutorialSequence" instance=ExtResource("1_oibr1")]
[node name="LegL" parent="Root/Rig" index="1"]
texture = ExtResource("2_j52yc")
[node name="LegR" parent="Root/Rig" index="2"]
texture = ExtResource("2_j52yc")
[node name="Body" parent="Root/Rig" index="3"]
texture = ExtResource("2_j52yc")
[node name="Hat" parent="Root/Rig/Body" index="0"]
texture = ExtResource("2_j52yc")
[node name="HandL" parent="Root/Rig/Body" index="1"]
texture = ExtResource("2_j52yc")
[node name="HandR" parent="Root/Rig/Body" index="2"]
texture = ExtResource("2_j52yc")
[node name="BTPlayer" type="BTPlayer" parent="." index="5"]
behavior_tree = ExtResource("3_feewj")
blackboard_plan = SubResource("BlackboardPlan_52mdk")

View File

@ -0,0 +1,36 @@
[gd_scene load_steps=5 format=3 uid="uid://5nqbasyipupf"]
[ext_resource type="PackedScene" uid="uid://ooigbfhfy4wa" path="res://demo/agents/agent_base.tscn" id="1_62fs7"]
[ext_resource type="Texture2D" uid="uid://b0oeqsc0xksto" path="res://demo/assets/agent_junior_pieces.png" id="2_gdg2c"]
[ext_resource type="BehaviorTree" uid="uid://bf4r652fv5kwi" path="res://demo/ai/tutorial_trees/tutorial_05_selector.tres" id="3_pm5ep"]
[sub_resource type="BlackboardPlan" id="BlackboardPlan_52mdk"]
var/speed/name = "speed"
var/speed/type = 3
var/speed/value = 400.0
var/speed/hint = 1
var/speed/hint_string = "10,1000,10"
[node name="TutorialSelector" instance=ExtResource("1_62fs7")]
[node name="LegL" parent="Root/Rig" index="1"]
texture = ExtResource("2_gdg2c")
[node name="LegR" parent="Root/Rig" index="2"]
texture = ExtResource("2_gdg2c")
[node name="Body" parent="Root/Rig" index="3"]
texture = ExtResource("2_gdg2c")
[node name="Hat" parent="Root/Rig/Body" index="0"]
texture = ExtResource("2_gdg2c")
[node name="HandL" parent="Root/Rig/Body" index="1"]
texture = ExtResource("2_gdg2c")
[node name="HandR" parent="Root/Rig/Body" index="2"]
texture = ExtResource("2_gdg2c")
[node name="BTPlayer" type="BTPlayer" parent="." index="5"]
behavior_tree = ExtResource("3_pm5ep")
blackboard_plan = SubResource("BlackboardPlan_52mdk")

View File

@ -0,0 +1,36 @@
[gd_scene load_steps=5 format=3 uid="uid://ehc00upu3co"]
[ext_resource type="PackedScene" uid="uid://ooigbfhfy4wa" path="res://demo/agents/agent_base.tscn" id="1_mbrnd"]
[ext_resource type="Texture2D" uid="uid://b0oeqsc0xksto" path="res://demo/assets/agent_junior_pieces.png" id="2_ttkri"]
[ext_resource type="BehaviorTree" uid="uid://beiki511huxb8" path="res://demo/ai/tutorial_trees/tutorial_06_decorators.tres" id="3_tpgll"]
[sub_resource type="BlackboardPlan" id="BlackboardPlan_52mdk"]
var/speed/name = "speed"
var/speed/type = 3
var/speed/value = 400.0
var/speed/hint = 1
var/speed/hint_string = "10,1000,10"
[node name="TutorialDecorators" instance=ExtResource("1_mbrnd")]
[node name="LegL" parent="Root/Rig" index="1"]
texture = ExtResource("2_ttkri")
[node name="LegR" parent="Root/Rig" index="2"]
texture = ExtResource("2_ttkri")
[node name="Body" parent="Root/Rig" index="3"]
texture = ExtResource("2_ttkri")
[node name="Hat" parent="Root/Rig/Body" index="0"]
texture = ExtResource("2_ttkri")
[node name="HandL" parent="Root/Rig/Body" index="1"]
texture = ExtResource("2_ttkri")
[node name="HandR" parent="Root/Rig/Body" index="2"]
texture = ExtResource("2_ttkri")
[node name="BTPlayer" type="BTPlayer" parent="." index="5"]
behavior_tree = ExtResource("3_tpgll")
blackboard_plan = SubResource("BlackboardPlan_52mdk")

View File

@ -0,0 +1,36 @@
[gd_scene load_steps=5 format=3 uid="uid://brq6c843j1eeo"]
[ext_resource type="PackedScene" uid="uid://ooigbfhfy4wa" path="res://demo/agents/agent_base.tscn" id="1_k4qfc"]
[ext_resource type="Texture2D" uid="uid://b0oeqsc0xksto" path="res://demo/assets/agent_junior_pieces.png" id="2_q4r1n"]
[ext_resource type="BehaviorTree" uid="uid://tep50j4d6kgp" path="res://demo/ai/tutorial_trees/tutorial_07_more_decorators.tres" id="3_ta3g6"]
[sub_resource type="BlackboardPlan" id="BlackboardPlan_52mdk"]
var/speed/name = "speed"
var/speed/type = 3
var/speed/value = 400.0
var/speed/hint = 1
var/speed/hint_string = "10,1000,10"
[node name="TutorialMoreDecorators" instance=ExtResource("1_k4qfc")]
[node name="LegL" parent="Root/Rig" index="1"]
texture = ExtResource("2_q4r1n")
[node name="LegR" parent="Root/Rig" index="2"]
texture = ExtResource("2_q4r1n")
[node name="Body" parent="Root/Rig" index="3"]
texture = ExtResource("2_q4r1n")
[node name="Hat" parent="Root/Rig/Body" index="0"]
texture = ExtResource("2_q4r1n")
[node name="HandL" parent="Root/Rig/Body" index="1"]
texture = ExtResource("2_q4r1n")
[node name="HandR" parent="Root/Rig/Body" index="2"]
texture = ExtResource("2_q4r1n")
[node name="BTPlayer" type="BTPlayer" parent="." index="5"]
behavior_tree = ExtResource("3_ta3g6")
blackboard_plan = SubResource("BlackboardPlan_52mdk")

View File

@ -0,0 +1,36 @@
[gd_scene load_steps=5 format=3 uid="uid://b8yj40s43bw8h"]
[ext_resource type="PackedScene" uid="uid://ooigbfhfy4wa" path="res://demo/agents/agent_base.tscn" id="1_bjdsc"]
[ext_resource type="Texture2D" uid="uid://b0oeqsc0xksto" path="res://demo/assets/agent_junior_pieces.png" id="2_onjfd"]
[ext_resource type="BehaviorTree" uid="uid://dp0cglcytwcj5" path="res://demo/ai/tutorial_trees/tutorial_08_final_touch.tres" id="3_c5qx4"]
[sub_resource type="BlackboardPlan" id="BlackboardPlan_52mdk"]
var/speed/name = "speed"
var/speed/type = 3
var/speed/value = 400.0
var/speed/hint = 1
var/speed/hint_string = "10,1000,10"
[node name="TutorialFinalTouch" instance=ExtResource("1_bjdsc")]
[node name="LegL" parent="Root/Rig" index="1"]
texture = ExtResource("2_onjfd")
[node name="LegR" parent="Root/Rig" index="2"]
texture = ExtResource("2_onjfd")
[node name="Body" parent="Root/Rig" index="3"]
texture = ExtResource("2_onjfd")
[node name="Hat" parent="Root/Rig/Body" index="0"]
texture = ExtResource("2_onjfd")
[node name="HandL" parent="Root/Rig/Body" index="1"]
texture = ExtResource("2_onjfd")
[node name="HandR" parent="Root/Rig/Body" index="2"]
texture = ExtResource("2_onjfd")
[node name="BTPlayer" type="BTPlayer" parent="." index="5"]
behavior_tree = ExtResource("3_c5qx4")
blackboard_plan = SubResource("BlackboardPlan_52mdk")

View File

@ -67,7 +67,7 @@ func _tick(_delta: float) -> Status:
var offset := Vector2(dir * randf_range(range_min, range_max), 0.0) var offset := Vector2(dir * randf_range(range_min, range_max), 0.0)
flank_pos = target.global_position + offset flank_pos = target.global_position + offset
if not agent.is_good_position(flank_pos): if not agent.is_good_position(flank_pos):
# Choose the opposite side if preferred is not good (i.e., inside a collision shape). # Choose the opposite side if the preferred side is not good (i.e., inside a collision shape).
flank_pos = target.global_position - offset flank_pos = target.global_position - offset
blackboard.set_var(position_var, flank_pos) blackboard.set_var(position_var, flank_pos)
return SUCCESS return SUCCESS

View File

@ -80,5 +80,9 @@ children = [SubResource("BTAction_kidxn"), SubResource("BTWait_tadkc"), SubResou
children = [SubResource("BTSequence_yhjh1"), SubResource("BTSequence_1xfnq"), SubResource("BTSequence_ww5v2")] children = [SubResource("BTSequence_yhjh1"), SubResource("BTSequence_1xfnq"), SubResource("BTSequence_ww5v2")]
[resource] [resource]
description = "Welcome to the [b]LimboAI[/b] demo project! This demo project consists of three parts:
- If you're new to behavior trees, you can access the [b]Tutorial[/b] by clicking the \"Begin Tutorial\" button on the toolbar.
- To experience the demo game, just click the \"Switch to Game\" button.
- On this screen, you can inspect the AI behavior tree in action for each agent in the game."
blackboard_plan = SubResource("BlackboardPlan_46tbn") blackboard_plan = SubResource("BlackboardPlan_46tbn")
root_task = SubResource("BTSequence_pxl2k") root_task = SubResource("BTSequence_pxl2k")

View File

@ -115,5 +115,6 @@ custom_name = "Charge Attack"
children = [SubResource("BTSequence_l3v31"), SubResource("BTSequence_p6pgg"), SubResource("BTSequence_mde2g"), SubResource("BTSequence_8lur1")] children = [SubResource("BTSequence_l3v31"), SubResource("BTSequence_p6pgg"), SubResource("BTSequence_mde2g"), SubResource("BTSequence_8lur1")]
[resource] [resource]
description = "A [dec]Decorator[/dec] is a type of task that typically has only one child. Decorators are commonly used to alter the behavior or status of their child task. In this behavior tree, the [dec]TimeLimit[/dec] decorator sets a maximum time for the [act]Arrive[/act] action to complete its work. If the child task exceeds this time limit without finishing, it will be aborted, and the TimeLimit decorator will return [FAILURE]."
blackboard_plan = SubResource("BlackboardPlan_qd806") blackboard_plan = SubResource("BlackboardPlan_qd806")
root_task = SubResource("BTSequence_pjuov") root_task = SubResource("BTSequence_pjuov")

View File

@ -115,5 +115,6 @@ children = [SubResource("BTSequence_n5ltc"), SubResource("BTSequence_1xfnq"), Su
children = [SubResource("BTProbability_ifsry"), SubResource("BTSequence_pxl2k")] children = [SubResource("BTProbability_ifsry"), SubResource("BTSequence_pxl2k")]
[resource] [resource]
description = "Here, the [dec]Probability[/dec] decorator allows the execution of its branch in 50% of cases. This introduces a slight variation to the behavior each time the [comp]Chaotic walk[/comp] sequence is considered by the [comp]Selector[/comp]. This sequence can be selected several times in a row as long as the Probability decorator permits it. The [comp]Engage player[/comp] sequence is only executed if Probability returns [FAILURE]."
blackboard_plan = SubResource("BlackboardPlan_46tbn") blackboard_plan = SubResource("BlackboardPlan_46tbn")
root_task = SubResource("BTSelector_y3llm") root_task = SubResource("BTSelector_y3llm")

View File

@ -182,5 +182,9 @@ children = [SubResource("BTPlayAnimation_olf37"), SubResource("BTAction_ulbrf"),
children = [SubResource("BTRunLimit_tq3e1"), SubResource("BTCooldown_ksvfy"), SubResource("BTSequence_y12eg"), SubResource("BTSequence_rgwic")] children = [SubResource("BTRunLimit_tq3e1"), SubResource("BTCooldown_ksvfy"), SubResource("BTSequence_y12eg"), SubResource("BTSequence_rgwic")]
[resource] [resource]
description = "Like actions, conditions do not contain child tasks within them. Instead, they evaluate specific criteria and return either a [SUCCESS] or [FAILURE] based on the agent's or environment's state (for example, \"IsLowOnHealth\", \"IsTargetInSight\"). Conditions are commonly employed alongside sequences to interrupt their execution if a particular requirement is not met.
In our example, if the target is not within the specified range, the [con]InRange[/con] condition will return [FAILURE], causing the [comp]sequence[/comp] to be aborted.
"
blackboard_plan = SubResource("BlackboardPlan_46tbn") blackboard_plan = SubResource("BlackboardPlan_46tbn")
root_task = SubResource("BTSelector_2jnau") root_task = SubResource("BTSelector_2jnau")

View File

@ -175,5 +175,8 @@ custom_name = "Main"
children = [SubResource("BTSequence_yhjh1"), SubResource("BTSelector_1rrya")] children = [SubResource("BTSequence_yhjh1"), SubResource("BTSelector_1rrya")]
[resource] [resource]
description = "Here, the [dec]Probability[/dec] decorator permits the execution of its branch in 30% of cases. This introduces a slight variation to the behavior each time the \"Change flank\" sequence is considered by the [comp]Selector[/comp].
The [dec]Repeat[/dec] decorator is handy for doing something multiple times within a behavior tree. In our example, it's used to make the [comp]Throw ninja star[/comp] sequence perform three times in a row."
blackboard_plan = SubResource("BlackboardPlan_46tbn") blackboard_plan = SubResource("BlackboardPlan_46tbn")
root_task = SubResource("BTSequence_pxl2k") root_task = SubResource("BTSequence_pxl2k")

View File

@ -158,5 +158,6 @@ children = [SubResource("BTAction_kidxn"), SubResource("BTPlayAnimation_usdja"),
children = [SubResource("BTSequence_yhjh1"), SubResource("BTSequence_1xfnq"), SubResource("BTSequence_ww5v2")] children = [SubResource("BTSequence_yhjh1"), SubResource("BTSequence_1xfnq"), SubResource("BTSequence_ww5v2")]
[resource] [resource]
description = "In some scenarios, you might need to execute multiple tasks at the same time until specific conditions are fulfilled. To achieve this, the [comp]Parallel[/comp] composite is an invaluable tool. This composite task allows its children to be executed simultaneously during each tick until a specified number of successes or failures is reached. In this example, it will execute both the [act]PlayAnimation[/act] and [act]MoveForward[/act] actions each tick until both actions have finished with a [SUCCESS] status."
blackboard_plan = SubResource("BlackboardPlan_46tbn") blackboard_plan = SubResource("BlackboardPlan_46tbn")
root_task = SubResource("BTSequence_pxl2k") root_task = SubResource("BTSequence_pxl2k")

View File

@ -213,5 +213,7 @@ custom_name = "Main"
children = [SubResource("BTSequence_yhjh1"), SubResource("BTProbabilitySelector_rjsiq")] children = [SubResource("BTSequence_yhjh1"), SubResource("BTProbabilitySelector_rjsiq")]
[resource] [resource]
description = "[comp]ProbabilitySelector[/comp] chooses a child task to execute based on attached probabilities. Probability distribution is calculated based on weights assigned to each child task.
"
blackboard_plan = SubResource("BlackboardPlan_46tbn") blackboard_plan = SubResource("BlackboardPlan_46tbn")
root_task = SubResource("BTSequence_pxl2k") root_task = SubResource("BTSequence_pxl2k")

View File

@ -195,5 +195,6 @@ children = [SubResource("BTComment_mqte5"), SubResource("BTPlayAnimation_vjtpq")
children = [SubResource("BTCooldown_oms7a"), SubResource("BTSequence_eikr4"), SubResource("BTSequence_wh4dl"), SubResource("BTSequence_djtph")] children = [SubResource("BTCooldown_oms7a"), SubResource("BTSequence_eikr4"), SubResource("BTSequence_wh4dl"), SubResource("BTSequence_djtph")]
[resource] [resource]
description = "Here, we use the [con]InRange[/con] condition task together with [comp]Sequence[/comp] and [comp]Selector[/comp] to create a reactive behavior for this agent. When the player comes close, this agent will attempt to hit them with a melee attack and move away afterward for a better ranged position."
blackboard_plan = SubResource("BlackboardPlan_8ay3j") blackboard_plan = SubResource("BlackboardPlan_8ay3j")
root_task = SubResource("BTSelector_feba6") root_task = SubResource("BTSelector_feba6")

View File

@ -149,5 +149,7 @@ children = [SubResource("BTAction_33wje"), SubResource("BTPlayAnimation_qbxm8"),
children = [SubResource("BTRunLimit_x2jr4"), SubResource("BTSequence_2n742"), SubResource("BTSequence_dss4d")] children = [SubResource("BTRunLimit_x2jr4"), SubResource("BTSequence_2n742"), SubResource("BTSequence_dss4d")]
[resource] [resource]
description = "[con]CheckAgentProperty[/con] examines the agents property value and compares it to a given value or a blackboard variable. In this example, it checks if the [color=cyan]summon_count[/color] property is less than 6.
You can also check or share a [dec]Cooldown[/dec] in different parts of the behavior tree if you provide a blackboard variable for the [dec]Cooldown[/dec] decorator to use. [con]CheckVar[/con] is responsible here for examining the cooldown variable named \"summon_cooldown\"."
blackboard_plan = SubResource("BlackboardPlan_58oq1") blackboard_plan = SubResource("BlackboardPlan_58oq1")
root_task = SubResource("BTSelector_gp6q5") root_task = SubResource("BTSelector_gp6q5")

View File

@ -0,0 +1,29 @@
[gd_resource type="BehaviorTree" load_steps=5 format=3 uid="uid://b1mfh8yad7rmw"]
[sub_resource type="BlackboardPlan" id="BlackboardPlan_ewfwq"]
var/speed/name = "speed"
var/speed/type = 3
var/speed/value = 400.0
var/speed/hint = 1
var/speed/hint_string = "10,1000,10"
[sub_resource type="BBNode" id="BBNode_fq0jf"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_rsejo"]
animation_player = SubResource("BBNode_fq0jf")
animation_name = &"idle"
[sub_resource type="BTSequence" id="BTSequence_4bq32"]
children = [SubResource("BTPlayAnimation_rsejo")]
[resource]
description = "Welcome to the [b]LimboAI Tutorial[/b]!
Here, you'll learn how to use behavior trees to craft AI for your games. We'll start with the basics and gradually move to more advanced topics. Strap in for a quick and engaging introduction to behavior trees.
Press ➡ button in the top-right corner to proceed.
Press ⬅ button any time you want to go back to a previous chapter."
blackboard_plan = SubResource("BlackboardPlan_ewfwq")
root_task = SubResource("BTSequence_4bq32")

View File

@ -0,0 +1,45 @@
[gd_resource type="BehaviorTree" load_steps=9 format=3 uid="uid://b1i0xo0o676va"]
[sub_resource type="BlackboardPlan" id="BlackboardPlan_ewfwq"]
var/speed/name = "speed"
var/speed/type = 3
var/speed/value = 400.0
var/speed/hint = 1
var/speed/hint_string = "10,1000,10"
var/flank_speed/name = "flank_speed"
var/flank_speed/type = 3
var/flank_speed/value = 600.0
var/flank_speed/hint = 1
var/flank_speed/hint_string = "10,1000,10"
[sub_resource type="BBNode" id="BBNode_wu06u"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_dubaq"]
animation_player = SubResource("BBNode_wu06u")
animation_name = &"idle"
[sub_resource type="BTWait" id="BTWait_meli1"]
duration = 5.0
[sub_resource type="BBNode" id="BBNode_mgehh"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_0fqno"]
animation_player = SubResource("BBNode_mgehh")
animation_name = &"dance"
[sub_resource type="BTWait" id="BTWait_m3h4o"]
duration = 5.0
[sub_resource type="BTSequence" id="BTSequence_rbfdh"]
children = [SubResource("BTPlayAnimation_dubaq"), SubResource("BTWait_meli1"), SubResource("BTPlayAnimation_0fqno"), SubResource("BTWait_m3h4o")]
[resource]
description = "Behavior trees are designed to simplify the creation of responsive and modular behaviors for games. They consist of tasks that represent specific actions or decision-making rules. Tasks can be broadly categorized into two groups: control tasks and leaf tasks. [b]Control tasks[/b] dictate the execution flow within the tree, while [b]leaf tasks[/b] represent specific actions to perform (such as moving or attacking) or conditions that need to be checked. Typically, it's the leaf tasks that perform the actual work in behavior trees.
A behavior tree is usually processed each frame (physics frame by default). It is traversed from top to bottom, with the control tasks determining the control flow. Each task has a [color=cyan]_tick[/color] method, which performs the task's work and returns a status indicating its progress: [SUCCESS], [FAILURE], or [RUNNING]. [SUCCESS] and [FAILURE] indicate the outcome of finished work, while [RUNNING] status is returned when a task requires more than one tick to complete its job. These statuses determine how the tree progresses, with the [RUNNING] status usually meaning that the tree will continue execution during the next frame."
blackboard_plan = SubResource("BlackboardPlan_ewfwq")
root_task = SubResource("BTSequence_rbfdh")

View File

@ -0,0 +1,97 @@
[gd_resource type="BehaviorTree" load_steps=24 format=3 uid="uid://cb0ybf24ahnc3"]
[ext_resource type="Script" path="res://demo/ai/tasks/select_random_nearby_pos.gd" id="1_as4cg"]
[ext_resource type="Script" path="res://demo/ai/tasks/arrive_pos.gd" id="2_dlpnp"]
[ext_resource type="Script" path="res://demo/ai/tasks/get_first_in_group.gd" id="3_uv18s"]
[ext_resource type="Script" path="res://demo/ai/tasks/in_range.gd" id="4_k3g8t"]
[ext_resource type="Script" path="res://demo/ai/tasks/face_target.gd" id="5_thvy5"]
[sub_resource type="BlackboardPlan" id="BlackboardPlan_ewfwq"]
var/speed/name = "speed"
var/speed/type = 3
var/speed/value = 400.0
var/speed/hint = 1
var/speed/hint_string = "10,1000,10"
[sub_resource type="BBNode" id="BBNode_20ku0"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_57u80"]
animation_player = SubResource("BBNode_20ku0")
animation_name = &"walk"
[sub_resource type="BTAction" id="BTAction_11xvc"]
script = ExtResource("1_as4cg")
range_min = 300.0
range_max = 500.0
position_var = "pos"
[sub_resource type="BTAction" id="BTAction_tdkpj"]
script = ExtResource("2_dlpnp")
target_position_var = "pos"
speed_var = "speed"
tolerance = 50.0
avoid_var = ""
[sub_resource type="BTSequence" id="BTSequence_echit"]
children = [SubResource("BTPlayAnimation_57u80"), SubResource("BTAction_11xvc"), SubResource("BTAction_tdkpj")]
[sub_resource type="BTProbability" id="BTProbability_g0ol3"]
children = [SubResource("BTSequence_echit")]
[sub_resource type="BTAction" id="BTAction_124bm"]
script = ExtResource("3_uv18s")
group = &"player"
output_var = "target"
[sub_resource type="BTCondition" id="BTCondition_n25o8"]
script = ExtResource("4_k3g8t")
distance_min = 0.0
distance_max = 200.0
target_var = "target"
[sub_resource type="BTAction" id="BTAction_1hfgr"]
script = ExtResource("5_thvy5")
target_var = "target"
[sub_resource type="BBNode" id="BBNode_ilr2h"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_mrsu3"]
animation_player = SubResource("BBNode_ilr2h")
animation_name = &"attack_1"
[sub_resource type="BTSequence" id="BTSequence_5vug3"]
children = [SubResource("BTAction_124bm"), SubResource("BTCondition_n25o8"), SubResource("BTAction_1hfgr"), SubResource("BTPlayAnimation_mrsu3")]
[sub_resource type="BBNode" id="BBNode_fq0jf"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_rsejo"]
animation_player = SubResource("BBNode_fq0jf")
animation_name = &"idle"
[sub_resource type="BTWait" id="BTWait_dl31p"]
duration = 2.0
[sub_resource type="BTSequence" id="BTSequence_vx4uy"]
children = [SubResource("BTPlayAnimation_rsejo"), SubResource("BTWait_dl31p")]
[sub_resource type="BTSelector" id="BTSelector_tdpek"]
children = [SubResource("BTProbability_g0ol3"), SubResource("BTSequence_5vug3"), SubResource("BTSequence_vx4uy")]
[resource]
description = "There are four types of tasks:
[ul][act]Actions[/act] are leaf tasks that perform the actual work.[/ul]
[ul][con]Conditions[/con] are leaf tasks that conduct various checks.[/ul]
[ul][comp]Composites[/comp] can have one or more child tasks, and dictate the execution flow of their children.[/ul]
[ul][dec]Decorators[/dec] can only have a single child and they change how their child task operates.[/ul]
Let's take a look into actions first. [act]Actions[/act] are responsible for most of the work and often change the game state in a significant manner. For instance, [act]PlayAnimation[/act] instructs the AnimationPlayer to start a specified animation, with the option to wait for its completion. On the other hand, the [act]Wait[/act] task simply pauses for a set duration before returning [SUCCESS].
Next, we'll explore the core composite tasks, such as [comp]Sequence[/comp] and [comp]Selector[/comp]. These are among the most crucial composites that you should know about."
blackboard_plan = SubResource("BlackboardPlan_ewfwq")
root_task = SubResource("BTSelector_tdpek")

View File

@ -0,0 +1,62 @@
[gd_resource type="BehaviorTree" load_steps=15 format=3 uid="uid://dln8ywvtqedt7"]
[ext_resource type="Script" path="res://demo/ai/tasks/select_random_nearby_pos.gd" id="1_gk66j"]
[ext_resource type="Script" path="res://demo/ai/tasks/arrive_pos.gd" id="2_v5eou"]
[sub_resource type="BlackboardPlan" id="BlackboardPlan_ewfwq"]
var/speed/name = "speed"
var/speed/type = 3
var/speed/value = 400.0
var/speed/hint = 1
var/speed/hint_string = "10,1000,10"
[sub_resource type="BBNode" id="BBNode_fq0jf"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_rsejo"]
animation_player = SubResource("BBNode_fq0jf")
animation_name = &"idle"
[sub_resource type="BTWait" id="BTWait_dl31p"]
duration = 3.0
[sub_resource type="BBNode" id="BBNode_6d0yy"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_wsspf"]
animation_player = SubResource("BBNode_6d0yy")
animation_name = &"walk"
[sub_resource type="BTAction" id="BTAction_fc1oo"]
script = ExtResource("1_gk66j")
range_min = 300.0
range_max = 500.0
position_var = "pos"
[sub_resource type="BTAction" id="BTAction_djl5v"]
script = ExtResource("2_v5eou")
target_position_var = "pos"
speed_var = "speed"
tolerance = 50.0
avoid_var = ""
[sub_resource type="BTFail" id="BTFail_i2f36"]
[sub_resource type="BTComment" id="BTComment_4i06i"]
custom_name = "👇️ Sequence is never going to reach this task, because it fails at the previous step."
[sub_resource type="BTWait" id="BTWait_yxpnx"]
duration = 888.0
[sub_resource type="BTSequence" id="BTSequence_vx4uy"]
children = [SubResource("BTPlayAnimation_rsejo"), SubResource("BTWait_dl31p"), SubResource("BTPlayAnimation_wsspf"), SubResource("BTAction_fc1oo"), SubResource("BTAction_djl5v"), SubResource("BTFail_i2f36"), SubResource("BTComment_4i06i"), SubResource("BTWait_yxpnx")]
[resource]
description = "The [comp]Sequence[/comp] is one of the core composite tasks. It executes its children sequentially, from first to last, until one of them returns [FAILURE], or all of them result in [SUCCESS]. In other words, if any child task results in [FAILURE], the Sequence execution will be aborted, and the Sequence itself will return [FAILURE].
In our example, you can observe a simple [comp]Sequence[/comp] in action. Notice how it fails when it reaches the [act]Fail[/act] action and never proceeds to the [act]Wait 888 sec[/act] action afterward. By the way, the simple [act]Fail[/act] task is quite useful for troubleshooting. Its sole function is to return [FAILURE].
"
blackboard_plan = SubResource("BlackboardPlan_ewfwq")
root_task = SubResource("BTSequence_vx4uy")

View File

@ -0,0 +1,108 @@
[gd_resource type="BehaviorTree" load_steps=26 format=3 uid="uid://bf4r652fv5kwi"]
[ext_resource type="Script" path="res://demo/ai/tasks/get_first_in_group.gd" id="1_3ed74"]
[ext_resource type="Script" path="res://demo/ai/tasks/select_random_nearby_pos.gd" id="1_rvh1c"]
[ext_resource type="Script" path="res://demo/ai/tasks/in_range.gd" id="2_jfsyt"]
[ext_resource type="Script" path="res://demo/ai/tasks/pursue.gd" id="2_nnswb"]
[ext_resource type="Script" path="res://demo/ai/tasks/arrive_pos.gd" id="2_t62a0"]
[sub_resource type="BlackboardPlan" id="BlackboardPlan_ewfwq"]
var/speed/name = "speed"
var/speed/type = 3
var/speed/value = 400.0
var/speed/hint = 1
var/speed/hint_string = "10,1000,10"
[sub_resource type="BTCondition" id="BTCondition_x0uu7"]
script = ExtResource("2_jfsyt")
distance_min = 0.0
distance_max = 200.0
target_var = "target"
[sub_resource type="BBNode" id="BBNode_icf24"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_iiei3"]
animation_player = SubResource("BBNode_icf24")
animation_name = &"walk"
[sub_resource type="BTAction" id="BTAction_824oc"]
script = ExtResource("1_rvh1c")
range_min = 700.0
range_max = 800.0
position_var = "pos"
[sub_resource type="BTAction" id="BTAction_y1you"]
script = ExtResource("2_t62a0")
target_position_var = "pos"
speed_var = "speed"
tolerance = 50.0
avoid_var = ""
[sub_resource type="BBNode" id="BBNode_ayt56"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_l1tdg"]
animation_player = SubResource("BBNode_ayt56")
animation_name = &"idle"
[sub_resource type="BTWait" id="BTWait_hh8ys"]
duration = 3.0
[sub_resource type="BTSequence" id="BTSequence_cgwor"]
children = [SubResource("BTCondition_x0uu7"), SubResource("BTPlayAnimation_iiei3"), SubResource("BTAction_824oc"), SubResource("BTAction_y1you"), SubResource("BTPlayAnimation_l1tdg"), SubResource("BTWait_hh8ys")]
[sub_resource type="BTCondition" id="BTCondition_d6aub"]
script = ExtResource("2_jfsyt")
distance_min = 200.0
distance_max = 10000.0
target_var = "target"
[sub_resource type="BBNode" id="BBNode_6d0yy"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_wsspf"]
animation_player = SubResource("BBNode_6d0yy")
animation_name = &"walk"
[sub_resource type="BTAction" id="BTAction_wc11r"]
script = ExtResource("2_nnswb")
target_var = "target"
speed_var = "speed"
approach_distance = 100.0
[sub_resource type="BBNode" id="BBNode_aw5jj"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_3aihc"]
animation_player = SubResource("BBNode_aw5jj")
animation_name = &"idle"
[sub_resource type="BTWait" id="BTWait_1o163"]
duration = 3.0
[sub_resource type="BTSequence" id="BTSequence_vx4uy"]
children = [SubResource("BTCondition_d6aub"), SubResource("BTPlayAnimation_wsspf"), SubResource("BTAction_wc11r"), SubResource("BTPlayAnimation_3aihc"), SubResource("BTWait_1o163")]
[sub_resource type="BTAction" id="BTAction_2murg"]
script = ExtResource("1_3ed74")
group = &"player"
output_var = "target"
[sub_resource type="BTSelector" id="BTSelector_ddhoo"]
children = [SubResource("BTSequence_cgwor"), SubResource("BTSequence_vx4uy"), SubResource("BTAction_2murg")]
[resource]
description = "The [comp]Selector[/comp] is another essential composite task. It executes its children sequentially, from first to last, until one of them returns [SUCCESS] or all of them result in [FAILURE]. In other words, when a child task results in [FAILURE], it moves on to the next one until it finds the one that returns [SUCCESS]. Once a child task results in [SUCCESS], the Selector stops and also returns [SUCCESS].
To understand the [comp]Selector[/comp], it helps to see it as the opposite of the [comp]Sequence[/comp]. While the Sequence continues iterating over children as long as they return [SUCCESS], the Selector does the same but as long as they return [FAILURE]. The purpose of the Selector is to find a child that succeeds. It's often useful to place higher priority tasks at the top so that the Selector attempts them first.
[comp]Selector[/comp] is frequently used with [comp]Sequence[/comp] and [con]Condition[/con] tasks to control the behavior tree's flow. A condition task would prevent a Sequence from proceeding if it evaluates to [FAILURE], and thus the Selector would try the next child.
In our example, the [con]InRange[/con] condition checks how far Junior is from the target. When Junior is farther than 200 pixels from the target, he'll attempt to approach it. If he is closer than 200 pixels from the target, he would try to walk away. Thanks to the Selector, only one of these behaviors will be performed at a time, based on the result of the [con]InRange[/con] check. Junior seems to have a dilemma — unable to decide whether to stay or go."
blackboard_plan = SubResource("BlackboardPlan_ewfwq")
root_task = SubResource("BTSelector_ddhoo")

View File

@ -0,0 +1,136 @@
[gd_resource type="BehaviorTree" load_steps=34 format=3 uid="uid://beiki511huxb8"]
[ext_resource type="Script" path="res://demo/ai/tasks/get_first_in_group.gd" id="1_3xoj7"]
[ext_resource type="Script" path="res://demo/ai/tasks/in_range.gd" id="2_08b67"]
[ext_resource type="Script" path="res://demo/ai/tasks/face_target.gd" id="3_orhnl"]
[ext_resource type="Script" path="res://demo/ai/tasks/select_random_nearby_pos.gd" id="4_oyght"]
[ext_resource type="Script" path="res://demo/ai/tasks/arrive_pos.gd" id="5_5o1gy"]
[ext_resource type="Script" path="res://demo/ai/tasks/pursue.gd" id="6_rpn40"]
[sub_resource type="BlackboardPlan" id="BlackboardPlan_ewfwq"]
var/speed/name = "speed"
var/speed/type = 3
var/speed/value = 400.0
var/speed/hint = 1
var/speed/hint_string = "10,1000,10"
[sub_resource type="BTAction" id="BTAction_2murg"]
script = ExtResource("1_3xoj7")
group = &"player"
output_var = "target"
[sub_resource type="BTRunLimit" id="BTRunLimit_60b8b"]
children = [SubResource("BTAction_2murg")]
[sub_resource type="BTCondition" id="BTCondition_m15aa"]
script = ExtResource("2_08b67")
distance_min = 0.0
distance_max = 200.0
target_var = "target"
[sub_resource type="BTAction" id="BTAction_oc76s"]
script = ExtResource("3_orhnl")
target_var = "target"
[sub_resource type="BBNode" id="BBNode_6d0yy"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_wsspf"]
await_completion = 5.0
animation_player = SubResource("BBNode_6d0yy")
animation_name = &"attack_1"
[sub_resource type="BTSequence" id="BTSequence_e0f8v"]
children = [SubResource("BTCondition_m15aa"), SubResource("BTAction_oc76s"), SubResource("BTPlayAnimation_wsspf")]
[sub_resource type="BTCooldown" id="BTCooldown_3tvjt"]
duration = 5.0
children = [SubResource("BTSequence_e0f8v")]
[sub_resource type="BTCondition" id="BTCondition_x0uu7"]
script = ExtResource("2_08b67")
distance_min = 0.0
distance_max = 200.0
target_var = "target"
[sub_resource type="BBNode" id="BBNode_icf24"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_iiei3"]
animation_player = SubResource("BBNode_icf24")
animation_name = &"walk"
[sub_resource type="BTAction" id="BTAction_824oc"]
script = ExtResource("4_oyght")
range_min = 700.0
range_max = 800.0
position_var = "pos"
[sub_resource type="BTAction" id="BTAction_y1you"]
script = ExtResource("5_5o1gy")
target_position_var = "pos"
speed_var = "speed"
tolerance = 50.0
avoid_var = ""
[sub_resource type="BBNode" id="BBNode_ayt56"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_l1tdg"]
animation_player = SubResource("BBNode_ayt56")
animation_name = &"idle"
[sub_resource type="BTWait" id="BTWait_hh8ys"]
duration = 3.0
[sub_resource type="BTSequence" id="BTSequence_cgwor"]
children = [SubResource("BTCondition_x0uu7"), SubResource("BTPlayAnimation_iiei3"), SubResource("BTAction_824oc"), SubResource("BTAction_y1you"), SubResource("BTPlayAnimation_l1tdg"), SubResource("BTWait_hh8ys")]
[sub_resource type="BTCondition" id="BTCondition_d6aub"]
script = ExtResource("2_08b67")
distance_min = 200.0
distance_max = 10000.0
target_var = "target"
[sub_resource type="BBNode" id="BBNode_rpwld"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_dug2k"]
animation_player = SubResource("BBNode_rpwld")
animation_name = &"walk"
[sub_resource type="BTAction" id="BTAction_wc11r"]
script = ExtResource("6_rpn40")
target_var = "target"
speed_var = "speed"
approach_distance = 100.0
[sub_resource type="BBNode" id="BBNode_aw5jj"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_3aihc"]
animation_player = SubResource("BBNode_aw5jj")
animation_name = &"idle"
[sub_resource type="BTWait" id="BTWait_1o163"]
duration = 0.5
[sub_resource type="BTSequence" id="BTSequence_vx4uy"]
children = [SubResource("BTCondition_d6aub"), SubResource("BTPlayAnimation_dug2k"), SubResource("BTAction_wc11r"), SubResource("BTPlayAnimation_3aihc"), SubResource("BTWait_1o163")]
[sub_resource type="BTSelector" id="BTSelector_ddhoo"]
children = [SubResource("BTRunLimit_60b8b"), SubResource("BTCooldown_3tvjt"), SubResource("BTSequence_cgwor"), SubResource("BTSequence_vx4uy")]
[resource]
description = "Let's improve our previous behavior, and take the opportunity to discuss [dec]Decorators[/dec]. As mentioned earlier, decorators are control tasks that should only have a single child. Typically, a decorator either alters how its child operates or modifies its return status. They are often a useful tool for introducing variance into behaviors that otherwise lack it.
In our example, we utilize the [dec]RunLimit[/dec] decorator to restrict its child from running more than once. After executing the first time, the child will never receive another tick. This is quite handy for all sorts of setup logic!
Now, let's examine another decorator we use here - the [dec]Cooldown[/dec]. This decorator executes its child task only if the specified duration time has passed since the previous execution of the child task. The first time the attack sequence results in [SUCCESS], it triggers the cooldown, preventing the [comp]Sequence[/comp] from being executed for the next 5 seconds. During this period, the Cooldown returns [FAILURE] until the specified duration time elapses. It's important to note that it only counts executions that finished with [SUCCESS]. This means that [con]InRange[/con] can be utilized here without triggering the Cooldown!"
blackboard_plan = SubResource("BlackboardPlan_ewfwq")
root_task = SubResource("BTSelector_ddhoo")

View File

@ -0,0 +1,143 @@
[gd_resource type="BehaviorTree" load_steps=36 format=3 uid="uid://tep50j4d6kgp"]
[ext_resource type="Script" path="res://demo/ai/tasks/get_first_in_group.gd" id="1_f605f"]
[ext_resource type="Script" path="res://demo/ai/tasks/in_range.gd" id="2_mj1cj"]
[ext_resource type="Script" path="res://demo/ai/tasks/face_target.gd" id="3_86p0r"]
[ext_resource type="Script" path="res://demo/ai/tasks/back_away.gd" id="4_u0vk1"]
[ext_resource type="Script" path="res://demo/ai/tasks/pursue.gd" id="6_1yikm"]
[sub_resource type="BlackboardPlan" id="BlackboardPlan_ewfwq"]
var/speed/name = "speed"
var/speed/type = 3
var/speed/value = 400.0
var/speed/hint = 1
var/speed/hint_string = "10,1000,10"
[sub_resource type="BTAction" id="BTAction_2murg"]
script = ExtResource("1_f605f")
group = &"player"
output_var = "target"
[sub_resource type="BTRunLimit" id="BTRunLimit_60b8b"]
children = [SubResource("BTAction_2murg")]
[sub_resource type="BTCondition" id="BTCondition_m15aa"]
script = ExtResource("2_mj1cj")
distance_min = 0.0
distance_max = 200.0
target_var = "target"
[sub_resource type="BTAction" id="BTAction_oc76s"]
script = ExtResource("3_86p0r")
target_var = "target"
[sub_resource type="BBNode" id="BBNode_6d0yy"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_wsspf"]
await_completion = 5.0
animation_player = SubResource("BBNode_6d0yy")
animation_name = &"attack_1"
[sub_resource type="BBNode" id="BBNode_w45kn"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_d2lad"]
await_completion = 5.0
animation_player = SubResource("BBNode_w45kn")
animation_name = &"attack_2"
[sub_resource type="BTSequence" id="BTSequence_e0f8v"]
children = [SubResource("BTCondition_m15aa"), SubResource("BTAction_oc76s"), SubResource("BTPlayAnimation_wsspf"), SubResource("BTPlayAnimation_d2lad")]
[sub_resource type="BTCooldown" id="BTCooldown_3tvjt"]
duration = 5.0
children = [SubResource("BTSequence_e0f8v")]
[sub_resource type="BTCondition" id="BTCondition_x0uu7"]
script = ExtResource("2_mj1cj")
distance_min = 0.0
distance_max = 200.0
target_var = "target"
[sub_resource type="BBNode" id="BBNode_wksgd"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_umlwj"]
animation_player = SubResource("BBNode_wksgd")
animation_name = &"walk"
[sub_resource type="BTAction" id="BTAction_6q0k4"]
script = ExtResource("4_u0vk1")
speed_var = "speed"
max_angle_deviation = 0.7
[sub_resource type="BTTimeLimit" id="BTTimeLimit_6eii7"]
time_limit = 2.0
children = [SubResource("BTAction_6q0k4")]
[sub_resource type="BTAlwaysSucceed" id="BTAlwaysSucceed_ieord"]
children = [SubResource("BTTimeLimit_6eii7")]
[sub_resource type="BBNode" id="BBNode_ayt56"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_l1tdg"]
animation_player = SubResource("BBNode_ayt56")
animation_name = &"idle"
[sub_resource type="BTWait" id="BTWait_hh8ys"]
duration = 3.0
[sub_resource type="BTSequence" id="BTSequence_cgwor"]
children = [SubResource("BTCondition_x0uu7"), SubResource("BTPlayAnimation_umlwj"), SubResource("BTAlwaysSucceed_ieord"), SubResource("BTPlayAnimation_l1tdg"), SubResource("BTWait_hh8ys")]
[sub_resource type="BTCondition" id="BTCondition_d6aub"]
script = ExtResource("2_mj1cj")
distance_min = 200.0
distance_max = 10000.0
target_var = "target"
[sub_resource type="BBNode" id="BBNode_rpwld"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_dug2k"]
animation_player = SubResource("BBNode_rpwld")
animation_name = &"walk"
[sub_resource type="BTAction" id="BTAction_wc11r"]
script = ExtResource("6_1yikm")
target_var = "target"
speed_var = "speed"
approach_distance = 100.0
[sub_resource type="BBNode" id="BBNode_aw5jj"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_3aihc"]
animation_player = SubResource("BBNode_aw5jj")
animation_name = &"idle"
[sub_resource type="BTWait" id="BTWait_1o163"]
duration = 0.5
[sub_resource type="BTSequence" id="BTSequence_vx4uy"]
children = [SubResource("BTCondition_d6aub"), SubResource("BTPlayAnimation_dug2k"), SubResource("BTAction_wc11r"), SubResource("BTPlayAnimation_3aihc"), SubResource("BTWait_1o163")]
[sub_resource type="BTSelector" id="BTSelector_ddhoo"]
children = [SubResource("BTRunLimit_60b8b"), SubResource("BTCooldown_3tvjt"), SubResource("BTSequence_cgwor"), SubResource("BTSequence_vx4uy")]
[resource]
description = "Let's explore some other [dec]Decorators[/dec]. Here's a slightly improved version of the previous behavior. We incorporate the [dec]TimeLimit[/dec] decorator with the [act]Back Away[/act] action to achieve a similar effect as before (walking away from the target). The TimeLimit decorator ensures that the child task does not take too long to finish its work. If the time runs out, the task's execution will be aborted, and TimeLimit will return [FAILURE].
Another useful decorator is [dec]AlwaysSucceed[/dec], which converts any [FAILURE] returned by its child into [SUCCESS]. We use this decorator here because TimeLimit may result in [FAILURE], but we still want the [comp]Sequence[/comp] to continue. Also, there are similar decorators such as [dec]AlwaysFail[/dec] and [dec]Invert[/dec], which you can use in your behavior trees as needed.
We also add a second attack, so that Junior feels more badass now. We've got a little hit-and-run behavior going on here!"
blackboard_plan = SubResource("BlackboardPlan_ewfwq")
root_task = SubResource("BTSelector_ddhoo")

View File

@ -0,0 +1,204 @@
[gd_resource type="BehaviorTree" load_steps=52 format=3 uid="uid://dp0cglcytwcj5"]
[ext_resource type="Script" path="res://demo/ai/tasks/get_first_in_group.gd" id="1_o5ahw"]
[ext_resource type="Script" path="res://demo/ai/tasks/select_flanking_pos.gd" id="2_er25a"]
[ext_resource type="Script" path="res://demo/ai/tasks/arrive_pos.gd" id="3_ed1xo"]
[ext_resource type="Script" path="res://demo/ai/tasks/face_target.gd" id="4_128ei"]
[ext_resource type="Script" path="res://demo/ai/tasks/in_range.gd" id="5_er18b"]
[ext_resource type="Script" path="res://demo/ai/tasks/back_away.gd" id="6_1urfq"]
[ext_resource type="Script" path="res://demo/ai/tasks/pursue.gd" id="7_ekws5"]
[sub_resource type="BlackboardPlan" id="BlackboardPlan_ewfwq"]
var/speed/name = "speed"
var/speed/type = 3
var/speed/value = 400.0
var/speed/hint = 1
var/speed/hint_string = "10,1000,10"
[sub_resource type="BTAction" id="BTAction_2murg"]
script = ExtResource("1_o5ahw")
group = &"player"
output_var = "target"
[sub_resource type="BTRunLimit" id="BTRunLimit_60b8b"]
children = [SubResource("BTAction_2murg")]
[sub_resource type="BTCondition" id="BTCondition_m15aa"]
script = ExtResource("5_er18b")
distance_min = 0.0
distance_max = 200.0
target_var = "target"
[sub_resource type="BTAction" id="BTAction_oc76s"]
script = ExtResource("4_128ei")
target_var = "target"
[sub_resource type="BBNode" id="BBNode_6d0yy"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_wsspf"]
await_completion = 5.0
animation_player = SubResource("BBNode_6d0yy")
animation_name = &"attack_1"
[sub_resource type="BBNode" id="BBNode_w45kn"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_d2lad"]
await_completion = 5.0
animation_player = SubResource("BBNode_w45kn")
animation_name = &"attack_2"
[sub_resource type="BTSequence" id="BTSequence_e0f8v"]
children = [SubResource("BTCondition_m15aa"), SubResource("BTAction_oc76s"), SubResource("BTPlayAnimation_wsspf"), SubResource("BTPlayAnimation_d2lad")]
[sub_resource type="BTCooldown" id="BTCooldown_3tvjt"]
duration = 5.0
children = [SubResource("BTSequence_e0f8v")]
[sub_resource type="BTCondition" id="BTCondition_x0uu7"]
script = ExtResource("5_er18b")
distance_min = 0.0
distance_max = 200.0
target_var = "target"
[sub_resource type="BBNode" id="BBNode_wksgd"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_umlwj"]
animation_player = SubResource("BBNode_wksgd")
animation_name = &"walk"
[sub_resource type="BTAction" id="BTAction_6q0k4"]
script = ExtResource("6_1urfq")
speed_var = "speed"
max_angle_deviation = 0.7
[sub_resource type="BTTimeLimit" id="BTTimeLimit_6eii7"]
time_limit = 2.0
children = [SubResource("BTAction_6q0k4")]
[sub_resource type="BTAlwaysSucceed" id="BTAlwaysSucceed_ieord"]
children = [SubResource("BTTimeLimit_6eii7")]
[sub_resource type="BBNode" id="BBNode_ayt56"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_l1tdg"]
animation_player = SubResource("BBNode_ayt56")
animation_name = &"idle"
[sub_resource type="BTWait" id="BTWait_hh8ys"]
duration = 3.0
[sub_resource type="BTSequence" id="BTSequence_cgwor"]
children = [SubResource("BTCondition_x0uu7"), SubResource("BTPlayAnimation_umlwj"), SubResource("BTAlwaysSucceed_ieord"), SubResource("BTPlayAnimation_l1tdg"), SubResource("BTWait_hh8ys")]
[sub_resource type="BTAction" id="BTAction_n0rxm"]
script = ExtResource("2_er25a")
target_var = "target"
flank_side = 0
range_min = 400
range_max = 500
position_var = "pos"
[sub_resource type="BBNode" id="BBNode_icf24"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_iiei3"]
animation_player = SubResource("BBNode_icf24")
animation_name = &"walk"
[sub_resource type="BTAction" id="BTAction_g2up4"]
script = ExtResource("3_ed1xo")
target_position_var = "pos"
speed_var = "speed"
tolerance = 50.0
avoid_var = ""
[sub_resource type="BTAction" id="BTAction_d5lkr"]
script = ExtResource("4_128ei")
target_var = "target"
[sub_resource type="BBNode" id="BBNode_h4k80"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_40yja"]
animation_player = SubResource("BBNode_h4k80")
animation_name = &"throw_prepare"
[sub_resource type="BTWait" id="BTWait_2dc1v"]
[sub_resource type="BBNode" id="BBNode_slipn"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_qnpjq"]
await_completion = 5.0
animation_player = SubResource("BBNode_slipn")
animation_name = &"throw"
[sub_resource type="BBNode" id="BBNode_qaqnn"]
saved_value = NodePath(".")
resource_name = "."
[sub_resource type="BTCallMethod" id="BTCallMethod_yd0fn"]
node = SubResource("BBNode_qaqnn")
method = &"throw_ninja_star"
[sub_resource type="BTSequence" id="BTSequence_ws7nq"]
children = [SubResource("BTAction_n0rxm"), SubResource("BTPlayAnimation_iiei3"), SubResource("BTAction_g2up4"), SubResource("BTAction_d5lkr"), SubResource("BTPlayAnimation_40yja"), SubResource("BTWait_2dc1v"), SubResource("BTPlayAnimation_qnpjq"), SubResource("BTCallMethod_yd0fn")]
[sub_resource type="BTProbability" id="BTProbability_omklt"]
run_chance = 0.25
children = [SubResource("BTSequence_ws7nq")]
[sub_resource type="BTCondition" id="BTCondition_d6aub"]
script = ExtResource("5_er18b")
distance_min = 200.0
distance_max = 10000.0
target_var = "target"
[sub_resource type="BBNode" id="BBNode_rpwld"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_dug2k"]
animation_player = SubResource("BBNode_rpwld")
animation_name = &"walk"
[sub_resource type="BTAction" id="BTAction_wc11r"]
script = ExtResource("7_ekws5")
target_var = "target"
speed_var = "speed"
approach_distance = 100.0
[sub_resource type="BBNode" id="BBNode_aw5jj"]
saved_value = NodePath("AnimationPlayer")
resource_name = "AnimationPlayer"
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_3aihc"]
animation_player = SubResource("BBNode_aw5jj")
animation_name = &"idle"
[sub_resource type="BTWait" id="BTWait_1o163"]
duration = 0.5
[sub_resource type="BTSequence" id="BTSequence_vx4uy"]
children = [SubResource("BTCondition_d6aub"), SubResource("BTPlayAnimation_dug2k"), SubResource("BTAction_wc11r"), SubResource("BTPlayAnimation_3aihc"), SubResource("BTWait_1o163")]
[sub_resource type="BTSelector" id="BTSelector_ddhoo"]
children = [SubResource("BTRunLimit_60b8b"), SubResource("BTCooldown_3tvjt"), SubResource("BTSequence_cgwor"), SubResource("BTProbability_omklt"), SubResource("BTSequence_vx4uy")]
[resource]
description = "And for the final touch, we've added throwing ninja stars to our previous behavior. The [dec]Probability[/dec] decorator adds a little variance so that we don't throw ninja stars all the time. This decorator executes its child task with a certain probability, so when it's not 100%, sometimes it will return [FAILURE] instead. Some of the work in this [comp]Sequence[/comp] is done by actions you've seen already, and the [act]CallMethod[/act] action invokes the [color=cyan]throw_ninja_star[/color] method on the agent node. By the way, the agent is always the owner of the BTPlayer node, which executes this behavior tree.
This concludes our tutorial. Hopefully, this little endeavor has been useful to you. You can learn more by reading the [b]Online Documentation[/b], which covers topics like creating your own tasks. Also, check out the [b]Showcase[/b], which presents behaviors of agents made for this little demo. Simply click \"End Tutorial\" to return to the [b]Showcase[/b]."
blackboard_plan = SubResource("BlackboardPlan_ewfwq")
root_task = SubResource("BTSelector_ddhoo")

Binary file not shown.

View File

@ -5,19 +5,25 @@ extends Node2D
@onready var agent_selection: MenuButton = %AgentSelection @onready var agent_selection: MenuButton = %AgentSelection
@onready var previous: Button = %Previous @onready var previous: Button = %Previous
@onready var next: Button = %Next @onready var next: Button = %Next
@onready var minimize_description: Button = %MinimizeDescription
@onready var description: RichTextLabel = %Description
@onready var begin_tutorial: Button = %BeginTutorial
@onready var navigation_hint: Label = %NavigationHint
@onready var scene_title: Label = %SceneTitle
var bt_player: BTPlayer var bt_player: BTPlayer
var selected_tree_index: int = -1 var selected_tree_index: int = -1
var agent_files: Array[String] var agent_files: Array[String]
var agents_dir: String
var is_tutorial: bool = false
func _ready() -> void: func _ready() -> void:
_populate_agent_files()
_on_agent_selection_id_pressed(0)
agent_selection.get_popup().id_pressed.connect(_on_agent_selection_id_pressed) agent_selection.get_popup().id_pressed.connect(_on_agent_selection_id_pressed)
previous.pressed.connect(func(): _on_agent_selection_id_pressed(selected_tree_index - 1)) previous.pressed.connect(func(): _on_agent_selection_id_pressed(selected_tree_index - 1))
next.pressed.connect(func(): _on_agent_selection_id_pressed(selected_tree_index + 1)) next.pressed.connect(func(): _on_agent_selection_id_pressed(selected_tree_index + 1))
_initialize()
func _physics_process(_delta: float) -> void: func _physics_process(_delta: float) -> void:
var inst: BTTask = bt_player.get_tree_instance() var inst: BTTask = bt_player.get_tree_instance()
@ -25,6 +31,21 @@ func _physics_process(_delta: float) -> void:
behavior_tree_view.update_tree(bt_data) behavior_tree_view.update_tree(bt_data)
func _initialize() -> void:
if is_tutorial:
_populate_agent_files("res://demo/agents/tutorial/")
begin_tutorial.text = "End Tutorial"
navigation_hint.text = "Navigate ➤"
scene_title.text = "Tutorial"
_on_agent_selection_id_pressed(0)
else:
_populate_agent_files("res://demo/agents/")
begin_tutorial.text = "Begin Tutorial"
navigation_hint.text = "Select Agent ➤"
scene_title.text = "Showcase"
_on_agent_selection_id_pressed(0)
func _attach_camera(agent: CharacterBody2D) -> void: func _attach_camera(agent: CharacterBody2D) -> void:
await get_tree().process_frame await get_tree().process_frame
camera.get_parent().remove_child(camera) camera.get_parent().remove_child(camera)
@ -32,13 +53,14 @@ func _attach_camera(agent: CharacterBody2D) -> void:
camera.position = Vector2(400.0, 0.0) camera.position = Vector2(400.0, 0.0)
func _populate_agent_files() -> void: func _populate_agent_files(p_path: String = "res://demo/agents/") -> void:
var popup: PopupMenu = agent_selection.get_popup() var popup: PopupMenu = agent_selection.get_popup()
popup.clear() popup.clear()
popup.reset_size() popup.reset_size()
agent_files.clear() agent_files.clear()
agents_dir = p_path
var dir := DirAccess.open("res://demo/agents/") var dir := DirAccess.open(p_path)
if dir: if dir:
dir.list_dir_begin() dir.list_dir_begin()
var file_name: String = dir.get_next() var file_name: String = dir.get_next()
@ -66,17 +88,47 @@ func _load_agent(file_name: String) -> void:
var agent: CharacterBody2D = agent_res.instantiate() var agent: CharacterBody2D = agent_res.instantiate()
add_child(agent) add_child(agent)
bt_player = agent.find_child("BTPlayer") bt_player = agent.find_child("BTPlayer")
description.text = _parse_description(bt_player.behavior_tree.description)
_attach_camera(agent) _attach_camera(agent)
func _parse_description(p_desc: String) -> String:
return p_desc \
.replace("[SUCCESS]", "[color=PaleGreen]SUCCESS[/color]") \
.replace("[FAILURE]", "[color=IndianRed]FAILURE[/color]") \
.replace("[RUNNING]", "[color=orange]RUNNING[/color]") \
.replace("[comp]", "[color=CornflowerBlue][b]") \
.replace("[/comp]", "[/b][/color]") \
.replace("[act]", "[color=white][b]") \
.replace("[/act]", "[/b][/color]") \
.replace("[dec]", "[color=MediumOrchid][b]") \
.replace("[/dec]", "[/b][/color]") \
.replace("[con]", "[color=orange][b]") \
.replace("[/con]", "[/b][/color]")
func _on_agent_selection_id_pressed(id: int) -> void: func _on_agent_selection_id_pressed(id: int) -> void:
assert(id >= 0 and id < agent_files.size()) assert(id >= 0 and id < agent_files.size())
selected_tree_index = id selected_tree_index = id
_load_agent("res://demo/agents/".path_join(agent_files[id])) _load_agent(agents_dir.path_join(agent_files[id]))
agent_selection.text = bt_player.behavior_tree.resource_path.get_file() agent_selection.text = bt_player.behavior_tree.resource_path.get_file()
if agent_selection.text.to_lower() != agent_selection.text:
# Treat filename as a title
agent_selection.text = agent_selection.text.trim_suffix(".tres")
previous.disabled = id == 0 previous.disabled = id == 0
next.disabled = id == (agent_files.size()-1) next.disabled = id == (agent_files.size()-1)
func _on_switch_to_game_pressed() -> void: func _on_switch_to_game_pressed() -> void:
get_tree().change_scene_to_file("res://demo/scenes/game.tscn") get_tree().change_scene_to_file("res://demo/scenes/game.tscn")
func _on_minimize_description_button_down() -> void:
description.visible = not description.visible
minimize_description.text = "-" if description.visible else "+"
func _on_tutorial_pressed() -> void:
is_tutorial = not is_tutorial
_initialize()

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=11 format=3 uid="uid://b3ae14mc2ty3y"] [gd_scene load_steps=13 format=3 uid="uid://b3ae14mc2ty3y"]
[ext_resource type="Script" path="res://demo/scenes/showcase.gd" id="1_l12ql"] [ext_resource type="Script" path="res://demo/scenes/showcase.gd" id="1_l12ql"]
[ext_resource type="Theme" uid="uid://boqtjf88xcpu4" path="res://demo/assets/ui.theme" id="2_3d7dj"] [ext_resource type="Theme" uid="uid://boqtjf88xcpu4" path="res://demo/assets/ui.theme" id="2_3d7dj"]
@ -9,6 +9,12 @@
[ext_resource type="PackedScene" uid="uid://bsig1usigbbuy" path="res://demo/scenes/base/arena.tscn" id="7_42nq6"] [ext_resource type="PackedScene" uid="uid://bsig1usigbbuy" path="res://demo/scenes/base/arena.tscn" id="7_42nq6"]
[ext_resource type="PackedScene" uid="uid://c5fhe3tulhlco" path="res://demo/props/dummy.tscn" id="8_apshw"] [ext_resource type="PackedScene" uid="uid://c5fhe3tulhlco" path="res://demo/props/dummy.tscn" id="8_apshw"]
[sub_resource type="LabelSettings" id="LabelSettings_rdr7a"]
font = ExtResource("3_7vli5")
font_size = 33
outline_size = 11
outline_color = Color(0.258915, 0.234974, 0.191974, 1)
[sub_resource type="LabelSettings" id="LabelSettings_3uhve"] [sub_resource type="LabelSettings" id="LabelSettings_3uhve"]
font = ExtResource("3_7vli5") font = ExtResource("3_7vli5")
font_size = 26 font_size = 26
@ -23,10 +29,16 @@ font_color = Color(1, 1, 0.239216, 1)
outline_size = 20 outline_size = 20
outline_color = Color(0.211521, 0.23888, 0.290166, 1) outline_color = Color(0.211521, 0.23888, 0.290166, 1)
[sub_resource type="LabelSettings" id="LabelSettings_tlprv"]
font = ExtResource("3_7vli5")
font_size = 23
font_color = Color(0.804089, 0.811917, 0.823636, 1)
outline_size = 10
outline_color = Color(0.145083, 0.168536, 0.203708, 1)
[node name="AgentShowcase" type="Node2D"] [node name="AgentShowcase" type="Node2D"]
y_sort_enabled = true y_sort_enabled = true
script = ExtResource("1_l12ql") script = ExtResource("1_l12ql")
metadata/_edit_horizontal_guides_ = [1019.0]
[node name="UI Layer" type="CanvasLayer" parent="."] [node name="UI Layer" type="CanvasLayer" parent="."]
@ -67,10 +79,26 @@ theme_override_fonts/font = ExtResource("3_7vli5")
theme_override_font_sizes/font_size = 22 theme_override_font_sizes/font_size = 22
text = "Switch to Game" text = "Switch to Game"
[node name="ClickToSelect" type="Label" parent="UI Layer/Control/Toolbar/HBoxContainer"] [node name="BeginTutorial" type="Button" parent="UI Layer/Control/Toolbar/HBoxContainer"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 10 focus_mode = 0
theme_override_fonts/font = ExtResource("3_7vli5")
theme_override_font_sizes/font_size = 22
text = "Begin Tutorial
"
[node name="SceneTitle" type="Label" parent="UI Layer/Control/Toolbar/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 6
text = "Tutorial"
label_settings = SubResource("LabelSettings_rdr7a")
[node name="NavigationHint" type="Label" parent="UI Layer/Control/Toolbar/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 8
text = "Select Agent ➤" text = "Select Agent ➤"
label_settings = SubResource("LabelSettings_3uhve") label_settings = SubResource("LabelSettings_3uhve")
horizontal_alignment = 2 horizontal_alignment = 2
@ -125,22 +153,28 @@ custom_minimum_size = Vector2(600, 0)
layout_mode = 2 layout_mode = 2
size_flags_vertical = 3 size_flags_vertical = 3
[node name="Logo" type="TextureRect" parent="UI Layer/Control"] [node name="PanelContainer" type="PanelContainer" parent="UI Layer/Control"]
layout_mode = 1 layout_mode = 1
anchors_preset = 3 anchors_preset = 12
anchor_left = 1.0
anchor_top = 1.0 anchor_top = 1.0
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
offset_left = -1899.0 offset_top = -8.0
offset_top = -130.0 offset_right = -612.0
offset_right = -1643.0 grow_horizontal = 2
offset_bottom = -45.0
grow_horizontal = 0
grow_vertical = 0 grow_vertical = 0
[node name="Control" type="Control" parent="UI Layer/Control/PanelContainer"]
layout_mode = 2
[node name="Logo" type="TextureRect" parent="UI Layer/Control/PanelContainer/Control"]
layout_mode = 1
offset_top = -128.0
offset_right = 256.0
offset_bottom = -43.0
texture = ExtResource("5_rwygb") texture = ExtResource("5_rwygb")
[node name="Demo project" type="Label" parent="UI Layer/Control/Logo"] [node name="Demo project" type="Label" parent="UI Layer/Control/PanelContainer/Control/Logo"]
layout_mode = 1 layout_mode = 1
anchors_preset = 3 anchors_preset = 3
anchor_left = 1.0 anchor_left = 1.0
@ -158,6 +192,54 @@ label_settings = SubResource("LabelSettings_la4ui")
horizontal_alignment = 2 horizontal_alignment = 2
vertical_alignment = 1 vertical_alignment = 1
[node name="Header" type="HBoxContainer" parent="UI Layer/Control/PanelContainer/Control"]
layout_mode = 2
offset_left = 3.0
offset_top = -43.0
offset_right = 1299.0
offset_bottom = -7.0
theme_override_constants/separation = 8
[node name="Label" type="Label" parent="UI Layer/Control/PanelContainer/Control/Header"]
layout_mode = 2
size_flags_horizontal = 10
text = "Description"
label_settings = SubResource("LabelSettings_tlprv")
[node name="MinimizeDescription" type="Button" parent="UI Layer/Control/PanelContainer/Control/Header"]
unique_name_in_owner = true
custom_minimum_size = Vector2(32, 32)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
focus_mode = 0
theme_override_fonts/font = ExtResource("3_7vli5")
text = "-"
[node name="MarginContainer" type="MarginContainer" parent="UI Layer/Control/PanelContainer"]
layout_mode = 2
theme_override_constants/margin_left = 20
theme_override_constants/margin_top = 6
theme_override_constants/margin_bottom = 6
[node name="VBoxContainer" type="VBoxContainer" parent="UI Layer/Control/PanelContainer/MarginContainer"]
layout_mode = 2
theme_override_constants/separation = 0
[node name="Description" type="RichTextLabel" parent="UI Layer/Control/PanelContainer/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 140)
layout_mode = 2
size_flags_vertical = 3
theme_override_font_sizes/normal_font_size = 20
theme_override_font_sizes/bold_font_size = 20
theme_override_font_sizes/italics_font_size = 20
theme_override_font_sizes/bold_italics_font_size = 20
theme_override_font_sizes/mono_font_size = 20
bbcode_enabled = true
text = "[b]Behavior Trees[/b] are composed of tasks that represent specific actions or decision-making rules. Tasks can be broadly categorized into two main types: control tasks and leaf tasks. Control tasks determine the execution flow within the tree. They include Sequence, Selector, and Invert. Leaf tasks represent specific actions to perform, like moving or attacking, or conditions that need to be checked. The BTTask class provides the foundation for various building blocks of the Behavior Trees. BT tasks can share data with the help of the Blackboard."
fit_content = true
[node name="Camera2D" type="Camera2D" parent="."] [node name="Camera2D" type="Camera2D" parent="."]
position = Vector2(400, 0) position = Vector2(400, 0)
zoom = Vector2(0.88, 0.88) zoom = Vector2(0.88, 0.88)
@ -177,3 +259,5 @@ metadata/_edit_lock_ = true
position = Vector2(1106, 423) position = Vector2(1106, 423)
[connection signal="pressed" from="UI Layer/Control/Toolbar/HBoxContainer/SwitchToGame" to="." method="_on_switch_to_game_pressed"] [connection signal="pressed" from="UI Layer/Control/Toolbar/HBoxContainer/SwitchToGame" to="." method="_on_switch_to_game_pressed"]
[connection signal="pressed" from="UI Layer/Control/Toolbar/HBoxContainer/BeginTutorial" to="." method="_on_tutorial_pressed"]
[connection signal="button_down" from="UI Layer/Control/PanelContainer/Control/Header/MinimizeDescription" to="." method="_on_minimize_description_button_down"]