0
\$\begingroup\$

I need to access a variable from another script in Unity, but I can't figure it out. Script:

public class move : MonoBehaviour {
public float speed;
// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {
    transform.position += Vector3.left * Time.deltaTime * speed;
}

}

I want to access the variable speed in another script, but I can't. Any help will be appreciated :)

\$\endgroup\$

4 Answers 4

6
\$\begingroup\$

If both scripts are on the same GameObject, you can use this

gameObject.GetComponent<move>().speed

This will access the given variable, in this case speed.


If the scripts are on different GameObjects you can do this :

GameObject.Find("nameOfObjectYourScriptIsOn").GetComponent<move>().speed

and you should have access to the variable speed.

Note : You need to replace nameOfObjectYourScriptIsOn with the name of the GameObject you have attached the move script to.

\$\endgroup\$
1
  • \$\begingroup\$ If you have just one object with a move script, FindObjectOfType<move>() is a better alternative, since it does a single search instead of two, and won't break if you change an object's name. \$\endgroup\$
    – DMGregory
    Commented Aug 3, 2020 at 13:23
3
\$\begingroup\$

Basically it is somehow different in Unity. In Unity most of the work and scripts are attached to any GameObject to make it work through MonoBehaviour. In other words you cannot be able to execute Monobehaviour's messages like Start, Update if that script is not attached to any GameObject.

So the way would be change little bit. You must have to get the very same instance that is dropped to any GameObject otherwise you may get no error but also get no change.

For this purpose I second the first part of Biix's answer, if you have both scripts attached to same GameObject then you can use GetComponent

// In script other than move
move _move = GetComponent<move>();
_move.speed = 10;

But if scripts are attached to two different GameObjects then you can use FindObjectOfType, by this you don't have to worry about the name of the GameObject on which your script is attached.

// In script other than move and also on different Game Object
move _move = FindObjectOfType<move>();
_move.speed = 10;
\$\endgroup\$
1
\$\begingroup\$

What you need are getters and setters. Basically it is a way of getting and/or setting variables in classes (or scripts in this case) from external code. There are many ways that you can do this:

Automatic get and set

By changing the code to the code below you are making the variable available to the outside classes (public get;) but those classes can't change the variable. Which you might want so you don't change it be accident.

[SerializeField]
private float InspectSpeed;

public float speed { get; private set; }

void Start () {
    speed = InspectSpeed;
}

So you might notice this is a lot of code, Yes.... It is. While automatic setters and getters are awesome for variables you want to share between classes/scripts the inspector won't allow you to use them (which is why i assume speed is public) so I added an extra float which is visible to the inspector. Since this is then not the same as speed you need to set it at startup.

To then access the speed variable you simply get it from the instance of the class:

move.speed;
//note you won't be able to change the variable as the setter is private

Manual getter

You could just add a method which has a return value of float which then always returns the variable of speed. When every you need speed just call the method

Public float getSpeed(){
    return speed;
}

so from another script/class you would call:

move.getSpeed();
//returns the speed

Making the variable public (not recommended)

You have already done this in the code sample that you provided. You declared the speed variable as public meaning that all scripts can just call the variable from anywhere. I suspect you did this to make it visible in the inspector (we have all done it at some point :)).

The problem with this is that as you add more and more variables to scrips that you want to be changeable in the inspector it becomes harder and harder to work with the code as you add more scripts. This is because when you need to call methods in other classes or scrips it will show every public variable as well as all the other public methods that you have. Sooner or later you will have 2 variable of the same name at which point it will be vary confusing which variable you are getting if you are getting data of the same name from multiple sources.

To fix this make every variable private and add "[Serializable]" above it which will prevent other classes/scripts from seeing it but the inspector will still be able to interact with it.

And just for the completion of this point you access the speed variable like this:

move.speed;

This should cover everything, if it doesn't work for whatever reason comment bellow :)

\$\endgroup\$
3
  • \$\begingroup\$ Does this really work if the variables are in separate C# files though? Won't you need to "Get" (GetComponent) the script before trying to use it? \$\endgroup\$
    – BiiX
    Commented Mar 19, 2016 at 18:47
  • \$\begingroup\$ Sorry, it didn't work. I kept getting an error message saying an object reference is required. \$\endgroup\$ Commented Mar 19, 2016 at 19:19
  • \$\begingroup\$ well you need to have an stance of the class so it knows were to get the value from (in theory you could have the move script attached to multiple items). Try to use a new global variable: "public move script" and replace were I said "move" in the examples with "script" then drag the script you want the speed off into the script area in the inspector. \$\endgroup\$ Commented Mar 21, 2016 at 15:37
1
\$\begingroup\$

I guess you are being down-voted for the question being simple to find online but a way that I have been using is the following:

public class TargetGameObject : MonoBehavior {

    public Move move;
    int vel = 0;
    ....

    void Update(){
        vel += move.speed;
    }
    //Use move.speed however you want once the game object is linked in the inspector.

You link the item in the GameObject inspector by dragging the GameObject with your move script attached. I would also recommend using camel-case for all class names. It is just good practice.

The other answers will work as well such as using FindObjectByName, GameObject.Find, etc but searching through all GameObjects if you have a fairly large game can be intensive on performance.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .