I'm hoping somebody can help me to understand what is happening here. I'm putting in two snippets of code

func _physics_process(delta):
    if Input.is_action_pressed("ui_left"):
        velocity.x = -speed
    elif Input.is_action_pressed("ui_right"):
        velocity.x = speed
    elif Input.is_action_pressed("ui_down"):
        velocity.y = speed
    elif Input.is_action_pressed("ui_up"):
        velocity.y = -speed    

    move_and_slide(velocity)
    velocity = velocity.move_toward(Vector2.ZERO, friction)

and this one:

func _physics_process(delta):
    var input_dir = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
    velocity = input_dir * speed
    
    move_and_slide(velocity)
    
    velocity = velocity.move_toward(Vector2.ZERO, friction)

Both work, and my character moves. In the first code, the move_toward is working brilliantly, and I can control the easing of the character by changing the friction value. On the second code, the easing doesn't work at all. When I print(velocity), I can see the friction value changing the velocity back to ZERO gradually in the first code, whereas in the second code I go from max speed to zero immediately. Does somebody know why move_toward is not working in the second code?

In the first example the value of velocity will not be touched when nothing is pressed. In the second example as soon as nothing is pressed input_dir will be zero and consequently velocity will be calculated as zero too.

    xyz - that makes perfect sense. Appreciate the answer very much!

    I had a some fun with this information thank to @xyz. In the interest of keeping a nice community for us beginners, here's the code I used for a simple character movement:

    extends KinematicBody2D
    
    
    var velocity = Vector2.ZERO
    var speed = 500
    var friction = 1
    
    
    
    func _physics_process(delta):
    	# use the get_vector to see which one of the direction keys is being pressed
    	# it can also calculate two keys being pressed together (up + left for example)
    	var move_dir = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
    	
    	# we then use if to see if move_dir is NOT equal to zero. Basically if you press a key
    	# then move_dir is not equal to zero
    	if move_dir != Vector2.ZERO:
    		
    		# we then use move_toward to bring the character up to speed.
    		# use a lower friction value to make this slow up / down facter slower
    		velocity = velocity.move_toward(move_dir * speed, friction)
    	else:
    		
    		# the else detects when you let go of the keys (becuase move_dir is now == ZERO)
    		# we then again use move_toward to bring the speed to velocity to ZERO, again using friction as a factor
    		# use two separate variables if you want different acceleration and deceleration speeds
    		velocity = velocity.move_toward(Vector2.ZERO, friction)
    		
    	move_and_slide(velocity)

    Obviously I put this code into a kinematic2D body. It's not perfect motion, but very satisfying to play with. As I mentioned in the code, set up two variables, one for acceleration and one for deceleration to fine tune how quickly you go to full speed, and how slowly you slow down. Hope that helps somebody starting out. Please, if there's something I've got wrong here, or could do better - always looking for constructive feedback.

      madpsychot
      Something real simple you could "improve" if it matters to you:

      # This might be easier on the eyes
      #than this when you come back from hiatus
      ### though it doesn't matter much. it's all preference ###
      ###BUTIREALLYHOPEYOURENOTSHARINGCODELIKETHIS###HELPWILLBEHARDIFYOUDO###

        madpsychot
        That's up to you and whoever else is working on it.
        If this was a shared project between you and me in particular, I'd appreciate it, yeah.