Can this movement script be more optimized?

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

Hello,

So I’ve made this KinematicBody2D 8-directional movement in GDScript, and I would like to hear feedback and if I can optimize it better. Currently, the controlled animated sprite can walk, run and dodge. I used lerp to add a sense of weight to the character and a little slide when dodging.

extends KinematicBody2D

var direction = Vector2(0,0)
var lerping_speed = Vector2(0,0)
var current_speed = Vector2(0,0)
var running_speed = Vector2(500, 500)
var walking_speed = Vector2(250, 250)

var entity
func _ready():
	entity = $Player
	set_process(true)
	set_process_input(true)

func _input(Input):
	
	if Input.is_action_pressed("ui_shift_left"):
		$Player.play("left_run")
		current_speed = running_speed
		direction.x = -current_speed.x
	elif Input.is_action_pressed("ui_ctrl_left"):
		if $DodgeCD.is_stopped():
			$DodgeCD.start()
			direction.x = -800
			lerping_speed.x = lerp(lerping_speed.x, direction.x, 1)
			$Player.play("left_dash")
	elif Input.is_action_pressed("ui_left"):
		$Player.play("left")
		current_speed = walking_speed
		direction.x = -current_speed.x
	elif Input.is_action_released("ui_left"):
		direction.x = 0
		if $AnimWait.is_stopped():
			$AnimWait.start()
			$Player.play("center")
		
	if Input.is_action_pressed("ui_shift_right"):
		$Player.play("right_run")
		current_speed = running_speed
		direction.x = current_speed.x
	elif Input.is_action_pressed("ui_ctrl_right"):
		if $DodgeCD.is_stopped():
			$DodgeCD.start()
			direction.x = 800
			lerping_speed.x = lerp(lerping_speed.x, direction.x, 1)
			$Player.play("right_dash")
	elif Input.is_action_pressed("ui_right"):
		$Player.play("right")
		current_speed = walking_speed
		direction.x = current_speed.x
	elif Input.is_action_released("ui_right"):
		direction.x = 0
		if $AnimWait.is_stopped():
			$AnimWait.start()
			$Player.play("center")

	if Input.is_action_pressed("ui_shift_up"):
		$Player.play("up_run")
		current_speed = running_speed
		direction.y = -current_speed.y
	elif Input.is_action_pressed("ui_ctrl_up"):
		if $DodgeCD.is_stopped():
			$DodgeCD.start()
			direction.y = -800
			lerping_speed.y = lerp(lerping_speed.y, direction.y, 1)
			$Player.play("up_dash")
	elif Input.is_action_pressed("ui_up"):
		$Player.play("up")
		current_speed = walking_speed
		direction.y = -current_speed.y
	elif Input.is_action_released("ui_up"):
		direction.y = 0
		if $AnimWait.is_stopped():
			$AnimWait.start()
			$Player.play("center")
		
	if Input.is_action_pressed("ui_shift_down"):
		$Player.play("down_run")
		current_speed = running_speed
		direction.y = current_speed.y
	elif Input.is_action_pressed("ui_ctrl_down"):
		if $DodgeCD.is_stopped():
			$DodgeCD.start()
			direction.y = 800
			lerping_speed.y = lerp(lerping_speed.y, direction.y, 1)
			$Player.play("down_dash")
	elif Input.is_action_pressed("ui_down"):
		$Player.play("down")
		current_speed = walking_speed
		direction.y = current_speed.y
	elif Input.is_action_released("ui_down"):
		direction.y = 0
		if $AnimWait.is_stopped():
			$AnimWait.start()
			$Player.play("center")

func _process(delta):
	lerping_speed.x = lerp(lerping_speed.x, direction.x, 0.09)
	lerping_speed.y = lerp(lerping_speed.y, direction.y, 0.09)
	entity.set_position(entity.get_position() + lerping_speed * delta)
:bust_in_silhouette: Reply From: Zylann

If you mean performance, the first thing I see is you should cache all get_node calls into onready variables, because each time you get a node, Godot does a linear search down children to find it. It also makes the code a little bit more maintainable in case node names change.


The following is not necessary because it’s true by default:

set_process(true)
set_process_input(true)

Everytime you have this:

lerping_speed.y = lerp(lerping_speed.y, direction.y, 1)

You can write this instead, because lerp(a, b, 1) always results in b:

lerping_speed.y = direction.y

You can change this line:

	lerping_speed.x = lerp(lerping_speed.x, direction.x, 0.09)
	lerping_speed.y = lerp(lerping_speed.y, direction.y, 0.09)

Into this:

	lerping_speed = lerping_speed.linear_interpolate(lerping_speed, direction, 0.09)

(also I note you are not using delta?)


About code tidyness, it looks like there is a lot of repetition going on. It’s almost 4 times the same code with only a few constant changes, so maybe there is a way to compress that by using a function.

Hello Zylann,

Thank you so much for the info. I’m learning new things everyday, and i think I’ve come up with a better control scheme. More tidy and responsive.

It features 4 speeds: walking, running, sneaking and dodging. And dodging is now button-pressed sensible, meaning that if I press longer it will dash longer, and if I’m running too instead of walking, the dash is even longer.

extends KinematicBody2D

# Physics Variables
var friction = 0.10
var acceleration = 0.25
var velocity = Vector2(0, 0)

# Speed Variables
var speed
var speed_walking = 100
var speed_running = 260
var speed_sneakin = 50

# User Input Mapping
var key_left  = "ui_left"
var key_right = "ui_right"
var key_up    = "ui_up"
var key_down  = "ui_down"
var key_shift = "ui_shift"
var key_ctrl  = "ui_ctrl"
var key_space = "ui_space"

var key_pressed_left  = false
var key_pressed_right = false
var key_pressed_up    = false
var key_pressed_down  = false
var key_pressed_shift = false
var key_pressed_ctrl  = false
var key_pressed_space = false

var key_unpressed_space = false
var key_unpressed_ctrl  = false
var key_unpressed_shift = false

func get_input():

key_pressed_left    = Input.is_action_pressed(key_left)
key_pressed_right   = Input.is_action_pressed(key_right)
key_pressed_up      = Input.is_action_pressed(key_up)
key_pressed_down    = Input.is_action_pressed(key_down)
key_pressed_shift   = Input.is_action_pressed(key_shift)
key_pressed_ctrl    = Input.is_action_pressed(key_ctrl)
key_pressed_space   = Input.is_action_pressed(key_space)
key_unpressed_space = Input.is_action_just_released(key_space)
key_unpressed_ctrl  = Input.is_action_just_released(key_ctrl)
key_unpressed_shift = Input.is_action_just_released(key_shift)

func _physics_process(delta):
get_input()

# Default Values for position and speed
var direction_x = 0
var direction_y = 0
speed = speed_walking

# Player control
if key_pressed_space:
	if $Player_DodgeCD.is_stopped():
		$Player_DodgeCD.start()
		velocity = lerp(velocity, velocity * 50, acceleration)
if key_pressed_ctrl:    speed = speed_sneakin
if key_pressed_shift:   speed = speed_running
if key_pressed_right:   direction_x += 1
if key_pressed_left:    direction_x -= 1 
if key_pressed_up:      direction_y -= 1 
if key_pressed_down:    direction_y += 1 

# Speed formula
if direction_x != 0: velocity.x = lerp(velocity.x, direction_x * speed, acceleration)
else:                velocity.x = lerp(velocity.x, 0, friction)
if direction_y != 0: velocity.y = lerp(velocity.y, direction_y * speed, acceleration)
else:                velocity.y = lerp(velocity.y, 0, friction)
velocity = move_and_slide(velocity)   

kanaszm | 2019-07-17 07:21