Why is my node returning as a null instance?

Godot Version

Godot 4.5 Stable

Why is FloorCast returning as null?

extends CharacterBody3D
class_name player
#Define Variables
@export_group(“Camera”)
var _camera_input_direction := Vector2.ZERO
var fall_speed = 1500
var coyote_timer = 0.0
var coyote_time = 0.1
var gravity = -800
var Speed = 0
var ground_Speed = Speed
var jump_time = 1.0
var jump_timer = 0.0
var jump_velocity = 500
var can_Jump = false
var momen = 2
var acc = 10
var dec = 10
var rot = 0.0
var slope_angle = 0.0
var direction = 0
var motion = Vector3(0,0,0)
var grounded = false
var fall_off_wall = false
var slope_factor = 0.0
var control_lock = false
var stuck = false
@onready var Player: MeshInstance3D = %Model
@onready var FloorCast = %FloorCast
@onready var IdleCollisionShape: CollisionShape3D = %“Hitbox-Idle”
var angle = 0
var friction = gravity * $“.”.rotation.z
var last_movement_direction := Vector3.BACK
var Max_Speed = 130
var Left_Stick_Sensitivity := 0.1
var Right_Stick_Sensitivity := 0.1
var Jump_Velocity = 250
var count = 0
var rotationSpeed = 12.0
@onready var camera: Node3D = %CameraPivot
@onready var _camera: Camera3D = %Camera3D
var moving = 0
var mouse_sensitivity := 0.25
var x_input = 0
var y_input = 0
#func _slopeDetection():
#if %FloorCast.is_colliding() or not %SlopeCast.is_colliding():
#angle = 0
#elif %SlopeCast.is_colliding():
#angle = 1
#gravity
func _floorcast_instansiate():
FloorCast = %FloorCast
func _ready() → void:
add_to_group(“Player”)
add_to_group(“Bad Guys”)
func _gravity(delta: float) → void:
if not is_on_floor() and rot == 0:
count == 1
velocity.y = move_toward(velocity.y, fall_speed, gravity * delta)
else:
if abs(slope_factor) == 1: #gets the slope factor to prepare for physics
velocity.y = 0

	else:
		velocity.y = 80

func _input(event: InputEvent) → void:
if event.is_action_pressed(“left_click”): #K&M input
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
if event.is_action_pressed(“ui_cancel”):
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
func _physics_process(delta: float) → void:
_jump(1)
if %FloorCast == null:
print(“Null”)
else:
print(FloorCast)
if FloorCast.is_colliding():
can_Jump = true#Jumping failsafe, bandaid if anything but as long as it works
if Input.is_action_just_pressed(“Jump”) and can_Jump:
velocity.y += jump_velocity
if not is_on_floor():
_gravity(delta)
camera.rotation.x += _camera_input_direction.y * delta #camera script
camera.rotation.x = clamp(camera.rotation.x, -PI / 6.0, PI / 3.0) #Restricts movement of the camera to help player maintain control
camera.rotation.y -= _camera_input_direction.x * delta #rotates the camera
_camera_input_direction = Vector2.ZERO #gets the camera input
#var camera_direction := Input.get_action_strength(“Look_Left”) - Input.get_action_strength(“Look_Right”);
#var character_direction := Input.get_action_strength(“Left”) - Input.get_action_strength(“Right”);
#camera.rotation.y += camera_direction * Right_Stick_Sensitivity;
#Player.rotation.y += character_direction * Right_Stick_Sensitivity;
#print(Speed)
if Input.is_action_pressed(“Up”) or Input.is_action_pressed(“Down”) or Input.is_action_pressed(“Left”) or Input.is_action_pressed(“Right”):
moving = true
if Speed != Max_Speed: #builds the momemtum for the player
Speed += momen
else:
moving = false
if Speed > 0:
Speed -= dec #decelerates the Speed so the player slows down
#var look_direction = Vector2(velocity.z, velocity.x)
#Player.rotation.y = lerp_angle(Player.rotation.y, look_direction.angle(), delta * 12)

var raw_input := Input.get_vector("Left", "Right", "Up", "Down") #gets the inputs
var forward := _camera.global_basis.z #gets the forwars inputs
var right := _camera.global_basis.x #gets the x inputs
var move_direction = forward * raw_input.y + right * raw_input.x #calculates the movement direction based on the input from they player 
move_direction.y = 0.0 #Failsafe
move_direction = move_direction.normalized()
var target_velocity = move_direction * Speed #Sets the velocity the game hopes to acheive
var smoothing_factor = 0.1 #adds a bit of force so the speed can bee maintained
if angle == 0:
	target_velocity = move_direction * Speed
	velocity = velocity.lerp(target_velocity, smoothing_factor)
else:
	target_velocity = move_direction * Speed * friction #Alternate movement for when on slopes
#var move_acc = acc * 0.9
#if moving:
	#velocity = velocity.move_toward(move_direction * Speed, move_acc * delta)
move_and_slide()
if is_on_floor():
	if count == 0:
		print("On floor")
		count = 1
	can_Jump = true
	slope_angle = get_floor_angle() + (PI / 2) #gets the slope of the ground
	slope_factor = get_floor_normal().z
else:
	slope_angle = 0.0 #sets angle mode back to default when in the air
	#Player.rotation.y = rot
	Player.rotation.x = rot
	Player.rotation.z = rot
if is_on_floor():
	if not grounded:
		if abs(slope_angle) >= abs(velocity.y) and abs(velocity.y) > abs(velocity.z):
			velocity.z = velocity * slope_factor #Changes the movement according to the slope
		grounded = true
	up_direction.normalized() #Normalises the direction
	rot = slope_angle
else:
	if not FloorCast.is_colliding() and grounded: #gets the velocity for when not on ground
		grounded = false
		velocity = get_real_velocity()
		rot = 0
		up_direction = Vector3(0, -1, 0)
if FloorCast.is_colliding(): #Self explanatory
	can_Jump = true
if move_direction.length() > 0.2:
	last_movement_direction = move_direction #gets the last direction the player moved in
var targetAngle := Vector3.BACK.signed_angle_to(last_movement_direction, Vector3.UP) #sets a tarhet for the angle
Player.global_rotation.y = lerp(Player.rotation.y, targetAngle, rotationSpeed * delta) #rotates the player accordinlgy

func _unhandled_input(event: InputEvent) → void: #mouse controls
var is_camera_motion := (
event is InputEventMouseMotion and
Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED
)
if is_camera_motion:
_camera_input_direction = event.screen_relative * mouse_sensitivity
func _coyote_time(delta):#coyote timer for jumping
if coyote_time > 0:
coyote_time -= delta
else:
coyote_time = coyote_timer
if coyote_timer > 0:
can_Jump = true
else:
if not is_on_floor():
can_Jump = false
func _jump(delta: float) → void: #on floor detector really. Misleading name on my part but long story there
if is_on_floor():
can_Jump = true
else:
can_Jump = false
if Input.is_action_just_pressed(“check”): #tester for key variables
print(“can_Jump:”, can_Jump)
print(“coyote_time:”, coyote_time)
print(“is_on_floor():”, is_on_floor())
print(“jump_timer:”, jump_timer, “/”, jump_time)
print(“Friction:”, friction)
print(“Angle:”, angle)
print(“is_on_wall:”, is_on_wall())
print(“Slope_Angle:”, slope_angle)

For the life of me I can not work out why FloorCast is returning as a null instance

Have you double checked if FloorCast is set as scene unique node for the player’s scene?

Yes, there’s no other node called FloorCast it’s completely unique to my Player scene

Are you instantiating FloorCast?

Just because it’s the only node with that name doesn’t mean it’s set as scene unique node. In the scene tree, is there a % sign next to FloorCast’s name?

(Like in this example:)

Yes it has that

No but tried it just there and it gave me an error

Can you show the scenetree of the characterbody where this script is attached to?

When does it return null? Print its value every step of the way, starting with printing it in _ready().

Does the debugger report any other erros?

It’s hard to say. I have a print(FloorCast) in the ready function and in the physics process and I got this

And Debugger:

What is “playerPhysics”?

My script?

Is this script used as a Singleton? Because otherwise there had to be a node named “PlayerPhysics” at the root of your current_scene. (The error occurs at “/root/PlayerPhysics”.)

1 Like

Can you open the playerCharbody.tscn-file in a textedtior and share the content here?

[gd_scene load_steps=6 format=3 uid=“uid://co532qttrhllw”]

[ext_resource type=“Script” uid=“uid://emndx4uyvhv7” path=“res://playerPhysics.gd” id=“1_rrgps”]

[sub_resource type=“CapsuleMesh” id=“CapsuleMesh_7yxoy”]

[sub_resource type=“BoxMesh” id=“BoxMesh_rrgps”]

[sub_resource type=“CapsuleShape3D” id=“CapsuleShape3D_kfj54”]

[sub_resource type=“SeparationRayShape3D” id=“SeparationRayShape3D_rrgps”]

[node name=“Player” type=“CharacterBody3D”]
floor_stop_on_slope = false
script = ExtResource(“1_rrgps”)

[node name=“Model” type=“MeshInstance3D” parent=“.”]
unique_name_in_owner = true
mesh = SubResource(“CapsuleMesh_7yxoy”)

[node name=“Visor” type=“MeshInstance3D” parent=“Model”]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.357396, 0.421128)
mesh = SubResource(“BoxMesh_rrgps”)

[node name=“Hitbox-Idle” type=“CollisionShape3D” parent=“.”]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.19209e-07, -0.00821924)
shape = SubResource(“CapsuleShape3D_kfj54”)

[node name=“CameraPivot” type=“Node3D” parent=“.”]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.05132, 0)

[node name=“SpringArm3D” type=“SpringArm3D” parent=“CameraPivot”]
transform = Transform3D(-1, 2.8195e-15, -8.74228e-08, -3.97679e-08, 0.890546, 0.454892, 7.7854e-08, 0.454892, -0.890546, 0, 0, 0)
shape = SubResource(“SeparationRayShape3D_rrgps”)
spring_length = 6.0

[node name=“Camera3D” type=“Camera3D” parent=“CameraPivot/SpringArm3D”]
unique_name_in_owner = true
transform = Transform3D(1, -1.77636e-14, -1.35003e-13, -3.55271e-15, 1, 0, -7.10543e-15, 0, 1, -9.76239e-08, -0.570405, 1.11669)

[node name=“SlopeCast” type=“RayCast3D” parent=“.”]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 0.345003, 0.938601, 0, -0.938601, 0.345003, 0, -0.892207, 0.093752)

[node name=“FloorCast” type=“RayCast3D” parent=“.”]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.8717418, 0)

The file seems fine.

As @hyvernox suggested, do you have this script as a autoload?

You’re running your script on more than one node. One of them is likely an autoload.

Yes so the enemy can get the player’s position

Yes so the enemy knows the player position