feat: units use navigation obstacle avoidance
This commit is contained in:
parent
f883d7d67e
commit
0e8bcf4442
|
@ -4,12 +4,15 @@
|
|||
[ext_resource type="AnimationLibrary" uid="uid://crkh5gahl2ci6" path="res://Animation/bean_characters.res" id="2_lrpu6"]
|
||||
|
||||
[sub_resource type="Goal" id="Goal_1c3rq"]
|
||||
requirements_dict = {
|
||||
"has_target": false
|
||||
}
|
||||
desired_state_dict = {
|
||||
"is_health_safe": true
|
||||
}
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_5pqvg"]
|
||||
radius = 8.42531
|
||||
radius = 15.6018
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_drlm2"]
|
||||
radius = 1.0
|
||||
|
@ -25,7 +28,7 @@ rings = 3
|
|||
[sub_resource type="BoxMesh" id="BoxMesh_p8wvo"]
|
||||
size = Vector3(0.2, 0.2, 0.5)
|
||||
|
||||
[node name="Unit" type="Unit"]
|
||||
[node name="Tank" type="Unit"]
|
||||
configure_team = 3
|
||||
collision_layer = 6
|
||||
collision_mask = 0
|
||||
|
@ -48,6 +51,10 @@ unique_name_in_owner = true
|
|||
path_desired_distance = 0.5
|
||||
target_desired_distance = 0.2
|
||||
path_height_offset = 0.5
|
||||
avoidance_enabled = true
|
||||
radius = 0.75
|
||||
time_horizon_agents = 4.0
|
||||
time_horizon_obstacles = 4.0
|
||||
|
||||
[node name="AwarenessArea" type="Area3D" parent="."]
|
||||
unique_name_in_owner = true
|
||||
|
@ -55,9 +62,10 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.1216, 3.55442)
|
|||
collision_layer = 0
|
||||
collision_mask = 2
|
||||
input_ray_pickable = false
|
||||
monitorable = false
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="AwarenessArea"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.238092)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.735143)
|
||||
shape = SubResource("SphereShape3D_5pqvg")
|
||||
|
||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
|
||||
[ext_resource type="AnimationLibrary" uid="uid://crkh5gahl2ci6" path="res://Animation/bean_characters.res" id="1_70627"]
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_drlm2"]
|
||||
radius = 1.0
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_q7mxo"]
|
||||
radius = 0.586696
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_n4q15"]
|
||||
specular_mode = 1
|
||||
albedo_color = Color(0.407843, 1, 0.447059, 1)
|
||||
roughness = 0.0
|
||||
|
||||
[sub_resource type="CapsuleMesh" id="CapsuleMesh_5r0b3"]
|
||||
material = SubResource("StandardMaterial3D_n4q15")
|
||||
|
@ -16,7 +18,7 @@ rings = 3
|
|||
[sub_resource type="BoxMesh" id="BoxMesh_p8wvo"]
|
||||
size = Vector3(0.2, 0.2, 0.5)
|
||||
|
||||
[node name="Unit" type="Unit"]
|
||||
[node name="Player" type="Unit"]
|
||||
configure_team = 1
|
||||
collision_layer = 6
|
||||
collision_mask = 0
|
||||
|
@ -36,7 +38,12 @@ unique_name_in_owner = true
|
|||
path_desired_distance = 0.2
|
||||
target_desired_distance = 0.5
|
||||
path_height_offset = 0.5
|
||||
avoidance_enabled = true
|
||||
radius = 0.75
|
||||
time_horizon_agents = 4.0
|
||||
time_horizon_obstacles = 4.0
|
||||
debug_enabled = true
|
||||
debug_path_custom_point_size = 7.0
|
||||
|
||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
||||
unique_name_in_owner = true
|
||||
|
@ -53,7 +60,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.39151, 0)
|
|||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
|
||||
shape = SubResource("SphereShape3D_drlm2")
|
||||
shape = SubResource("CapsuleShape3D_q7mxo")
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
|
||||
|
|
|
@ -151,7 +151,7 @@ mesh = SubResource("PlaneMesh_hohcb")
|
|||
skeleton = NodePath("../../../..")
|
||||
|
||||
[node name="Floor2" type="StaticBody3D" parent="WorldEnvironment/NavigationRegion3D"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -19.901, 0, 0)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -19.9976, 0, 0)
|
||||
collision_layer = 5
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="WorldEnvironment/NavigationRegion3D/Floor2"]
|
||||
|
@ -219,139 +219,139 @@ transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, -23.14
|
|||
[node name="ModernTrain6" parent="WorldEnvironment/NavigationRegion3D" instance=ExtResource("6_favl6")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -16.443, 0.268182, 3.2886)
|
||||
|
||||
[node name="Node3D" type="Node3D" parent="WorldEnvironment"]
|
||||
[node name="Tracks" type="Node3D" parent="WorldEnvironment"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 7.25984)
|
||||
|
||||
[node name="track2" parent="WorldEnvironment/Node3D" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track2" parent="WorldEnvironment/Tracks" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -8.66062, 1.8999e-07, 0)
|
||||
|
||||
[node name="track3" parent="WorldEnvironment/Node3D" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track3" parent="WorldEnvironment/Tracks" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -6.18288, 1.8999e-07, 0)
|
||||
|
||||
[node name="track4" parent="WorldEnvironment/Node3D" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track4" parent="WorldEnvironment/Tracks" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -3.69507, 1.8999e-07, 0)
|
||||
|
||||
[node name="track5" parent="WorldEnvironment/Node3D" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track5" parent="WorldEnvironment/Tracks" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -1.21011, 1.8999e-07, 0)
|
||||
|
||||
[node name="track6" parent="WorldEnvironment/Node3D" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track6" parent="WorldEnvironment/Tracks" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 1.27448, 1.8999e-07, 0)
|
||||
|
||||
[node name="track7" parent="WorldEnvironment/Node3D" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track7" parent="WorldEnvironment/Tracks" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 3.75945, 1.8999e-07, 0)
|
||||
|
||||
[node name="track8" parent="WorldEnvironment/Node3D" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track8" parent="WorldEnvironment/Tracks" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 6.24283, 1.8999e-07, 0)
|
||||
|
||||
[node name="track9" parent="WorldEnvironment/Node3D" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track9" parent="WorldEnvironment/Tracks" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 8.7278, 1.8999e-07, 0)
|
||||
|
||||
[node name="Node3D2" type="Node3D" parent="WorldEnvironment"]
|
||||
[node name="Tracks2" type="Node3D" parent="WorldEnvironment"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 3.17094)
|
||||
|
||||
[node name="track2" parent="WorldEnvironment/Node3D2" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track2" parent="WorldEnvironment/Tracks2" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -8.66062, 1.8999e-07, 0)
|
||||
|
||||
[node name="track3" parent="WorldEnvironment/Node3D2" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track3" parent="WorldEnvironment/Tracks2" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -6.18288, 1.8999e-07, 0)
|
||||
|
||||
[node name="track4" parent="WorldEnvironment/Node3D2" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track4" parent="WorldEnvironment/Tracks2" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -3.69507, 1.8999e-07, 0)
|
||||
|
||||
[node name="track5" parent="WorldEnvironment/Node3D2" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track5" parent="WorldEnvironment/Tracks2" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -1.21011, 1.8999e-07, 0)
|
||||
|
||||
[node name="track6" parent="WorldEnvironment/Node3D2" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track6" parent="WorldEnvironment/Tracks2" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 1.27448, 1.8999e-07, 0)
|
||||
|
||||
[node name="track7" parent="WorldEnvironment/Node3D2" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track7" parent="WorldEnvironment/Tracks2" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 3.75945, 1.8999e-07, 0)
|
||||
|
||||
[node name="track8" parent="WorldEnvironment/Node3D2" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track8" parent="WorldEnvironment/Tracks2" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 6.24283, 1.8999e-07, 0)
|
||||
|
||||
[node name="track9" parent="WorldEnvironment/Node3D2" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track9" parent="WorldEnvironment/Tracks2" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 8.7278, 1.8999e-07, 0)
|
||||
|
||||
[node name="Node3D3" type="Node3D" parent="WorldEnvironment"]
|
||||
[node name="Tracks3" type="Node3D" parent="WorldEnvironment"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -4.67443)
|
||||
|
||||
[node name="track2" parent="WorldEnvironment/Node3D3" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track2" parent="WorldEnvironment/Tracks3" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -8.66062, 1.8999e-07, 0)
|
||||
|
||||
[node name="track3" parent="WorldEnvironment/Node3D3" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track3" parent="WorldEnvironment/Tracks3" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -6.18288, 1.8999e-07, 0)
|
||||
|
||||
[node name="track4" parent="WorldEnvironment/Node3D3" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track4" parent="WorldEnvironment/Tracks3" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -3.69507, 1.8999e-07, 0)
|
||||
|
||||
[node name="track5" parent="WorldEnvironment/Node3D3" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track5" parent="WorldEnvironment/Tracks3" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -1.21011, 1.8999e-07, 0)
|
||||
|
||||
[node name="track6" parent="WorldEnvironment/Node3D3" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track6" parent="WorldEnvironment/Tracks3" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 1.27448, 1.8999e-07, 0)
|
||||
|
||||
[node name="track7" parent="WorldEnvironment/Node3D3" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track7" parent="WorldEnvironment/Tracks3" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 3.75945, 1.8999e-07, 0)
|
||||
|
||||
[node name="track8" parent="WorldEnvironment/Node3D3" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track8" parent="WorldEnvironment/Tracks3" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 6.24283, 1.8999e-07, 0)
|
||||
|
||||
[node name="track9" parent="WorldEnvironment/Node3D3" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track9" parent="WorldEnvironment/Tracks3" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 8.7278, 1.8999e-07, 0)
|
||||
|
||||
[node name="Node3D4" type="Node3D" parent="WorldEnvironment"]
|
||||
[node name="Tracks4" type="Node3D" parent="WorldEnvironment"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -19.8802, 0, 7.25984)
|
||||
|
||||
[node name="track2" parent="WorldEnvironment/Node3D4" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track2" parent="WorldEnvironment/Tracks4" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -8.66062, 1.8999e-07, 0)
|
||||
|
||||
[node name="track3" parent="WorldEnvironment/Node3D4" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track3" parent="WorldEnvironment/Tracks4" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -6.18288, 1.8999e-07, 0)
|
||||
|
||||
[node name="track4" parent="WorldEnvironment/Node3D4" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track4" parent="WorldEnvironment/Tracks4" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -3.69507, 1.8999e-07, 0)
|
||||
|
||||
[node name="track5" parent="WorldEnvironment/Node3D4" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track5" parent="WorldEnvironment/Tracks4" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -1.21011, 1.8999e-07, 0)
|
||||
|
||||
[node name="track6" parent="WorldEnvironment/Node3D4" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track6" parent="WorldEnvironment/Tracks4" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 1.27448, 1.8999e-07, 0)
|
||||
|
||||
[node name="track7" parent="WorldEnvironment/Node3D4" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track7" parent="WorldEnvironment/Tracks4" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 3.75945, 1.8999e-07, 0)
|
||||
|
||||
[node name="track8" parent="WorldEnvironment/Node3D4" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track8" parent="WorldEnvironment/Tracks4" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 6.24283, 1.8999e-07, 0)
|
||||
|
||||
[node name="track9" parent="WorldEnvironment/Node3D4" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track9" parent="WorldEnvironment/Tracks4" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 8.7278, 1.8999e-07, 0)
|
||||
|
||||
[node name="Node3D5" type="Node3D" parent="WorldEnvironment"]
|
||||
[node name="Tracks5" type="Node3D" parent="WorldEnvironment"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -19.8802, 0, 3.17094)
|
||||
|
||||
[node name="track2" parent="WorldEnvironment/Node3D5" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track2" parent="WorldEnvironment/Tracks5" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -8.66062, 1.8999e-07, 0)
|
||||
|
||||
[node name="track3" parent="WorldEnvironment/Node3D5" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track3" parent="WorldEnvironment/Tracks5" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -6.18288, 1.8999e-07, 0)
|
||||
|
||||
[node name="track4" parent="WorldEnvironment/Node3D5" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track4" parent="WorldEnvironment/Tracks5" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -3.69507, 1.8999e-07, 0)
|
||||
|
||||
[node name="track5" parent="WorldEnvironment/Node3D5" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track5" parent="WorldEnvironment/Tracks5" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -1.21011, 1.8999e-07, 0)
|
||||
|
||||
[node name="track6" parent="WorldEnvironment/Node3D5" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track6" parent="WorldEnvironment/Tracks5" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 1.27448, 1.8999e-07, 0)
|
||||
|
||||
[node name="track7" parent="WorldEnvironment/Node3D5" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track7" parent="WorldEnvironment/Tracks5" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 3.75945, 1.8999e-07, 0)
|
||||
|
||||
[node name="track8" parent="WorldEnvironment/Node3D5" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track8" parent="WorldEnvironment/Tracks5" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 6.24283, 1.8999e-07, 0)
|
||||
|
||||
[node name="track9" parent="WorldEnvironment/Node3D5" instance=ExtResource("7_8fuqb")]
|
||||
[node name="track9" parent="WorldEnvironment/Tracks5" instance=ExtResource("7_8fuqb")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 8.7278, 1.8999e-07, 0)
|
||||
|
||||
[node name="Player" parent="." instance=ExtResource("3_wl7wm")]
|
||||
|
@ -360,9 +360,6 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7.16025, 1.8999e-07, -2.07711
|
|||
[node name="Player2" parent="." instance=ExtResource("3_wl7wm")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.28022, 1.8999e-07, -4.279)
|
||||
|
||||
[node name="Tank" parent="." instance=ExtResource("4_0o33v")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6.70922, -7.63685e-07, 3.72251)
|
||||
|
||||
[node name="Tank2" parent="." instance=ExtResource("4_0o33v")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.4143, -7.63685e-07, 5.91707)
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "enemy_world_state.hpp"
|
||||
#include "entity_health.hpp"
|
||||
#include "godot_cpp/variant/utility_functions.hpp"
|
||||
#include "unit.hpp"
|
||||
#include "goap/goal.hpp"
|
||||
#include "utils/godot_macros.hpp"
|
||||
|
@ -23,38 +24,19 @@ void EnemyWorldState::_ready() { GDGAMEONLY();
|
|||
}
|
||||
|
||||
void EnemyWorldState::on_awareness_entered(gd::Node3D *node) {
|
||||
Unit *unit{gd::Object::cast_to<Unit>(node)};
|
||||
if(unit == nullptr)
|
||||
return;
|
||||
if(unit == this->parent_unit)
|
||||
return;
|
||||
if(unit->get_entity_health()->get_is_dead())
|
||||
return;
|
||||
unit->get_entity_health()->connect("death", this->aware_unit_death.bind(unit));
|
||||
this->known_enemies.push_back(unit);
|
||||
this->try_set_target(this->select_target_from_known());
|
||||
if(Unit *unit{gd::Object::cast_to<Unit>(node)}) {
|
||||
gd::UtilityFunctions::print("!!! ", this->get_path(), ": ", node->get_path(), " entered awareness");
|
||||
this->add_aware_unit(unit);
|
||||
}
|
||||
}
|
||||
|
||||
void EnemyWorldState::on_awareness_exited(gd::Node3D *node) {
|
||||
Unit *unit{gd::Object::cast_to<Unit>(node)};
|
||||
if(unit == nullptr)
|
||||
return;
|
||||
if(this->known_enemies.has(unit)) {
|
||||
unit->get_entity_health()->disconnect("death", this->aware_unit_death.bind(unit));
|
||||
this->known_enemies.erase(unit);
|
||||
}
|
||||
if(unit == this->target_node) {
|
||||
this->select_and_set_target();
|
||||
}
|
||||
this->remove_aware_unit(unit);
|
||||
}
|
||||
|
||||
void EnemyWorldState::on_damaged(int remaining, int delta, Unit *source) {
|
||||
if(!this->known_enemies.has(source)) {
|
||||
source->get_entity_health()->connect("death", this->aware_unit_death.bind(source));
|
||||
this->known_enemies.push_back(source);
|
||||
}
|
||||
if(!this->parent_unit->has_plan())
|
||||
this->try_set_target(this->select_target_from_known());
|
||||
this->add_aware_unit(source);
|
||||
}
|
||||
|
||||
Unit *EnemyWorldState::select_target_from_known_with_priority(float *out_priority) {
|
||||
|
@ -75,6 +57,37 @@ Unit *EnemyWorldState::select_target_from_known() {
|
|||
return this->select_target_from_known_with_priority(&dummy);
|
||||
}
|
||||
|
||||
void EnemyWorldState::add_aware_unit(Unit *unit) {
|
||||
if(unit == nullptr)
|
||||
return;
|
||||
if(unit == this->parent_unit)
|
||||
return;
|
||||
if(this->known_enemies.has(unit))
|
||||
return;
|
||||
if(unit->get_entity_health()->get_is_dead())
|
||||
return;
|
||||
if(!this->get_is_unit_enemy(unit))
|
||||
return;
|
||||
unit->get_entity_health()->connect("death", this->aware_unit_death.bind(unit));
|
||||
this->known_enemies.insert(0, unit);
|
||||
if(!this->parent_unit->has_plan())
|
||||
this->try_set_target(this->select_target_from_known());
|
||||
else
|
||||
gd::UtilityFunctions::print("!!! ", this->get_path(), " not replanning because a plan is already in motion");
|
||||
gd::UtilityFunctions::print("!!! ", this->get_path(), " found ", unit->get_path());
|
||||
}
|
||||
|
||||
void EnemyWorldState::remove_aware_unit(Unit *unit) {
|
||||
if(unit == nullptr)
|
||||
return;
|
||||
if(!this->known_enemies.has(unit))
|
||||
return;
|
||||
unit->get_entity_health()->disconnect("death", this->aware_unit_death.bind(unit));
|
||||
this->known_enemies.erase(unit);
|
||||
if(unit == this->target_node)
|
||||
this->select_and_set_target();
|
||||
}
|
||||
|
||||
void EnemyWorldState::on_aware_unit_death(Unit *_, Unit *dead_entity) {
|
||||
this->on_awareness_exited(dead_entity);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ public:
|
|||
//! Shorthand for select_target_from_known_with_priority(nullptr)
|
||||
Unit *select_target_from_known();
|
||||
private:
|
||||
void add_aware_unit(Unit *unit);
|
||||
void remove_aware_unit(Unit *unit);
|
||||
void select_and_set_target();
|
||||
void on_aware_unit_death(Unit *_, Unit *dead_entity);
|
||||
float calculate_priority(Unit *target);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#include "planner.hpp"
|
||||
#include "action_db.hpp"
|
||||
#include "godot_cpp/templates/hashfuncs.hpp"
|
||||
#include "utils/godot_macros.hpp"
|
||||
#include <cstdint>
|
||||
#include <godot_cpp/classes/engine.hpp>
|
||||
#include <godot_cpp/classes/global_constants.hpp>
|
||||
#include <godot_cpp/templates/hashfuncs.hpp>
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
|
||||
namespace goap {
|
||||
|
@ -85,8 +85,8 @@ void Planner::_bind_methods() {
|
|||
GDPROPERTY_HINTED(actions_inspector, gd::Variant::ARRAY, gd::PROPERTY_HINT_ARRAY_TYPE, ActionDB::get_array_hint());
|
||||
}
|
||||
|
||||
void Planner::_enter_tree() { GDGAMEONLY();
|
||||
this->world_state = this->get_node<ActorWorldState>("../ActorWorldState");
|
||||
void Planner::_ready() { GDGAMEONLY();
|
||||
this->world_state = this->get_node<ActorWorldState>("%ActorWorldState");
|
||||
}
|
||||
|
||||
Plan Planner::plan_for_goal(gd::Ref<Goal> goal) {
|
||||
|
|
|
@ -53,7 +53,7 @@ class Planner : public gd::Node {
|
|||
GDCLASS(Planner, gd::Node);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
virtual void _enter_tree() override;
|
||||
virtual void _ready() override;
|
||||
|
||||
//! Compute a plan to achieve the passed `Goal`.
|
||||
Plan plan_for_goal(gd::Ref<Goal> goal);
|
||||
|
|
|
@ -21,11 +21,11 @@
|
|||
#include <godot_cpp/core/defs.hpp>
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
using namespace godot;
|
||||
namespace gd = godot;
|
||||
|
||||
void initialize_gdextension_types(ModuleInitializationLevel p_level)
|
||||
void initialize_gdextension_types(gd::ModuleInitializationLevel p_level)
|
||||
{
|
||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
if (p_level != gd::MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
return;
|
||||
}
|
||||
utils::godot_cpp_utils_register_types();
|
||||
|
@ -40,24 +40,24 @@ void initialize_gdextension_types(ModuleInitializationLevel p_level)
|
|||
goap::ActionDB::register_action<TankSelfHeal>();
|
||||
goap::ActionDB::register_action<TakeCover>();
|
||||
|
||||
ClassDB::register_class<goap::ActorWorldState>();
|
||||
ClassDB::register_class<goap::Goal>();
|
||||
ClassDB::register_class<goap::Planner>();
|
||||
ClassDB::register_class<goap::State>();
|
||||
gd::ClassDB::register_class<goap::ActorWorldState>();
|
||||
gd::ClassDB::register_class<goap::Goal>();
|
||||
gd::ClassDB::register_class<goap::Planner>();
|
||||
gd::ClassDB::register_class<goap::State>();
|
||||
|
||||
ClassDB::register_class<MoveTo>();
|
||||
ClassDB::register_class<Animate>();
|
||||
ClassDB::register_class<Activate>();
|
||||
gd::ClassDB::register_class<MoveTo>();
|
||||
gd::ClassDB::register_class<Animate>();
|
||||
gd::ClassDB::register_class<Activate>();
|
||||
|
||||
ClassDB::register_class<UnitWorldState>();
|
||||
ClassDB::register_class<EnemyWorldState>();
|
||||
ClassDB::register_class<GoalMarker>();
|
||||
ClassDB::register_class<Unit>();
|
||||
ClassDB::register_class<RTSGameMode>();
|
||||
ClassDB::register_class<RTSPlayer>();
|
||||
ClassDB::register_class<EntityHealth>();
|
||||
ClassDB::register_class<NavMarker>();
|
||||
ClassDB::register_class<NavRoom>();
|
||||
gd::ClassDB::register_class<UnitWorldState>();
|
||||
gd::ClassDB::register_class<EnemyWorldState>();
|
||||
gd::ClassDB::register_class<GoalMarker>();
|
||||
gd::ClassDB::register_class<Unit>();
|
||||
gd::ClassDB::register_class<RTSGameMode>();
|
||||
gd::ClassDB::register_class<RTSPlayer>();
|
||||
gd::ClassDB::register_class<EntityHealth>();
|
||||
gd::ClassDB::register_class<NavMarker>();
|
||||
gd::ClassDB::register_class<NavRoom>();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
|
@ -65,9 +65,9 @@ extern "C"
|
|||
// Initialization
|
||||
GDExtensionBool GDE_EXPORT metro_rts_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization)
|
||||
{
|
||||
GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
|
||||
gd::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
|
||||
init_obj.register_initializer(initialize_gdextension_types);
|
||||
init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);
|
||||
init_obj.set_minimum_library_initialization_level(gd::MODULE_INITIALIZATION_LEVEL_SCENE);
|
||||
|
||||
return init_obj.init();
|
||||
}
|
||||
|
|
|
@ -7,37 +7,39 @@
|
|||
void MoveTo::_bind_methods() {}
|
||||
|
||||
void MoveTo::_ready() {
|
||||
this->parent_node3d = Object::cast_to<gd::Node3D>(this->get_parent());
|
||||
this->parent_unit = Object::cast_to<Unit>(this->get_parent());
|
||||
this->agent = this->get_node<gd::NavigationAgent3D>("../NavigationAgent3D");
|
||||
if(this->target_node == nullptr) {
|
||||
this->state_ended();
|
||||
gd::UtilityFunctions::push_warning("failed to start MoveTo state due to missing target");
|
||||
return;
|
||||
}
|
||||
this->agent->set_target_position(this->target_node->get_global_position());
|
||||
this->agent->connect("velocity_computed", this->nav_velocity_computed);
|
||||
this->calculate_path();
|
||||
gd::UtilityFunctions::print(this->parent_node3d->get_path(), " MoveTo ", this->target_node->get_path());
|
||||
gd::UtilityFunctions::print(this->parent_unit->get_path(), " MoveTo ", this->target_node->get_path());
|
||||
}
|
||||
|
||||
void MoveTo::_end_state() {
|
||||
this->agent->set_target_position(this->parent_node3d->get_global_position());
|
||||
this->agent->disconnect("velocity_computed", this->nav_velocity_computed);
|
||||
this->agent->set_target_position(this->parent_unit->get_global_position());
|
||||
}
|
||||
|
||||
void MoveTo::_process(double delta_time) {
|
||||
gd::Vector3 const pos = this->parent_node3d->get_global_position();
|
||||
gd::Vector3 const pos = this->parent_unit->get_global_position();
|
||||
gd::Vector3 const target = this->agent->get_next_path_position();
|
||||
gd::Vector3 const direction = (target - pos).normalized();
|
||||
this->parent_node3d->set_global_position(pos + direction * delta_time);
|
||||
this->parent_node3d->look_at(pos - gd::Vector3{direction.x, 0.f, direction.z});
|
||||
|
||||
this->agent->set_velocity(direction);
|
||||
bool const navigation_finished{this->agent->is_navigation_finished()};
|
||||
if(this->is_action_done_interrupt() || navigation_finished)
|
||||
this->state_ended();
|
||||
|
||||
if((utils::time_seconds() - this->last_repath) > this->get_repath_interval())
|
||||
this->calculate_path();
|
||||
}
|
||||
|
||||
void MoveTo::_physics_process(double delta) {
|
||||
this->parent_unit->move_and_slide();
|
||||
}
|
||||
|
||||
void MoveTo::calculate_path() {
|
||||
gd::Vector3 const target_pos{this->target_node->get_global_position()};
|
||||
this->agent->set_target_position(target_pos);
|
||||
|
@ -45,6 +47,14 @@ void MoveTo::calculate_path() {
|
|||
this->target_position_at_last = target_pos;
|
||||
}
|
||||
|
||||
void MoveTo::on_velocity_computed(gd::Vector3 vel) {
|
||||
gd::Vector3 const pos{this->parent_unit->get_global_position()};
|
||||
gd::Vector3 const target_dir{(this->agent->get_next_path_position() - pos).normalized()};
|
||||
// recalculate if avoidance is causing the motion to lock up
|
||||
if(target_dir.dot(vel.normalized()) < 0.25f)
|
||||
this->calculate_path();
|
||||
}
|
||||
|
||||
float MoveTo::target_delta_position() const {
|
||||
return this->target_position_at_last
|
||||
.distance_to(this->target_node->get_global_position());
|
||||
|
@ -52,7 +62,7 @@ float MoveTo::target_delta_position() const {
|
|||
|
||||
float MoveTo::distance_to_target() const {
|
||||
return this->target_position_at_last
|
||||
.distance_to(this->parent_node3d->get_global_position());
|
||||
.distance_to(this->parent_unit->get_global_position());
|
||||
}
|
||||
|
||||
double MoveTo::get_repath_interval() const {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef RTS_STATES_HPP
|
||||
#define RTS_STATES_HPP
|
||||
|
||||
#include "unit.hpp"
|
||||
#include "goap/state.hpp"
|
||||
#include <godot_cpp/classes/animation_player.hpp>
|
||||
#include <godot_cpp/classes/navigation_agent3d.hpp>
|
||||
|
@ -14,14 +15,17 @@ public:
|
|||
virtual void _ready() override;
|
||||
virtual void _end_state() override;
|
||||
virtual void _process(double delta_time) override;
|
||||
virtual void _physics_process(double delta_time) override;
|
||||
void calculate_path();
|
||||
void on_velocity_computed(gd::Vector3 vel);
|
||||
float target_delta_position() const;
|
||||
float distance_to_target() const;
|
||||
double get_repath_interval() const;
|
||||
public:
|
||||
gd::Node3D *target_node{nullptr};
|
||||
private:
|
||||
gd::Node3D *parent_node3d{nullptr};
|
||||
gd::Callable nav_velocity_computed{callable_mp(this, &MoveTo::on_velocity_computed)};
|
||||
Unit *parent_unit{nullptr};
|
||||
gd::NavigationAgent3D *agent{nullptr};
|
||||
gd::Vector3 target_position_at_last{};
|
||||
double last_repath{0.0};
|
||||
|
|
33
src/unit.cpp
33
src/unit.cpp
|
@ -2,6 +2,7 @@
|
|||
#include "entity_health.hpp"
|
||||
#include "goap/action.hpp"
|
||||
#include "goap/goal.hpp"
|
||||
#include "rts_states.hpp"
|
||||
#include "utils/godot_macros.hpp"
|
||||
#include <godot_cpp/classes/navigation_agent3d.hpp>
|
||||
#include <godot_cpp/variant/callable_method_pointer.hpp>
|
||||
|
@ -18,6 +19,7 @@ void Unit::_bind_methods() {
|
|||
|
||||
void Unit::_enter_tree() { GDGAMEONLY();
|
||||
this->agent = this->get_node<gd::NavigationAgent3D>("%NavigationAgent3D");
|
||||
this->agent->connect("velocity_computed", callable_mp(this, &Unit::on_velocity_computed));
|
||||
this->planner = this->get_node<goap::Planner>("%Planner");
|
||||
this->world_state = this->get_node<UnitWorldState>("%ActorWorldState");
|
||||
this->world_state->connect("attention_changed", callable_mp(this, &Unit::stop_plan));
|
||||
|
@ -111,16 +113,15 @@ EntityHealth *Unit::get_entity_health() {
|
|||
return this->health;
|
||||
}
|
||||
|
||||
void Unit::set_goal_and_plan(gd::Ref<goap::Goal> goal) {
|
||||
this->current_goal = goal;
|
||||
if(goal.is_null()) {
|
||||
this->current_plan.clear();
|
||||
} else {
|
||||
this->current_plan = this->planner->plan_for_goal(goal);
|
||||
if(this->current_plan.is_empty()) {
|
||||
this->current_goal.unref();
|
||||
}
|
||||
}
|
||||
void Unit::on_velocity_computed(gd::Vector3 vel) {
|
||||
gd::Vector3 const pos{this->get_global_position()};
|
||||
gd::Vector3 const target_dir{(this->agent->get_next_path_position() - pos).normalized()};
|
||||
if(vel.x == 0 && vel.z == 0)
|
||||
return;
|
||||
if(gd::Object::cast_to<MoveTo>(this->state) == nullptr)
|
||||
return;
|
||||
this->set_velocity(vel);
|
||||
this->look_at(pos - gd::Vector3{vel.x, 0.f, vel.z});
|
||||
}
|
||||
|
||||
void Unit::destroy_state() {
|
||||
|
@ -166,3 +167,15 @@ void Unit::next_action() {
|
|||
void Unit::replan_goal() {
|
||||
this->begin_goal(this->current_goal);
|
||||
}
|
||||
|
||||
void Unit::set_goal_and_plan(gd::Ref<goap::Goal> goal) {
|
||||
this->current_goal = goal;
|
||||
if(goal.is_null()) {
|
||||
this->current_plan.clear();
|
||||
} else {
|
||||
this->current_plan = this->planner->plan_for_goal(goal);
|
||||
if(this->current_plan.is_empty()) {
|
||||
this->current_goal.unref();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,11 +44,12 @@ public:
|
|||
bool has_plan() const;
|
||||
EntityHealth *get_entity_health();
|
||||
private:
|
||||
void set_goal_and_plan(gd::Ref<goap::Goal> goal);
|
||||
void on_velocity_computed(gd::Vector3 vel);
|
||||
void destroy_state();
|
||||
void state_finished();
|
||||
void next_action();
|
||||
void replan_goal();
|
||||
void set_goal_and_plan(gd::Ref<goap::Goal> goal);
|
||||
private:
|
||||
gd::Callable on_state_finished{callable_mp(this, &Unit::state_finished)};
|
||||
gd::Callable on_plan_failed{callable_mp(this, &Unit::replan_goal)};
|
||||
|
|
|
@ -14,6 +14,7 @@ void UnitWorldState::_bind_methods() {
|
|||
GDFUNCTION(get_can_see_target);
|
||||
GDFUNCTION(get_is_target_dead);
|
||||
GDFUNCTION(get_is_at_target);
|
||||
GDFUNCTION(get_has_target);
|
||||
GDFUNCTION(get_target_node);
|
||||
GDFUNCTION(get_is_target_enemy);
|
||||
GDFUNCTION(get_is_in_melee_range);
|
||||
|
@ -24,6 +25,7 @@ void UnitWorldState::_bind_methods() {
|
|||
|
||||
void UnitWorldState::_enter_tree() { GDGAMEONLY();
|
||||
this->parent_unit = gd::Object::cast_to<Unit>(this->get_parent());
|
||||
gd::UtilityFunctions::print("!!! ", this->get_path(), ": is part of ", this->parent_unit->get_path());
|
||||
this->agent = this->get_node<gd::NavigationAgent3D>("%NavigationAgent3D");
|
||||
this->eye_location = this->get_node<gd::Node3D>("%Eyes");
|
||||
this->health = this->get_node<EntityHealth>("%EntityHealth");
|
||||
|
@ -61,8 +63,12 @@ bool UnitWorldState::get_is_at_target() const {
|
|||
return (target - current).length_squared() <= min_dist * min_dist;
|
||||
}
|
||||
|
||||
bool UnitWorldState::get_has_target() const {
|
||||
return this->target_node != nullptr;
|
||||
}
|
||||
|
||||
bool UnitWorldState::get_is_target_dead() const {
|
||||
if(EntityHealth *health{this->target_node->get_node<EntityHealth>("EntityHealth")})
|
||||
if(EntityHealth *health{this->target_node->get_node<EntityHealth>("%EntityHealth")})
|
||||
return health->get_injury_current() <= 0.f;
|
||||
return false;
|
||||
}
|
||||
|
@ -73,6 +79,10 @@ bool UnitWorldState::get_is_target_unit() const {
|
|||
|
||||
bool UnitWorldState::get_is_target_enemy() const {
|
||||
Unit *unit{gd::Object::cast_to<Unit>(this->target_node)};
|
||||
return unit != nullptr && this->get_is_unit_enemy(unit);
|
||||
}
|
||||
|
||||
bool UnitWorldState::get_is_unit_enemy(Unit *unit) const {
|
||||
return unit != nullptr
|
||||
&& unit->get_team() != UnitTeam::Neutral
|
||||
&& unit->get_team() != this->parent_unit->get_team();
|
||||
|
|
|
@ -15,9 +15,11 @@ public:
|
|||
virtual void _enter_tree() override;
|
||||
bool get_can_see_target() const;
|
||||
bool get_is_at_target() const;
|
||||
bool get_has_target() const;
|
||||
bool get_is_target_dead() const;
|
||||
bool get_is_target_unit() const;
|
||||
bool get_is_target_enemy() const;
|
||||
bool get_is_unit_enemy(Unit *unit) const;
|
||||
bool get_is_in_melee_range() const;
|
||||
bool get_is_health_safe() const;
|
||||
gd::Vector3 get_parent_global_position() const;
|
||||
|
|
Loading…
Reference in a new issue