Godot Version
4.1
Question
Hey guys, (new into game development)
after doing the GDquest courses for the last weeks i am trying to get my hand starting a project of my own.
I have a selection manager node with an attached script
to on click create a dragbox and on release call a function that selects all units in the dragbox. (used this tutorial for the code: https://www.youtube.com/watch?v=TnL0i47QhqI)
now i also have a Game_manager node as the root of my main_scene. here i have an array that stores the selected units. I also debug print() the amount in the array when it gets changed with a setter function
the problem is that when i select a single unit it work as intended it selects it and adds a single unit to the array.
But when i use the drag select it doubles all units added to the array.
i cant seem to findout why it happens. Even chatgtp is not very helpfull in this regard.
I hope you guys can help a noob like myself!
below is the code im currently using:
extends Node
#reference to the colorrect dragbox node
@onready var ui_dragbox: ColorRect = %ui_dragbox
var mouse_dragging := false
var drag_start_position: Vector2
func _input(event: InputEvent) -> void:
if event is InputEventMouseMotion and mouse_dragging:
print("Dragging: ", event.position)
#region creating the selection dragbox
#mouse drag start
if event.is_action_pressed("left_mouse_click"):
mouse_dragging = true
drag_start_position = event.position
ui_dragbox.show()
ui_dragbox.position = drag_start_position
ui_dragbox.size = Vector2.ZERO
_clear_selected_units()
update_selection()
#mouse drag end
elif event.is_action_released("left_mouse_click"):
mouse_dragging = false
ui_dragbox.hide()
# select unit when mouse click released and nothing is selected
if GameManager.selected_units.is_empty():
var ray := _mouse_screen_to_world(get_viewport().get_camera_3d(), 1)
if ray and ray["collider"] is player_unit:
ray["collider"].selected = true
GameManager.selected_units.push_back(ray["collider"])
update_selection()
#update selection gizmo
if mouse_dragging and event is InputEventMouseMotion:
var m_start := drag_start_position
var m_end: Vector2 = event.position
var diff = m_end - m_start
var rect := Rect2(m_start, diff).abs() #to convert values instead of flip positions
ui_dragbox.position = rect.position
ui_dragbox.size = rect.size
_select_units_2d_projected(rect)
#endregion
func _clear_selected_units() -> void:
for unit in GameManager.selected_units:
if not is_instance_valid(unit):
continue
unit.selected = false
GameManager.selected_units = []
update_selection()
func _select_units_2d_projected(rect: Rect2) -> void:
var all_units = get_tree().get_nodes_in_group("units")
var cam := get_viewport().get_camera_3d()
for unit in all_units:
if rect.has_point(cam.unproject_position(unit.global_position)):
if unit.selected == false:
unit.selected = true
if unit not in GameManager.selected_units:
GameManager.selected_units.append(unit)
#if not unit.selected:
#unit.selected = true
#GameManager.selected_units.push_back(unit)
#if unit not in GameManager.selected_units:
#GameManager.selected_units.append(unit)
update_selection()
#raycast to get mouse position on 3d world
func _mouse_screen_to_world(camera: Camera3D, collision_mask:int = 0xFFFFFFFF) -> Dictionary:
var mouse_position = camera.get_viewport().get_mouse_position()
var ray_origin = camera.project_ray_origin(mouse_position)
var ray_end = ray_origin + camera.project_ray_normal(mouse_position) * 500
var space_state = camera.get_world_3d().direct_space_state
var query := PhysicsRayQueryParameters3D.new()
query.from = ray_origin
query.to = ray_end
query.collision_mask= collision_mask
var raycast = space_state.intersect_ray(query)
return raycast
##updates the selection in the Game Manager and Game UI
func update_selection():
if GameManager.selected_units.size() > 0:
GameManager.unit_is_selected = true
GameUi.update_selection_portraits()
else:
GameManager.unit_is_selected = false
GameUi.update_selection_portraits()
