Building System?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By jm4rcos

I was searching and did not find any tutorial how to make a building system. I want to select a mesh (wall) and make it folow the mouse and when I press some key, it conects with the floor. How am I able to do this? Any help will be appreciated! Cheers!

:bust_in_silhouette: Reply From: Tim Martin

Hello,
One idea for this. You could start with four top-level nodes

  • A MeshInstance called Wall with your wall mesh.
  • A StaticBody called Floor. Add a MeshInstance as a child of Floor, and give this a new PlaneMesh. Then select this new MeshInstance and click (top-middle of screen) Mesh->Create Single Convex Collision Sibling
  • A Spatial called BuildingManager with a GDScript attached.
  • A Camera called Camera

BuildingManager could have script like (note: this isn’t tested, might have typos…)

extends Spatial

onready var current_wall = $"../Wall".duplicate()
onready var camera = $"../Camera"

func _ready():
	add_child(current_wall)

func _physics_process(var _delta : float):
	var mouse_pos = get_viewport().get_mouse_position()
	var from = camera.project_ray_origin(mouse_pos)
	var to = from + camera.project_ray_normal(mouse_pos) * 1000.0
	var result = get_world().direct_space_state.intersect_ray(from, to)
	if not result.empty():
		current_wall.translation = result.position
	
	if Input.is_action_just_pressed("ui_accept"):
		current_wall = $"../Wall".duplicate()
		add_child(current_wall)

Should keep the wall following the mouse as you move the mouse over the floor, until you press whatever you have bound to “ui_accept” at which point it will “fix” the wall in place and spawn a new one, which can also then be placed, and so on…

You will probably need to adjust the translation.y after the ray-cast so that the Wall is not half-embedded in the floor. And then you might want to add the option to rotate the wall, and also to start snapping the position you get back from the ray-cast to a grid.

You then probably want to make Wall a StaticBody (like Floor), with its own MeshInstance and CollisionShape children. Otherwise your player character could run right through it. These Wall StaticBody instances might need to be on a different collision_layer from Floor, which you could then exclude when you call intersect_ray. Or not… it depends on if you want to be able to build walls-on-walls…

EDIT: BuildingManager Node → Spatial
EDIT2: Add camera. Complete example at DemoBuilding.tscn - Pastebin.com

Thank you, Tim! Cheers!!

jm4rcos | 2020-05-08 19:44

but tim, it says that get_world() is not declared. can you help with that?

jm4rcos | 2020-05-08 20:36

Ah yes, my mistake.
BuildingManager has to be a Spatial, not a Node. And then the script would start “extends Spatial”.

You then have access to the 3D world (https://docs.godotengine.org/en/stable/classes/class_spatial.html#class-spatial-method-get-world)

Tim Martin | 2020-05-09 10:23

I was trying to call the camera that is inside the player scene and the $“…/Wall”. But it shows "Attempt to call “duplicate()” in base “null instance” on a null instance. Is the camera used in camera.project_ray… the same as the player? And I created A MeshInstance, called floor in the main.scene, than a Static also in the scene and the Spatial (BuildingManager). Used singleton to call the scenes but did not worked

jm4rcos | 2020-05-10 01:04

Hello jm4rcos,

Yep, another typo. Forgot to mention that you need to add a Camera node too. The dangers of typing and not testing…

Here is the full example of the prototype above, I added some simple (x,z) snapping and rotation on LEFT and RIGHT buttons too.

It remains super basic, but hopefully it can give you a starting point from which you can expand.

Scene file: save this as DemoBuilding.tscn inside your existing project DemoBuilding.tscn - Pastebin.com

DemoBuilding.tscn

Tim Martin | 2020-05-10 12:40

Thank you so much, Tim!!! Very helpful. I am already changind some thins to make the style i wanted. Just getting trouble when trying to modulate the “wall”. Cheers!!

jm4rcos | 2020-05-10 23:56