Demo: Improved AI for melee and ranged
This commit is contained in:
parent
92ecc17a44
commit
f6ce516771
|
@ -21,7 +21,7 @@ func _generate_name() -> String:
|
||||||
|
|
||||||
# Called each time this task is ticked (aka executed).
|
# Called each time this task is ticked (aka executed).
|
||||||
func _tick(_delta: float) -> Status:
|
func _tick(_delta: float) -> Status:
|
||||||
var target := blackboard.get_var(target_var) as CharacterBody2D
|
var target: Node2D = blackboard.get_var(target_var)
|
||||||
if not is_instance_valid(target):
|
if not is_instance_valid(target):
|
||||||
return FAILURE
|
return FAILURE
|
||||||
var dir: float = target.global_position.x - agent.global_position.x
|
var dir: float = target.global_position.x - agent.global_position.x
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
#*
|
#*
|
||||||
@tool
|
@tool
|
||||||
extends BTAction
|
extends BTAction
|
||||||
## Pursue target.
|
## Pursue: Move towards target until agent is flanking it.
|
||||||
##
|
##
|
||||||
## Returns RUNNING, while moving towards target but not yet at the desired distance.
|
## Returns RUNNING, while moving towards target but not yet at the desired position.
|
||||||
## Returns SUCCESS, when at the desired distance from target.
|
## Returns SUCCESS, when at the desired position from target (flanking it).
|
||||||
## Returns FAILURE, if target is not a valid instance.
|
## Returns FAILURE, if target is not a valid Node2D instance.
|
||||||
|
|
||||||
|
|
||||||
const TOLERANCE := 30.0
|
const TOLERANCE := 30.0
|
||||||
|
@ -23,33 +23,48 @@ const TOLERANCE := 30.0
|
||||||
@export var speed_var: String = "speed"
|
@export var speed_var: String = "speed"
|
||||||
@export var approach_distance: float = 100.0
|
@export var approach_distance: float = 100.0
|
||||||
|
|
||||||
var _side: float
|
#var _side: float
|
||||||
|
var _waypoint: Vector2
|
||||||
|
|
||||||
# Display a customized name (requires @tool).
|
# Display a customized name (requires @tool).
|
||||||
func _generate_name() -> String:
|
func _generate_name() -> String:
|
||||||
return "Pursue %s" % [LimboUtility.decorate_var(target_var)]
|
return "Pursue %s" % [LimboUtility.decorate_var(target_var)]
|
||||||
|
|
||||||
# Called each time this task is entered.
|
|
||||||
func _enter() -> void:
|
func _enter() -> void:
|
||||||
_side = 0.0
|
var target: Node2D = blackboard.get_var(target_var, null)
|
||||||
|
if is_instance_valid(target):
|
||||||
|
_select_new_waypoint(_get_desired_position(target))
|
||||||
|
|
||||||
|
|
||||||
# Called each time this task is ticked (aka executed).
|
# Called each time this task is ticked (aka executed).
|
||||||
func _tick(_delta: float) -> Status:
|
func _tick(_delta: float) -> Status:
|
||||||
var target := blackboard.get_var(target_var, null) as CharacterBody2D
|
var target: Node2D = blackboard.get_var(target_var, null)
|
||||||
if not is_instance_valid(target):
|
if not is_instance_valid(target):
|
||||||
return FAILURE
|
return FAILURE
|
||||||
|
|
||||||
if _side == 0:
|
var desired_pos: Vector2 = _get_desired_position(target)
|
||||||
var dir: Vector2 = agent.global_position - target.global_position
|
if agent.global_position.distance_to(desired_pos) < TOLERANCE:
|
||||||
_side = signf(dir.x)
|
|
||||||
var target_pos := Vector2(
|
|
||||||
target.global_position.x + approach_distance * _side,
|
|
||||||
target.global_position.y)
|
|
||||||
|
|
||||||
if agent.global_position.distance_to(target_pos) < TOLERANCE:
|
|
||||||
return SUCCESS
|
return SUCCESS
|
||||||
|
|
||||||
var speed: float = blackboard.get_var(speed_var, 200.0)
|
var speed: float = blackboard.get_var(speed_var, 200.0)
|
||||||
agent.velocity = agent.global_position.direction_to(target_pos) * speed
|
if agent.global_position.distance_to(_waypoint) < TOLERANCE:
|
||||||
|
_select_new_waypoint(desired_pos)
|
||||||
|
agent.velocity = agent.global_position.direction_to(_waypoint) * speed
|
||||||
agent.move_and_slide()
|
agent.move_and_slide()
|
||||||
return RUNNING
|
return RUNNING
|
||||||
|
|
||||||
|
|
||||||
|
## Get closest flanking position to target.
|
||||||
|
func _get_desired_position(target: Node2D) -> Vector2:
|
||||||
|
var side: float = signf(agent.global_position.x - target.global_position.x)
|
||||||
|
var desired_pos: Vector2 = target.global_position
|
||||||
|
desired_pos.x += approach_distance * side
|
||||||
|
return desired_pos
|
||||||
|
|
||||||
|
|
||||||
|
## Select an intermidiate waypoint towards the desired position.
|
||||||
|
func _select_new_waypoint(desired_position: Vector2) -> void:
|
||||||
|
var distance_vector: Vector2 = desired_position - agent.global_position
|
||||||
|
var angle_variation: float = randf_range(-0.2, 0.2)
|
||||||
|
_waypoint = agent.global_position + distance_vector.limit_length(150.0).rotated(angle_variation)
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
@tool
|
||||||
|
extends BTAction
|
||||||
|
## SelectRandomNearbyPos: Select a position nearby within specified range.
|
||||||
|
## Returns SUCCESS.
|
||||||
|
|
||||||
|
## Maximum distance to the desired position.
|
||||||
|
@export var range_min: float = 300.0
|
||||||
|
@export var range_max: float = 500.0
|
||||||
|
@export var position_var: String = "_pos"
|
||||||
|
|
||||||
|
# Display a customized name (requires @tool).
|
||||||
|
func _generate_name() -> String:
|
||||||
|
return "SelectRandomNearbyPos range: [%s, %s] ➜%s" % [
|
||||||
|
range_min, range_max,
|
||||||
|
LimboUtility.decorate_var(position_var)]
|
||||||
|
|
||||||
|
# Called each time this task is ticked (aka executed).
|
||||||
|
func _tick(_delta: float) -> Status:
|
||||||
|
var angle: float = randf() * TAU
|
||||||
|
var rand_distance: float = randf_range(range_min, range_max)
|
||||||
|
var pos: Vector2 = agent.global_position + Vector2(sin(angle), cos(angle)) * rand_distance
|
||||||
|
blackboard.set_var(position_var, pos)
|
||||||
|
return SUCCESS
|
|
@ -1,4 +1,4 @@
|
||||||
[gd_resource type="BehaviorTree" load_steps=40 format=3 uid="uid://c2u6sljqkim0n"]
|
[gd_resource type="BehaviorTree" load_steps=41 format=3 uid="uid://c2u6sljqkim0n"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://demo/ai/tasks/get_first_in_group.gd" id="1_uvue5"]
|
[ext_resource type="Script" path="res://demo/ai/tasks/get_first_in_group.gd" id="1_uvue5"]
|
||||||
[ext_resource type="Script" path="res://demo/ai/tasks/pursue.gd" id="2_aanv5"]
|
[ext_resource type="Script" path="res://demo/ai/tasks/pursue.gd" id="2_aanv5"]
|
||||||
|
@ -28,8 +28,7 @@ animation_name = &"idle"
|
||||||
blend = 0.1
|
blend = 0.1
|
||||||
|
|
||||||
[sub_resource type="BTRandomWait" id="BTRandomWait_xlud8"]
|
[sub_resource type="BTRandomWait" id="BTRandomWait_xlud8"]
|
||||||
min_duration = 0.7
|
max_duration = 3.0
|
||||||
max_duration = 1.5
|
|
||||||
|
|
||||||
[sub_resource type="BTAction" id="BTAction_c4cxo"]
|
[sub_resource type="BTAction" id="BTAction_c4cxo"]
|
||||||
script = ExtResource("1_uvue5")
|
script = ExtResource("1_uvue5")
|
||||||
|
@ -54,8 +53,8 @@ speed = 1.5
|
||||||
script = ExtResource("2_fl3fr")
|
script = ExtResource("2_fl3fr")
|
||||||
target_var = "_target"
|
target_var = "_target"
|
||||||
closest_side = false
|
closest_side = false
|
||||||
range_min = 400.0
|
range_min = 400
|
||||||
range_max = 600.0
|
range_max = 600
|
||||||
position_var = "_flank_pos"
|
position_var = "_flank_pos"
|
||||||
|
|
||||||
[sub_resource type="BTAction" id="BTAction_66hsk"]
|
[sub_resource type="BTAction" id="BTAction_66hsk"]
|
||||||
|
@ -133,8 +132,10 @@ resource_name = "AnimationPlayer"
|
||||||
animation_player = SubResource("BBNode_s6vt4")
|
animation_player = SubResource("BBNode_s6vt4")
|
||||||
animation_name = &"throw_prepare"
|
animation_name = &"throw_prepare"
|
||||||
blend = 0.1
|
blend = 0.1
|
||||||
|
speed = 0.7
|
||||||
|
|
||||||
[sub_resource type="BTWait" id="BTWait_gbcyb"]
|
[sub_resource type="BTWait" id="BTWait_gbcyb"]
|
||||||
|
duration = 1.3
|
||||||
|
|
||||||
[sub_resource type="BBNode" id="BBNode_qkfqt"]
|
[sub_resource type="BBNode" id="BBNode_qkfqt"]
|
||||||
saved_value = NodePath("AnimationPlayer")
|
saved_value = NodePath("AnimationPlayer")
|
||||||
|
@ -154,9 +155,12 @@ resource_name = "."
|
||||||
node = SubResource("BBNode_1yxc5")
|
node = SubResource("BBNode_1yxc5")
|
||||||
method = &"throw_ninja_star"
|
method = &"throw_ninja_star"
|
||||||
|
|
||||||
|
[sub_resource type="BTRandomWait" id="BTRandomWait_2pmoe"]
|
||||||
|
min_duration = 1.5
|
||||||
|
|
||||||
[sub_resource type="BTSequence" id="BTSequence_rgbq3"]
|
[sub_resource type="BTSequence" id="BTSequence_rgbq3"]
|
||||||
custom_name = "Throw ninja star"
|
custom_name = "Throw ninja star"
|
||||||
children = [SubResource("BTAction_8q20y"), SubResource("BTPlayAnimation_qa8jy"), SubResource("BTWait_gbcyb"), SubResource("BTPlayAnimation_0ktds"), SubResource("BTCallMethod_yx4fk")]
|
children = [SubResource("BTAction_8q20y"), SubResource("BTPlayAnimation_qa8jy"), SubResource("BTWait_gbcyb"), SubResource("BTPlayAnimation_0ktds"), SubResource("BTCallMethod_yx4fk"), SubResource("BTRandomWait_2pmoe")]
|
||||||
metadata/_weight_ = 1.0
|
metadata/_weight_ = 1.0
|
||||||
|
|
||||||
[sub_resource type="BTProbabilitySelector" id="BTProbabilitySelector_rjsiq"]
|
[sub_resource type="BTProbabilitySelector" id="BTProbabilitySelector_rjsiq"]
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
[gd_resource type="BehaviorTree" load_steps=29 format=3 uid="uid://cqluon1y1hnn5"]
|
[gd_resource type="BehaviorTree" load_steps=40 format=3 uid="uid://cqluon1y1hnn5"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://demo/ai/tasks/get_first_in_group.gd" id="1_3j1v8"]
|
[ext_resource type="Script" path="res://demo/ai/tasks/get_first_in_group.gd" id="1_3j1v8"]
|
||||||
[ext_resource type="Script" path="res://demo/ai/tasks/select_flanking_pos.gd" id="2_vbh52"]
|
[ext_resource type="Script" path="res://demo/ai/tasks/select_flanking_pos.gd" id="2_vbh52"]
|
||||||
[ext_resource type="Script" path="res://demo/ai/tasks/arrive_pos.gd" id="3_20ffh"]
|
[ext_resource type="Script" path="res://demo/ai/tasks/arrive_pos.gd" id="3_20ffh"]
|
||||||
[ext_resource type="Script" path="res://demo/ai/tasks/face_target.gd" id="4_x8yor"]
|
[ext_resource type="Script" path="res://demo/ai/tasks/face_target.gd" id="4_x8yor"]
|
||||||
|
[ext_resource type="Script" path="res://demo/ai/tasks/select_random_nearby_pos.gd" id="5_mexvv"]
|
||||||
|
|
||||||
[sub_resource type="BlackboardPlan" id="BlackboardPlan_46tbn"]
|
[sub_resource type="BlackboardPlan" id="BlackboardPlan_46tbn"]
|
||||||
var/speed/name = "speed"
|
var/speed/name = "speed"
|
||||||
|
@ -28,19 +29,55 @@ max_duration = 2.5
|
||||||
[sub_resource type="BTAction" id="BTAction_c4cxo"]
|
[sub_resource type="BTAction" id="BTAction_c4cxo"]
|
||||||
script = ExtResource("1_3j1v8")
|
script = ExtResource("1_3j1v8")
|
||||||
group = &"player"
|
group = &"player"
|
||||||
output_var = "_target"
|
output_var = "target"
|
||||||
|
|
||||||
[sub_resource type="BTSequence" id="BTSequence_yhjh1"]
|
[sub_resource type="BTSequence" id="BTSequence_yhjh1"]
|
||||||
custom_name = "Take a break"
|
custom_name = "Take a break"
|
||||||
children = [SubResource("BTPlayAnimation_qiw21"), SubResource("BTRandomWait_xlud8"), SubResource("BTAction_c4cxo")]
|
children = [SubResource("BTPlayAnimation_qiw21"), SubResource("BTRandomWait_xlud8"), SubResource("BTAction_c4cxo")]
|
||||||
|
|
||||||
|
[sub_resource type="BTComment" id="BTComment_qhsko"]
|
||||||
|
custom_name = "He is bored attacking player all the time ;)"
|
||||||
|
|
||||||
|
[sub_resource type="BTAction" id="BTAction_lpk67"]
|
||||||
|
script = ExtResource("5_mexvv")
|
||||||
|
range_min = 300.0
|
||||||
|
range_max = 500.0
|
||||||
|
position_var = "pos"
|
||||||
|
|
||||||
|
[sub_resource type="BBNode" id="BBNode_ok0r5"]
|
||||||
|
saved_value = NodePath("AnimationPlayer")
|
||||||
|
resource_name = "AnimationPlayer"
|
||||||
|
|
||||||
|
[sub_resource type="BTPlayAnimation" id="BTPlayAnimation_unftu"]
|
||||||
|
animation_player = SubResource("BBNode_ok0r5")
|
||||||
|
animation_name = &"walk"
|
||||||
|
blend = 0.1
|
||||||
|
|
||||||
|
[sub_resource type="BTAction" id="BTAction_apfsn"]
|
||||||
|
script = ExtResource("3_20ffh")
|
||||||
|
target_position_var = "pos"
|
||||||
|
speed_var = "speed"
|
||||||
|
tolerance = 50.0
|
||||||
|
|
||||||
|
[sub_resource type="BTTimeLimit" id="BTTimeLimit_baob7"]
|
||||||
|
time_limit = 3.0
|
||||||
|
children = [SubResource("BTAction_apfsn")]
|
||||||
|
|
||||||
|
[sub_resource type="BTSequence" id="BTSequence_0gdqn"]
|
||||||
|
custom_name = "Random Walk"
|
||||||
|
children = [SubResource("BTComment_qhsko"), SubResource("BTAction_lpk67"), SubResource("BTPlayAnimation_unftu"), SubResource("BTTimeLimit_baob7")]
|
||||||
|
|
||||||
|
[sub_resource type="BTProbability" id="BTProbability_sat88"]
|
||||||
|
run_chance = 0.3
|
||||||
|
children = [SubResource("BTSequence_0gdqn")]
|
||||||
|
|
||||||
[sub_resource type="BTAction" id="BTAction_kuuw2"]
|
[sub_resource type="BTAction" id="BTAction_kuuw2"]
|
||||||
script = ExtResource("2_vbh52")
|
script = ExtResource("2_vbh52")
|
||||||
target_var = "_target"
|
target_var = "target"
|
||||||
closest_side = true
|
closest_side = true
|
||||||
range_min = 400.0
|
range_min = 400
|
||||||
range_max = 1000.0
|
range_max = 1000
|
||||||
position_var = "_shoot_pos"
|
position_var = "shoot_pos"
|
||||||
|
|
||||||
[sub_resource type="BBNode" id="BBNode_kc64r"]
|
[sub_resource type="BBNode" id="BBNode_kc64r"]
|
||||||
saved_value = NodePath("AnimationPlayer")
|
saved_value = NodePath("AnimationPlayer")
|
||||||
|
@ -53,7 +90,7 @@ blend = 0.1
|
||||||
|
|
||||||
[sub_resource type="BTAction" id="BTAction_66hsk"]
|
[sub_resource type="BTAction" id="BTAction_66hsk"]
|
||||||
script = ExtResource("3_20ffh")
|
script = ExtResource("3_20ffh")
|
||||||
target_position_var = "_shoot_pos"
|
target_position_var = "shoot_pos"
|
||||||
speed_var = "speed"
|
speed_var = "speed"
|
||||||
tolerance = 50.0
|
tolerance = 50.0
|
||||||
|
|
||||||
|
@ -62,10 +99,10 @@ children = [SubResource("BTAction_66hsk")]
|
||||||
|
|
||||||
[sub_resource type="BTAction" id="BTAction_enw2m"]
|
[sub_resource type="BTAction" id="BTAction_enw2m"]
|
||||||
script = ExtResource("4_x8yor")
|
script = ExtResource("4_x8yor")
|
||||||
target_var = "_target"
|
target_var = "target"
|
||||||
|
|
||||||
[sub_resource type="BTSequence" id="BTSequence_lhg7f"]
|
[sub_resource type="BTSequence" id="BTSequence_lhg7f"]
|
||||||
custom_name = "Reposition"
|
custom_name = "Get into position"
|
||||||
children = [SubResource("BTAction_kuuw2"), SubResource("BTPlayAnimation_panch"), SubResource("BTTimeLimit_24ath"), SubResource("BTAction_enw2m")]
|
children = [SubResource("BTAction_kuuw2"), SubResource("BTPlayAnimation_panch"), SubResource("BTTimeLimit_24ath"), SubResource("BTAction_enw2m")]
|
||||||
metadata/_weight_ = 1.0
|
metadata/_weight_ = 1.0
|
||||||
|
|
||||||
|
@ -110,9 +147,16 @@ metadata/_weight_ = 1.0
|
||||||
times = 3
|
times = 3
|
||||||
children = [SubResource("BTSequence_rgbq3")]
|
children = [SubResource("BTSequence_rgbq3")]
|
||||||
|
|
||||||
|
[sub_resource type="BTSequence" id="BTSequence_h2tm0"]
|
||||||
|
custom_name = "Align and shoot"
|
||||||
|
children = [SubResource("BTSequence_lhg7f"), SubResource("BTRepeat_g08ia")]
|
||||||
|
|
||||||
|
[sub_resource type="BTSelector" id="BTSelector_1rrya"]
|
||||||
|
children = [SubResource("BTProbability_sat88"), SubResource("BTSequence_h2tm0")]
|
||||||
|
|
||||||
[sub_resource type="BTSequence" id="BTSequence_pxl2k"]
|
[sub_resource type="BTSequence" id="BTSequence_pxl2k"]
|
||||||
custom_name = "Main"
|
custom_name = "Main"
|
||||||
children = [SubResource("BTSequence_yhjh1"), SubResource("BTSequence_lhg7f"), SubResource("BTRepeat_g08ia")]
|
children = [SubResource("BTSequence_yhjh1"), SubResource("BTSelector_1rrya")]
|
||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
blackboard_plan = SubResource("BlackboardPlan_46tbn")
|
blackboard_plan = SubResource("BlackboardPlan_46tbn")
|
||||||
|
|
Loading…
Reference in New Issue