Well, that's a big topic 🙂
When you define a variable in a script like tis:
variable x
That variable is only visible within that script file. It has a value for only as long as that script is running, then it's gone.
In programming, it's similar to what would be called a "local variable".
When you define a variable like this:
static variable x
The variable is only accessible within this script, however it will preserve it's value over multiple executions of the script. This is used when you want the script to maintain state for some reason, a simple and not particularly useful
example is counting the number of times the script is used.
static variable x
x = x + 1
print ("I've been called" x "times")
Allowing scripts to save state between runs is very useful, and sometimes you might want this variable to be accessible by other scripts besides the one in which it was defined. To do that it is declared public
public variable x
A public variable is also a static variable, meaning it will hold a value forever, and it may be accessed by any script.
But while a public variable can be used to pass information between scripts, it is not accessible from outside the script environment. It is only visible to other scripts. For certain variables, it is convenient to allow them to behave like what Mobius calls a parameter. A named thing you can see in the UI, and most importantly can change with a binding. To do that you declare it with export
export variable x
An exported variable is also public so other scripts can see it, and it is also static so it holds it's value.
Now this next part is something that is supposed to happen, but it's relatively new and I'm not entirely sure it is working at this moment. When you export an MSL variable it should look and feel like any built-in Mobius parameter like syncMode or subcycles. You can put it in the Instant Parameters list and see it in the UI, or you can change it from a binding. For example binding a MIDI continuous control knob to to the variable, then as you twist the knob, scripts that run "see" that value. The same could be done by binding the variable a host parameter, then you would see the value in the host application and could change it there with parameter automation or whatever else the host allows you to do with plugin parameters. This part is pretty advanced, and I could talk at length about it if someone is curious, but I'll leave it there for now.
So, what does track do? This one is kind of hard to describe without dragging in a bunch of programming language terminology, but think of it this way. A public or global variable has one value, and that value is shared by all tracks. If you run a script that uses a global variable, the value will be the same no matter which track you are running the script in. It is however quite useful for each track to maintain it's own collection of variables. That variable may have the same name, but the value of that variable will be different in each track.
One example of this is the system variable named "mode". One of the most common things to write in a script is this:
if mode == "Reset" Record
So where does the value of "mode" come from? Each track has something named "mode" but each track can be in a different mode, some may be in "Record" mode, some in "Reset" mode, etc. When you define an MSL variable like this:
public track variable x
It means that x will have an independent value in each track. This has lots of uses.