Designing/Implementing resize handles for houses for a city builder game

Godot Version

4.6 stable

Question

So as the name suggests I would like to implement handles that pop up when you hover over the building (ref pic). But of course I wouldn’t want them all to pop out the moment I hover over a building, it should work based on proximity, so if my mouse is hitting a wall I want that wall’s handle to pop out so I can modify it and also disappear when I hover over another important area.

First Idea
First thing that came to mind is to have a lot of special collision boxes in these areas that I would basically just move and/or resize them as the house gets the same treatment, but seeing how this house will probably need to be spawned about 100-200 times since it is a city builder, it seems like excessive amounts of collision shapes for this scenario, I am also not sure if collision shapes count towards draw calls but either way it seems too much.
I could modify this so the collisions only appear after hovering over a house and then sneakily shooting another ray right after to see what I am actually hitting but that also seems a bit too much.

Second Idea
Since I can retrieve what is hit, its position, size, roof overhangs all the custom and non-custom properties, I could retrieve the ray position relative to my house and based on that and defining some rules I could know that for example I am hitting a front wall of the house or the roof overhang and with that I can spawn the arrow in the correct position.

Third Idea
I can probably retrieve UVs of the hit face and based on that and a small texture data I can figure out what I am actually hitting.

I hope some of these don’t sound too overcomplicated it is just something that I have come up with, I would love to hear anyone’s opinion on how they think something like this can be handled, literally any ideas are welcome.

PS. Here is my ray setup, nothing fancy but does the job:

func _physics_process(_delta: float) -> void:
	'''
	Ray Info
	'''
	var mouse_pos := get_viewport().get_mouse_position()
	var ray_start := camera.project_ray_origin(mouse_pos)
	var direction := camera.project_ray_normal(mouse_pos)
	var space_state := get_world_3d().direct_space_state
	var ray := PhysicsRayQueryParameters3D.create(
		ray_start,
		ray_start + direction * 1000.0,
		)
	var ray_result := space_state.intersect_ray(ray)

This is the way to do it.

200 collision shapes is peanuts for your PC. Especially that you’re not really calculating any complex physics, you’re just catching mouse raycasts. Most of the time these collision shapes will just stay idle anyway.

Don’t try to disable/enable collision shapes either, you need collision shapes to detect the hover anyway, so just leave them on the whole time.

Don’t fall for the premature optimization trap. First implement a system that works, and only try to optimize if you really need it.

You’ll need some collision shapes to detect the mouse position in 3D space anyway, so we’re back to “first idea”.

Again, you need collision shapes to detect the hit, so we’re back to “first idea”.

Hey hey, thanks for the advice, wanted to just reiterate it would be like 5-6 collision shapes per house, you still reckon it isn’t too much? I know I am definitely prematurely optimizing but I just had to ask :sweat_smile:

Make it a 100 collision shapes per house, doesn’t matter. First create a working system, then measure performance, then worry about optimization.

Fair enough, thanks for the tips! :grin:

1 Like