Player is on floor according to player script, but not according to another script

Godot Version

4.6

Question

Hi guys! I’ve been playing around with godot a bit, I want to make a game where if you’re on the ground there is some kind of shield which you can move with the mouse to protect yourself. But it should disappear when you’re off the ground. Now for some strange reason, the script of the shield registers the player as “off the ground” (print statement) while the actual player script registers it as on the ground.

#Player.gd
class_name Player extends CharacterBody2D


@export var FRICTION = 2000.0
@export var SPEED = 1500.0
@export var STEP_DISTANCE = 250.0
@export var JUMP_VELOCITY = -600.0
@export var MAX_JUMPS = 2

var count := 0
var direction_sign := 0
var target_distance := 0.0


func _physics_process(delta: float) -> void:
	print("player on floor according to player script: ", is_on_floor())
	
	if not is_on_floor():
		velocity += get_gravity() * delta
	else:
		count = 0
		
	if  Input.is_action_just_pressed("jump") and count < MAX_JUMPS:
		count += 1
		velocity.y = JUMP_VELOCITY
		
	var direction := Input.get_axis("move_left", "move_right")
	direction_sign = sign(direction)

	if Input.is_action_just_pressed("move_left") or Input.is_action_just_pressed("move_right"):
		velocity.x = direction_sign * SPEED 
		target_distance = STEP_DISTANCE
	else:
		velocity.x = move_toward(velocity.x, 0, FRICTION * delta)
		
	if target_distance > 0:
		target_distance -= abs(velocity.x * delta)
	if target_distance <= 0:
		velocity.x = 0
	
	move_and_slide()
# shield.gd
class_name Shield extends StaticBody2D


var player = Player.new()
@onready var sprite = $Sprite2D
@onready var collision_shape = $CollisionShape2D

# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	print(collision_shape)


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	print("visible: ", sprite.visible)
	print("player on floor: ", player.is_on_floor())
	
	
	if not player.is_on_floor():
		sprite.hide()
		collision_shape.disabled = true;
	else:
		sprite.show()
		collision_shape.disabled = false;

By the way, the “steps” are intended, I want to make a 2048-like movement.

You are creating a new player object here. Since it’s just the object and not a scene it doesn’t have any child nodes (and can’t collide without a CollisionShape) and it’s not getting added to your scene either.

Your var player should be referencing an existing player scene instance instead of creating some new instance.

One additional note: collision_shape.disabled should be changed via set_deferred().

How does the shield get reference to the player node?

what do I do instead of Player.new()?

Depends on your scene structure. The easiest way is probably to export the variable ( @export var player: Player ) and set the reference in the inspector.

1 Like

Thanks a lot man!

1 Like