Help with raycast and interactions

Godot Version

4.4.1 stable

Question

I’m trying to use StateCharts as a way to create two different states in an object I want the player to interact with. I have the states working fine but I need to be able to tell what my raycast is looking at. And then be able to press an interact button to then have the object do something. Hard to explain but I will try to show examples below.


This is my objects scene tree.

I have an interaction component that shows UI when put on any object in Godot.

class_name InteractionComponent extends Node

@export var mesh : MeshInstance3D
@export var context : String
@export var override_icon : bool
@export var new_icon : Texture2D

var parent 
var highlight_material = preload("res://materials/interactable_highlight.tres")

func _ready() -> void:
	parent = get_parent()
	connect_parent()
	set_default_mesh()

func _process(delta: float) -> void:
	pass

func in_range() -> void:
	mesh.material_overlay = highlight_material
	MessageBus.interaction_focused.emit(context, new_icon, override_icon)

func not_in_range() -> void:
	mesh.material_overlay = null
	MessageBus.interaction_unfocused.emit()

func on_interact() -> void:
	print(parent.name)

func connect_parent() -> void:
	parent.add_user_signal("focused")
	parent.add_user_signal("unfocused")
	parent.add_user_signal("interacted")
	parent.connect("focused", Callable(self, "in_range"))
	parent.connect("unfocused", Callable(self, "not_in_range"))
	parent.connect("interacted", Callable(self, "on_interact"))

func set_default_mesh() -> void:
	if mesh:
		pass
	else:
		for i in parent.get_children():
			if i is MeshInstance3D:
				mesh = i

Code for the InteractionComponent.

This is my raycast code.

func interact_cast() -> void:
	var camera = Global.player.CAMERA_CONTROLLER
	var space_state = camera.get_world_3d().direct_space_state
	var screen_center = get_viewport().size / 2
	var origin = camera.project_ray_origin(screen_center)
	var end = origin + camera.project_ray_normal(screen_center) * interact_distance
	var query = PhysicsRayQueryParameters3D.create(origin, end)
	query.collide_with_bodies = true
	var result = space_state.intersect_ray(query)
	var current_cast_result = result.get("collider")
	if current_cast_result != interact_cast_result:
		if interact_cast_result and interact_cast_result.has_user_signal("unfocused"):
			interact_cast_result.emit_signal("unfocused")
		interact_cast_result = current_cast_result
		if interact_cast_result and interact_cast_result.has_user_signal("focused"):
			interact_cast_result.emit_signal("focused")

func interact() -> void:
	if interact_cast_result and interact_cast_result.has_user_signal("interacted"):
		interact_cast_result.emit_signal("interacted")

Basically is there a way for me to put what my raycast is looking at in a variable, then using an if statement, have that variable equal the object I want it to (in this case the “generator”), and also have the interact button pressed. This would change the state from “Broken” to “Fixed” but only when I am looking at the generator. Not when I’m looking at something else. Sorry for the bad explaination but all help is greatly appreciated!

1 Like