How to assign a variable for once?

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

I have created a target variable that should change in every click and drag, but the variable always comes back to the original value after I released the click. I want the target variable to stay to where the last location of the clicked mouse stands (remember the top down RTS games where units move to where the mouse clicked). How? Here’s the code:

on ready car posit = get_position()
var target = Vector2.ZERO

func_process(delta):
    target = posit
    if Input.is_mouse_button_pressed(1):
        target = get_global_mouse_position()

Please imagine if the speed and other lines of code of this 2d kinematic body are already there. Only these lines are shown.

:bust_in_silhouette: Reply From: DodoIta

If it’s a drag and drop, maybe it’s not working because you are selecting the target during the first click, not its release. Anyway, I’d suggest you to set the target using the _input or _unhandled_input callbacks:

onready var target := get_position()

# Provided you defined a "click" action in the InputMap
func _unhandled_input(event: InputEvent) -> void:
    if event.is_action_released("click"):
        target = get_global_mouse_position()

# Then make it move towards target in _process

I haven’t tested this code, but it should work

Sorry. It does not work. When I click any on the map, the unit does not move. By the way, this is not drag and drop but click and drag to move, a necessary mechanic in RTS video games.

BellKitsu | 2022-05-10 16:10

:bust_in_silhouette: Reply From: jgodfrey

Your problem is in the assignment of target = posit, here:

func_process(delta):
    target = posit # <--- problem!
    if Input.is_mouse_button_pressed(1):
        target = get_global_mouse_position()

The posit variable holds a single, static value as assigned in the onready statement. In each frame (_process), you first assign that static value to target. Then, only if the mouse button is pressed, you assign the current mouse position to target. In frames where the mouse is not pressed, the assignment of the single, static value is stored in target, but is not overwritten by the mouse position (because no mouse press) - which is why you get the original value back when the button isn’t pressed.

I’m not sure why that first assignment is necessary (though, could depend on other code details you aren’t showing). My first inclination would be to simply remove the target = posit line in _process().

Here’s the new code:

on ready car posit = get_position()
var target = Vector2.ZERO

func_process(delta):
    
    if Input.is_mouse_button_pressed(1):
        target = get_global_mouse_position()

Without the target = posit, the problem is (sort-of) solved, but unit will move into the top left corner of the map upon start. So this is not the right answer.

BellKitsu | 2022-05-10 15:54

OK, so this is probably closer to what you want…

onready var target = get_position()

func_process(delta):
    if Input.is_mouse_button_pressed(1):
        target = get_global_mouse_position()

That will set the initial target (prior to the first mouse press) to the “current position” (instead of Vector2.ZERO) . Then, on each mouse press, will reassign target to the mouse position…

jgodfrey | 2022-05-10 16:36