Is $ the same as 'default'?
Nope. Not even close.
Is this just a personal preference or a functional difference?
Some older games tend to initialize variables using
$
. Usually within an
You must be registered to see the links
(initialization block).
default
was added to RenPy later, and is why those older games didn't use it.
The problem being that later developers then copied that older code into more recent games. Good games don't always mean good programming. As a result, a lot of bad habits persist into modern RenPy games.
You must be registered to see the links
as already stated is pretty much "do single python command."
More importantly it is pretty much "do that single python command now."
As part of an
init
block, those commands (initializing the variables) ran during game startup.
Less commonly back then, developers would put those same commands in the main body of their script. Usually just after the
label start
. No harm done. The game would start, and the variables would be initialized (either in the main script or within the
init
block).
The problem is the developers add, remove or change the use of variables as they continue to develop their game.
Imagine a developer adds a new variable (
mynewvar
) as part of their episode 3 release, but related to code that happened in episode 1.
The logical place to initialize that variable would be with all the other ep1 variables (probably at either
label start
or the episode 1 script).
Except, you have players out there who are in the end of episode 2. Their save files don't include that variable, because it wasn't added until later. They haven't restarted the game or replayed episode 1, so the
$
code hasn't been run.
The player loads their ep2 save and starts to play through ep3 and encounters an
if mynewvar >= 1
statement. The game crashes, because as far as the game is concerned, that variable doesn't exist (critically, it wasn't loaded from the save file and the value hasn't changed since).
This was why
default
was added to RenPy.
It is a mechanism that initializes variables regardless of where in the code the
default
statement is placed. Most critically, it protects programmers from falling for this edge case bug for variables added to the script later. If the developer uses
default
, they'll never need to worry about whether the variable exists or not, because it always does.
If the script encounters a
default
statement while it is being executed - that statement is effectively ignored (because it's already been processed during game startup).
Want a really bad example?
Python:
label start:
scene black with fade
"*** START ***"
"The variable value is [mynewvar]."
$ mynewvar = 7
default mynewvar = 99
"The variable value is now [mynewvar]."
"*** THE END ***"
return
This works, because the
default
statement is executed during startup and not at run time.
It will print "99" and then "7".
As for the difference between
default
and
define
, others have already explained that
default
is for variables that change value while the script is running and
define
is for variables that don't (static variables).
It's probably worth explaining why.
(From my limited understanding): Anytime the value of a variable is changed during runtime execution of the script, there is some sort of flag for each variable to include that variable within the next save/autosave file. (think of it as "marked for saving").
define
doesn't set that flag.
default
does.
So when a player loads a save file, they get all the latest values of those variables for that playthrough, without making the save file huge by saving variables that will never change.
It also means that a developer can change a variable created using
define
and the player will see that new value and not the value when the player was previous playing.
Imagine something like
define maximum_lovepoints = 100
and the developer want so up that value to 120. If they'd used
default
, the player would load their save file and the value would be overwritten with 100. Not what the developer had in mind.
More commonly, it would be something more like changing the color of a character's name or something like that.
The explanation and reasoning why may be complicated, but the implementation is easy:
"use
You must be registered to see the links
for variables that might change and
You must be registered to see the links
for variables that almost never will".
"init blocks are the 'old' way of doing it".
Or put another way, "define is for constants and default is for variables".