class_name EntityInteractor extends Node enum InteractorType { PLAYER_INPUT, UNDECIDED } @export var interactorType:InteractorType = InteractorType.UNDECIDED; @export var entityDirection:EntityDirection = null; @export var characterBody:CharacterBody3D = null; @export var interactRange = 0.7; @export var entity:Entity = null @export_flags_3d_physics() var interactLayers = 2; func interactWith(interactable:EntityInteractable) -> void: interactable.interact(self) pass func getRaycastInteractable() -> EntityInteractable: if !entityDirection or !characterBody: return null var rayDirection = entityDirection.getDirectionVector() var query = PhysicsRayQueryParameters3D.create( characterBody.position, characterBody.position + (rayDirection * interactRange) ) query.collide_with_bodies = true; query.collide_with_areas = true; query.collision_mask = interactLayers; query.exclude = [ characterBody ]; var result = characterBody.get_world_3d().direct_space_state.intersect_ray(query) if !result or !result.collider: return null var coll:Node3D = result.collider; var interactable:EntityInteractable = coll.find_child("EntityInteractable") return interactable func _process(delta: float) -> void: match interactorType: InteractorType.PLAYER_INPUT: _processPlayerInput() InteractorType.UNDECIDED: _processUndecided() _: assert(false, "Invalid interactor type") func _processPlayerInput() -> void: if !Input.is_action_just_pressed("interact"): return var interactable:EntityInteractable = getRaycastInteractable() if interactable: self.interactWith(interactable) func _processUndecided() -> void: pass