Issue with placing objects in 3D

Godot Version

4.6.2.

Question

Hey everyone,

I tried implementing a placement system. After failing to do it myself I resorted to using a YouTube Tutorial. (This one: https://www.youtube.com/watch?v=f0yuG8LS-sU)

But since this tutorial uses a different camera approach I couldnt quite get it to work as intended 100%.

I really tried my best to figure out why this jumping of the placeable object happens but i wasnt able to fix it.

The part that is causing the problems start at “if placing:“.

I guess it has to do something with the different angle / viewport that is used - but im not sure.

I’d really appreaciate some help in understanding and figuring out how to solve this and why this happens.

Thanks in advance :slight_smile:

extends CharacterBody3D

@onready var pivot = $CamOrigin
@onready var raycast = %RayCast3D
@onready var hand = $CamOrigin/Camera3D/Hand
@onready var camera = $CamOrigin/Camera3D
var object_in_hand = null

@export var sens : float = 0.5

@onready var table = preload("res://scenes/Table_4_Seats.tscn")
var instance
var placing
var range = 10000
var can_place = false

func _ready():
	Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
	camera = get_viewport().get_camera_3d()
	
func _input(event):
	if event is InputEventMouseMotion:
		rotate_y(deg_to_rad(-event.relative.x * sens))
		pivot.rotate_x(deg_to_rad(-event.relative.y * sens))
		pivot.rotation.x = clamp(pivot.rotation.x, deg_to_rad(-90), deg_to_rad(45))

func _unhandled_input(event: InputEvent) -> void:
	if event.is_action_pressed("interact") and can_place:
		placing = false
		can_place = false
		instance.placed()
		#instance.queue_free()

func _process(delta: float) -> void:
	$CanvasLayer/Label.text = str(get_tree().get_nodes_in_group("FreeSeats").size())
	pickup()
	%Money.text = str(GameManager.money)
	
	if placing:
		var mouse_pos = get_viewport().get_mouse_position()
		var ray_origin = camera.global_position 
		var ray_end = ray_origin + camera.project_ray_normal(mouse_pos) * range
		var query = PhysicsRayQueryParameters3D.create(ray_origin, ray_end)
		var collision = camera.get_world_3d().direct_space_state.intersect_ray(query)
		if collision:
			instance.transform.origin = collision.position
			can_place = instance.check_placement()

	if Input.is_action_just_pressed("1"):
		if placing:
			instance.queue_free()
		instance = table.instantiate()
		placing = true
		get_parent().get_node("NavigationRegion3D").add_child(instance)

I would guess your ray is hitting the already placed bench. For a test remove the collision from the bench object. If that is the case think about a solution with different collision layers, or check for the floor.

Thanks a lot. That was the fix. Actually didnt think of that.

I disabled all the layers on the node and only set them, when the node gets placed:
set_collision_layer_value(1, true) set_collision_layer_value(2, true) set_collision_mask_value(1, true) set_collision_mask_value(2, true)

Thanks again.

1 Like