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.
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.
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
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)