add base system
This commit is contained in:
48
core/ai/ai_base/ai_base.gd
Normal file
48
core/ai/ai_base/ai_base.gd
Normal file
@@ -0,0 +1,48 @@
|
||||
extends CharacterBody3D
|
||||
|
||||
class_name AIBase
|
||||
|
||||
@export var speed: float = 4.0
|
||||
@export var enable_state_machine: bool = true:
|
||||
set(value):
|
||||
enable_state_machine = value
|
||||
toggle_enable_state_machine()
|
||||
|
||||
|
||||
@onready var patrol_radius_shape: CollisionShape3D = $PatrolRadiusShape
|
||||
@onready var nav_agent: NavigationAgent3D = $NavigationAgent3D
|
||||
@onready var state_machine: StateMachine = $StateMachine
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
randomize()
|
||||
toggle_enable_state_machine()
|
||||
|
||||
func toggle_enable_state_machine() -> void:
|
||||
$StateMachine.enable = enable_state_machine
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if !enable_state_machine:
|
||||
return
|
||||
|
||||
state_machine.physics_process(delta)
|
||||
|
||||
if nav_agent.is_navigation_finished():
|
||||
velocity = Vector3.ZERO
|
||||
move_and_slide()
|
||||
return
|
||||
|
||||
var next_point = nav_agent.get_next_path_position()
|
||||
var direction = global_position.direction_to(next_point)
|
||||
|
||||
velocity.x = direction.x * speed
|
||||
velocity.z = direction.z * speed
|
||||
|
||||
move_and_slide()
|
||||
|
||||
func navigate_to_random_point() -> void:
|
||||
var nav_map_rid = get_world_3d().get_navigation_map()
|
||||
var patrol_radius = patrol_radius_shape.shape.radius
|
||||
var target_point_in_space = global_position + Vector3(randf_range(-1, 1), 0, randf_range(-1, 1)).normalized() * randf_range(0, patrol_radius)
|
||||
var closest_valid_point = NavigationServer3D.map_get_closest_point(nav_map_rid, target_point_in_space)
|
||||
nav_agent.target_position = closest_valid_point
|
||||
1
core/ai/ai_base/ai_base.gd.uid
Normal file
1
core/ai/ai_base/ai_base.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b30p1yqojbbbk
|
||||
41
core/ai/ai_base/ai_base.tscn
Normal file
41
core/ai/ai_base/ai_base.tscn
Normal file
@@ -0,0 +1,41 @@
|
||||
[gd_scene format=3 uid="uid://clx701xdwelgx"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://b30p1yqojbbbk" path="res://core/ai/ai_base/ai_base.gd" id="1_4d1nn"]
|
||||
[ext_resource type="Script" uid="uid://ps3vlu2qvmop" path="res://core/ai/ai_base/state_machine.gd" id="2_q1hg3"]
|
||||
[ext_resource type="Script" uid="uid://nga8qx56iwgu" path="res://core/ai/ai_base/idle_state.gd" id="3_26faq"]
|
||||
[ext_resource type="Script" uid="uid://bngfthvt04ivv" path="res://core/ai/ai_base/patrol_state.gd" id="4_lim44"]
|
||||
|
||||
[sub_resource type="CapsuleMesh" id="CapsuleMesh_mh3lg"]
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_mh3lg"]
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_lim44"]
|
||||
radius = 20.0
|
||||
|
||||
[node name="AiBase" type="CharacterBody3D" unique_id=1228675528]
|
||||
script = ExtResource("1_4d1nn")
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="." unique_id=214482161]
|
||||
mesh = SubResource("CapsuleMesh_mh3lg")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=92811823]
|
||||
shape = SubResource("CapsuleShape3D_mh3lg")
|
||||
|
||||
[node name="NavigationAgent3D" type="NavigationAgent3D" parent="." unique_id=1370024449]
|
||||
|
||||
[node name="StateMachine" type="Node" parent="." unique_id=1286404264 node_paths=PackedStringArray("initial_state")]
|
||||
script = ExtResource("2_q1hg3")
|
||||
initial_state = NodePath("IdleState")
|
||||
|
||||
[node name="IdleState" type="Node" parent="StateMachine" unique_id=763668255]
|
||||
script = ExtResource("3_26faq")
|
||||
state_id = "idle"
|
||||
|
||||
[node name="PatrolState" type="Node" parent="StateMachine" unique_id=2054606629]
|
||||
script = ExtResource("4_lim44")
|
||||
state_id = "patrol"
|
||||
|
||||
[node name="PatrolRadiusShape" type="CollisionShape3D" parent="." unique_id=1379515938]
|
||||
shape = SubResource("SphereShape3D_lim44")
|
||||
disabled = true
|
||||
debug_color = Color(1, 1, 0, 1)
|
||||
24
core/ai/ai_base/idle_state.gd
Normal file
24
core/ai/ai_base/idle_state.gd
Normal file
@@ -0,0 +1,24 @@
|
||||
extends State
|
||||
|
||||
@export var wait_time: float = 3.0
|
||||
|
||||
var runtime_timer: Timer
|
||||
|
||||
func enter() -> void:
|
||||
runtime_timer = Timer.new()
|
||||
runtime_timer.name = "IdleTimer"
|
||||
add_child(runtime_timer)
|
||||
runtime_timer.one_shot = true
|
||||
runtime_timer.timeout.connect(_on_timer_timeout)
|
||||
runtime_timer.start(wait_time)
|
||||
|
||||
func exit() -> void:
|
||||
if runtime_timer:
|
||||
if runtime_timer.is_connected("timeout", _on_timer_timeout):
|
||||
runtime_timer.timeout.disconnect(_on_timer_timeout)
|
||||
|
||||
runtime_timer.queue_free()
|
||||
runtime_timer = null
|
||||
|
||||
func _on_timer_timeout() -> void:
|
||||
transitioned.emit(self, "patrol")
|
||||
1
core/ai/ai_base/idle_state.gd.uid
Normal file
1
core/ai/ai_base/idle_state.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://nga8qx56iwgu
|
||||
10
core/ai/ai_base/patrol_state.gd
Normal file
10
core/ai/ai_base/patrol_state.gd
Normal file
@@ -0,0 +1,10 @@
|
||||
extends State
|
||||
|
||||
@onready var agent: AIBase = owner
|
||||
|
||||
func enter() -> void:
|
||||
agent.navigate_to_random_point()
|
||||
|
||||
func update(_delta) -> void:
|
||||
if agent.nav_agent.is_navigation_finished():
|
||||
transitioned.emit(self, "idle")
|
||||
1
core/ai/ai_base/patrol_state.gd.uid
Normal file
1
core/ai/ai_base/patrol_state.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bngfthvt04ivv
|
||||
19
core/ai/ai_base/state.gd
Normal file
19
core/ai/ai_base/state.gd
Normal file
@@ -0,0 +1,19 @@
|
||||
extends Node
|
||||
|
||||
class_name State
|
||||
|
||||
@export var state_id: String = ""
|
||||
|
||||
signal transitioned(state, new_state_name)
|
||||
|
||||
func enter() -> void:
|
||||
pass
|
||||
|
||||
func exit() -> void:
|
||||
pass
|
||||
|
||||
func update(_delta) -> void:
|
||||
pass
|
||||
|
||||
func physics_update(_delta) -> void:
|
||||
pass
|
||||
1
core/ai/ai_base/state.gd.uid
Normal file
1
core/ai/ai_base/state.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dpso7abi5ftyw
|
||||
48
core/ai/ai_base/state_machine.gd
Normal file
48
core/ai/ai_base/state_machine.gd
Normal file
@@ -0,0 +1,48 @@
|
||||
extends Node
|
||||
|
||||
class_name StateMachine
|
||||
|
||||
@export var initial_state: State
|
||||
|
||||
var current_state: State
|
||||
var states: Dictionary = {}
|
||||
var enable: bool = true:
|
||||
set(value):
|
||||
enable = value
|
||||
toggle_enable()
|
||||
|
||||
func toggle_enable() -> void:
|
||||
if !enable:
|
||||
return
|
||||
|
||||
if !states.is_empty():
|
||||
return
|
||||
|
||||
for state in get_children():
|
||||
if state is State:
|
||||
states[state.state_id] = state
|
||||
state.transitioned.connect(_on_state_transition)
|
||||
|
||||
if initial_state:
|
||||
current_state = initial_state
|
||||
current_state.enter()
|
||||
|
||||
func physics_process(delta) -> void:
|
||||
if current_state and enable:
|
||||
current_state.update(delta)
|
||||
|
||||
func _on_state_transition(state: State, new_state_id: String) -> void:
|
||||
if state != current_state:
|
||||
return
|
||||
|
||||
var new_state = states.get(new_state_id)
|
||||
if not new_state:
|
||||
return
|
||||
|
||||
if current_state:
|
||||
current_state.exit()
|
||||
|
||||
current_state = new_state
|
||||
current_state.enter()
|
||||
|
||||
print("Transizione a: ", current_state.state_id)
|
||||
1
core/ai/ai_base/state_machine.gd.uid
Normal file
1
core/ai/ai_base/state_machine.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ps3vlu2qvmop
|
||||
Reference in New Issue
Block a user