What I’m asking, I’m unsure if it’s possible or not. I am currently making a 2D platformer game where the UI follows the player around, using a CanvasLayer as an intermediary between the Player and the UI (per a suggestion on another post on here) with an instance of the UI as a child of the Canvas Layer.
What I’m wanting to know is if it’s possible for this player-locked UI to not be locked in the main scene? Pictures below for reference:
Would that allow me to instantiate it on the player so it follows them around? Apologies if that’s an obvious question; I’m newer to Godot/programming.
Thank you for this! I inadvertently found out I’ve been using what I thought were Autoloads, but were in fact Singletons. Thank you for providing that link, funny as the domain is.
So, after putting my UI as an Autoload and putting it as a child node of my player, I am getting a Null Instance error for my Health and Experience nodes. I’m not sure why; code below, the setup is one of my pictures in the original post.
gd line 16 at function _ready() (function in question):
It’s saying that my %Health and %Experience are null instances, despite them being visible in the 2D editor, and set as unique names.
Edit to add: the do_visible_ui() function is just a bunch of boolean checks that don’t get changed until the player does something in the game, like die/win:
Autoloads load automatically without even adding them to levels. You probably have an additional UI within the game, if you have one as child of the player. The Canvas layer automatically follows the viewport. When you assign things as child nodes, they usually inherit from the parent. This may change what the UI nodes are doing.
Making the autoload a singleton makes sure that you can access the autoload without needing get-parent/child references. You can assign them a class name and just say things like UI.function() to call functions to enable/disable.
You can also get/set references to use data within a singleton. So that means you can access variables within a database or variable manager. So you can have a simple place to store game data and use this to save/load easier.
class_name Database
static var Chest_List = {"Lv1_Chest1": false, "Lv1_Chest2": true}
static var PlayerHealth : int = 100
class_name Chest extends Node
@export var Item_ID : String
var Is_Chest_Open : bool :
get : return Database.Chest_List[Item_ID]
set(value) : Database.Chest_List[Item_ID] = value
class_name HealthBar extends Node
var Health : int :
get : return Database.PlayerHealth
set(value) : Database.PlayerHealth = value
Thank you for this, really. As I said, I’m newer to programming, and there’s many facets (such as set/get) that I didn’t know existed as I’m now delving past the beginner things. I was wondering the last couple of days how to iterate on my code currently, and I think making a Resource/Database for the Player might be a way to go. Currently I have a loose coupling with my UI/Player right now, and I think that’s what’s throwing those errors in my UI.
Yeah, the get/set can make things easier. You don’t need to actually put both Get/Set ether. When you know you’re not going to have the Health-Bar change the player health. You can use Get and leave the Set part out.
There’s also a cool trick you can do with two health bars. Make another variable inside your Health-Bar and put that health_bar behind the other one. Make this health_bar a slightly different color.
When you take damage the first health will change instantly because they are directly linked to the database. But the second health_bar wont change and you have to check to see whether it matches the other value.
Use that to slowly increment the health every frame until they match up. This will add a simple affect that shows how much damage you took, but then gradually matches the current health.
I’m not attempting to bump this old post, but for posterity’s sake, the solution was to, in my player script, make:
@onready var this_scene = get_tree().current_scene.name
func _ready():
if this_scene == 'PortalRoom':
$Camera2D.enabled = false
else:
$Camera2D.enabled = true
the Camera2D not follow the player if the scene name check is true, then I was able to put a new Camera2D on the scene that I didn’t want to have follow the player. The Godot Docs on Camera2D talked about "when [.enabled = false], it defaults to any other Camera2D node in the tree.