Extracting text from a string for use as a variable?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Dumuz

Is there a way to extract original text from a string?
I’d like to pass a string to another script, but for that script to take the name in the string as if it were one of it’s global variables.

Example;

Script 1:

func _set_parameters():
     var outcome
     if test = true:
            outcome = "alive"
     else:
          outcome = "dead"
     $other_script._testing_for(outcome)

Script 2:

var alive = "I live!"
var dead = "I'm not alive!"

func _testing_for(incoming # Would like for this to be interpreted without the quotation marks from the first script.):
     print(incoming)

This way I don’t have to assign each possible string to a variable.

:bust_in_silhouette: Reply From: jgodfrey

You can certainly pass a string argument from one script another. And, pretty much exactly as you outline above.

The only real trick is that you need to have access to the node that contains the other script.

For example, this should work as expected:

Tree

- Node2D
  - Sprite

Script on Node2D

_ready():
    $Sprite.print_me("My string")

Script on Sprite

func print_me(input):
    print(input)

That’ll print My string

Is that what you’re trying to do?

Also, for clarity, the original string can be stored in a variable…

var my_string = "A new string"
$Sprite.print_me(my_string)

That’ll print A new string, as expected…

jgodfrey | 2020-02-18 16:45

:bust_in_silhouette: Reply From: Bernard Cloutier

Let’s see if I understand: you want to use the content of the incoming parameter to select the variable to print, but without explicitly checking it (ie: if incoming == "alive": print(alive) elif incoming == "dead" ...), right? You can use index notation to access a variable’s content with a string, like this:

var myVar = "Hello world"

func _ready():
    var stringToPrint = self["myVar"]
    print(stringToPrint)

Your script 2 would end up like this:

var alive = "I live!"
var dead = "I'm not alive!"

func _testing_for(incoming):
     print(self[incoming])

However, if you feel the need to access different variables by string, it usually indicates that what you want is a dictionary. Here’s what that would look like:

var states= {
    "alive": "I live!",
    "dead": "I'm not alive!"
}

func _testing_for(incoming):
     print(states[incoming])

You can add a check to see if the key exists in the dictionary before accessing it (if states.has(incoming): ...), since accessing a value that doesn’t exist will throw an exception, but sometimes you want the game to crash immediately while developping so you can catch errors sooner (ex: the caller shouldn’t call _testing_for with a value that doesn’t exist.

An improved version would use something like an enum for keys:

enum States {
    alive,
    dead
}
var states= {
    States.alive: "I live!",
    States.dead: "I'm not alive!"
}

func _testing_for(incoming): #incoming must be one of States enum
     print(states[incoming])

You would call _testing_for from another scripts like so:

func _set_parameters():
     var outcome
     if test = true:
            outcome = $other_script.States.alive
     else:
          outcome = $other_script.States.dead
     $other_script._testing_for(outcome)

Using an enum means you can more clearly define what values can be passed to your function and makes it less likely that you’ll make typos in your strings.

Looks like making a dictionary was what I needed to do. I appreciate the run down on enums too. I haven’t tried using either of those methods yet, until now. The doc’s make it look much more intimidating than it is.

Thank you!

Dumuz | 2020-02-18 17:18

:bust_in_silhouette: Reply From: Dumuz

Been a while since I looked back at some of my questions. Decided to answer with what I was actually looking for at the time (To be fair; the way I asked was terrible as I was a complete noob to scripting):

Use the get() method

Script 1:

func _set_parameters():
     var outcome
     if test == true:
            outcome = "alive"
     else:
          outcome = "dead"
     $other_script._testing_for(outcome)

Script 2:

var alive = "I live!"
var dead = "I'm not alive!"

func _testing_for(incoming):
     print(get(incoming)) # Will print either "I live!" or "I'm not alive!" depending on incoming equaling either "alive" or "dead" respectively.