How to save variables of removed nodes

4.3

I’m trying to have a total amount of each player’s kills (4 player) in a competitive game, but since they get removed, the variables of their score get reset to 0 as well.

I’m trying to figure out how to save the variable amounts in the level script, without them resetting, but I can’t figure it out. What do you recommend I should do?

There are two ways for it:

  1. Do not remove the node, just disabled it like set process false, etc
  2. Save the kills in a Global Autoload before remove
4 Likes

As KingGD said:

But there is another way, through static variables. Example at the link.

2 Likes

I don’t know how the video works. I made them state variables, how do I connect them to the main script? Can I have multiple of the same state variables in different scripts?

  1. You must LOAD SCRIPT on start of your MAIN SCRIPT.
    like: @onready var player_stats = load("res/player/player.gd")
  2. Then player script is loaded, this means your static variables got place where they can be stored.
  3. Then you can save in static variables (that are in Player.gd) all changes.
1 Like

Just track the score in the level script, or a separate script, rather than the player script.

For instance, make a dictionary in the scorekeeper script.

something like var PlayerScores:Dictionary

And it’s structure will be an identifier for the player as the key (player name would work, a reference to the player’s node would also work, you have your pick of it really) followed by their score as the key.

The score doesn’t just have to be an int either, it can be an array (so for example if you want to have something like kills/deaths/assists, you could just make it an array of 3 numbers, and fetch those values from these numbers whenever you wish to display them)

There are many ways you could keep the score, but the most correct way would be to use a signal, but here is a lazy way:

in your scorekeeper node you must have this:

var PlayerScores:Dictionary

Then in your player, you have this:

func _ready() -> void:
	$"../ScoreKeeper".PlayerScores[name] = 0 #Create or reset a dictionary entry for this player on spawn

func damage_receieved(Source: String) -> void:
	player_death(Source) # Source in this case is the name of the player that harmed this player. Ideally received from a signal.

func player_death(Killer: String) -> void:
	$"../ScoreKeeper".PlayerScores[name] += 1 # Add score to the player that killed this player before destroying this player
    queue_free() # Destroy player

$“…/ScoreKeeper” is a reference to the scorekeeper node containing the scorekeeping script. It could also potentially be get_parent() if all players are child to the node that keeps the score.

Direct referencing like this is not recommended (it can weigh down your code in the long run) which is why I recommend you learn how to create and use custom signals instead.

1 Like

The strange thing is that I am using @onready var playerone = $PlayerOne

And then using if playerone.living (living is a var in the playerone script) == false:

And that seemed to be working fine.

I’ll have to try some of this out and see if it will fix all the score counting stuff though.

You’d have to do that individually for every player, and it’ll look for players after they’re destroyed, better to just let the player handle updating the scores.

Because each player can create their own score entry in my (lazy and not highly recommended) method, there is no hard limit on how many players there can be.

And because the player handles updating the score, the scorekeeping script doesn’t actually need to track anything, the player just updates the scorekeeping script’s variable which is more efficient (since nothing needs to be executed on _process) and serves your need of preserving the score after the player’s death.

Although KingGD’s solution would probably be perfectly fine for your purpose as well, but it didn’t really answer the actual question. Which is to simply store the variable in another script (like the level script) from the start.

1 Like

Quick question: do static variables work for multiple scripts ie, playerone script and another seperate script both have a static var of the same name, will they count as the same variable? @rabcor @KingGD @GorevAndrew

I think I got it working, I used static variables in the player codes and here is the code in the level script:

func scoring():
	playeronescore = (playertwo.ponescore + playerthree.ponescore + playerfour.ponescore)
	playertwoscore = (playerone.ptwoscore + playerthree.ptwoscore + playerfour.ptwoscore)
	playerthreescore = (playerone.pthreescore + playertwo.pthreescore + playerfour.pthreescore)
	playerfourscore = (playerone.pfourscore + playertwo.pfourscore + playerthree.pfourscore)
	
	
	playeronekillcount = (playertwo.ponekillcount + playerthree.ponekillcount + playerfour.ponekillcount)
	playertwokillcount = (playerone.ptwokillcount + playerthree.ptwokillcount + playerfour.pthreekillcount)
	playerthreekillcount = (playerone.pthreekillcount + playertwo.pthreekillcount + playerfour.pthreekillcount)
	playerfourkillcount = (playerone.pfourkillcount + playertwo.pfourkillcount + playerthree.pfourkillcount)

2 Likes