0 votes

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!

asked May 8 in Engine by jm4rcos (20 points)

1 Answer

0 votes

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 https://pastebin.com/Hs1ieHeg

answered May 8 by Tim Martin (108 points)
edited May 10 by Tim Martin

Thank you, Tim! Cheers!!

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

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)

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

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 https://pastebin.com/Hs1ieHeg

DemoBuilding.tscn

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!!

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.