• Godot Help
  • Vector2 is a 'null Instance'. How and why?

I have a declared velocity as a global Vector2 variable. I never set it to be anything other than a Vector2. When I use the move_toward method on it in the move_state function, it works and adjusts the player's velocity by either the ACCELERATION or FRICTION constants depending on if the player is trying to move.

What I want to happen is a speed boost when the player presses the attack button. When in the move state, the move_state function is running every frame, and if the player presses the attack button the velocity will be set to the last normalised input vector multiplied by the ATTACK_SPEED constant (to give them a big speed boost) then change state to attack. Then, while in the attack_state function I will move the velocity vector towards Vector2.ZERO by the global FRICTION const so the players initial speed boost slows down. But, somehow velocity has become a null Instance and it doesn't work.

I get 'Attempt to call function 'move_toward' in base 'null instance' on a null instance.' in the attack_state function.

Thanks


const ACCELERATION = 40
const FRICTION = 60
const MAX_SPEED = 400
const ATTACK_VELOCITY = 1000

enum {
	MOVE,
	ROLL,
	ATTACK
}

var state = MOVE
var velocity = Vector2.ZERO
var input_vector = Vector2.ZERO
var last_input_vector = Vector2.ZERO

onready var animationPlayer = $AnimationPlayer
onready var animationTree = $AnimationTree
onready var animationState = animationTree.get("parameters/playback")
onready var sprite = $Sprite

func _ready():
	animationTree.active = true

func _physics_process(delta):
	match state:
		MOVE:
			move_state(delta)
		ROLL:
			pass
		ATTACK:
			attack_state(delta)
	
	##Code to snap the sprite coords to a 4px grid
	##Finds the distance between the sprite and closest 4px interval then moves to it
	#sprite.position.x = stepify(global_position.x, 4) - global_position.x
	#sprite.position.y = stepify(global_position.y, 4) - global_position.y
	
func move_state(delta):
	input_vector.x = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
	input_vector.y = Input.get_action_strength("ui_down") - Input.get_action_strength("ui_up")
	input_vector = input_vector.normalized()
	
	if input_vector!= Vector2.ZERO:
		last_input_vector = input_vector
		animationTree.set("parameters/Idle/blend_position", input_vector)
		animationTree.set("parameters/Run/blend_position", input_vector)
		animationTree.set("parameters/Attack/blend_position", input_vector)
		animationState.travel("Run")
		velocity = velocity.move_toward(input_vector * MAX_SPEED, ACCELERATION)
	else:
		animationState.travel("Idle")
		velocity = velocity.move_toward(Vector2.ZERO, FRICTION)
	
	velocity = move_and_slide(velocity)
	
	if Input.is_action_just_pressed("attack"):
		velocity +=  (last_input_vector * ATTACK_VELOCITY)
		state = ATTACK
	
func attack_state(delta):
	animationState.travel("Attack")
	velocity = velocity.move_toward(Vector2.ZERO, FRICTION)
	velocity = move_and_collide(velocity * delta)
	
func attack_animation_finished():
	state = MOVE

In attack_state(), you're setting velocity to the result of move_and_collide(). I believe that move_and_collide() returns a null unless a collision occurs, at which point you get a KinematicCollision(2D) object back. You don't get a vector in either case.

Nevermind, I figured it out. I thought 'move_and_slide(velocity)' would return the new velocity value, but it returns a null object. I got rid of the 'velocity = ' in front because I'm not sure if it's useful then and now it works.