'null instance' returned from 'offset' & 'position'

Godot Version

4.6.2

Question

I am working on a 2D platforming game and it’s my first time using Godot at all. I’m trying to get the camera (Camera2D) to move so that the player will be offset to the left side of the screen when facing right and offset to the right side of the screen when facing left. I used code from this forum attempting the same thing.

However, I keep receiving these errors: Invalid access to property or key ‘offset’ on a base object of type ‘null instance’. & Invalid access to property or key ‘position’ on a base object of type ‘null instance’.

This is my edited version of the code for different node names and such:

func _process(delta: float) -> void:
	var screenWidth = get_viewport_rect().size.x
	var cameraTarget
	var targetDistance = 100
	var cameraSpeed = 6

	if Input.is_action_pressed("ui_right"):
		cameraTarget = $Player.position.x + targetDistance - screenWidth/2 * delta
		$Camera2D.offset.x = min($Camera2D.offset.x + cameraSpeed, cameraTarget)
	else: if Input.is_action_pressed("ui_left"):
		cameraTarget = $Player.position.x - targetDistance - screenWidth/2 * delta
		$Camera2D.offset.x = max($Camera2D.offset.x - cameraSpeed, cameraTarget)
	$Camera2D.offset.y = $Player.position.y

The original code was for a question dated in 2021, so I wonder if the issue is caused from a difference in versions? I’m using the most recent version, 4.6.2.

Any help would be appreciated!

Both your $Camera2D and $Player seem to be null. Do you have nodes named “Camera2D“ and “Player“ in your scene? You can drag and drop a node into the script to create a correct reference to the node.

2 Likes

BecaUse your nodes are null, just CHeck thAt the names used in your Code correspond to tHe nAmes you used when creating the nodes.

Thank you for the tip about clicking and dragging! Somehow, the node names in the code did not correspond with the node names in the hierarchy, so while I thought they were called ‘Player’ and ‘Camera2D,’ they were actually called… “..” and “.” weirdly enough. A simple fix with variables. Thanks again!

Fixed code:

func _process(delta: float) -> void:
	var screenWidth = get_viewport_rect().size.x
	var cameraTarget = $".." # matching the target to the player node
	var targetDistance = 100
	var cameraSpeed = 6
	var player = $".." # naming the player node to something that aligned w its name in the hierarchy
	var camera = $"." # same thing here with the camera
	
	if Input.is_action_pressed("ui_right"):
		cameraTarget = player.position.x + targetDistance - screenWidth/2 * delta
		camera.offset.x = min(camera.offset.x + cameraSpeed, cameraTarget)
	if Input.is_action_pressed("ui_left"):
		cameraTarget = player.position.x - targetDistance - screenWidth/2 * delta
		camera.offset.x = max(camera.offset.x - cameraSpeed, cameraTarget)
	camera.offset.y = player.position.y
1 Like

Glad it helped :slight_smile:

Here’s why your references are weird if you’re interested:
Dollarsign $ references are actually nodepaths to the nodes they reference. (I assumed they were child nodes of the node the script is attached to, in wich case the path to them would be just their name.)

$“.” is a reference to the node the script is attached to, so it’s not needed. This:
$“.”.position = Vector3.ZERO
Is the same as this:
self.position = Vector3.ZERO
But you can omit both and just do this:
position = Vector3.ZERO(This will set the camera position, if the script is attached to the camera)

Dollarsign references will break if you move the nodes in your scene, since their nodepath will change.

If you actually want to reference nodes by name you have to right click them and enable “access by unique name”. Then this: %Player will always be a reference to a node called ‘Player’, wherever it is in your scene. (Note it’s a different sign: %)

Also you can hold CTRL when you drag&drop the node into your script to create reference varibles, similarly as you did. (It will add the @onready annotation, and it should be dropped outside of functions)

1 Like

Ohh, I see! Thank you for the additional information, this should help make things a little cleaner in the code : )