Same variable across two different scripts.

I’m pretty new to scripting, and I have a question about variables.
If I have a bool variable in one script, is there a way for me to reference/access from another script?

I’m asking because I have two scripts. One is a simple cursor lock script (I’ll call it Script 1)

using UnityEngine;
using System.Collections;

public class CursorLock : MonoBehaviour
{

    void Start()
    {
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
    }
    void Update()
    {
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
    }
}

The other is basically a script that makes a dialog screen pop up when you press “e” and are near the person. (Script 2)

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class DoorScript : MonoBehaviour {


   // Use this for initialization
   void Start () {

  }

  // Update is called once per frame
  void Update()
  {
  bool lockOutOf;

  float mainChar;
  mainChar = GameObject.Find("MainChar").transform.position.x;

  if ((mainChar <= -153.6f & mainChar >= -771.6f) & (Input.GetKey(KeyCode.E)))
  {


  GameObject.Find("DialogScreen").transform.localScale = new Vector3(1, 1, 1);
  lockOutOf = false;

  }

  if ((mainChar > -153.6f & mainChar < -771.6f))
  {
  GameObject.Find("DialogScreen").transform.localScale = new Vector3(0, 0, 0);
  lockOutOf = true;
  }


  }
}

Is there anyway I could reference lockOutOf (the bool in script 2) and use it in Script 1, so that when lockOutOf = true, the cursor is locked, and when lockOutOf = false, the cursor is unlocked?

Sorry if this didn’t make much sense. If it didn’t, my question is basically how can I make the first if statement in script 2 unlock the cursor, and the second if statement lock the cursor.

Yes, just make it

public bool lockOutOf;

Then you can literally just type

lockOutOf = false;

In your other script :slight_smile:

Also,
In Script1, ii’d remove the code in Start as it’s already in Update to avoid confusion :slight_smile:

Ok, I’ll try that. thanks for the help!

You’re probably going to requireDoorScript.lockOutOf = false; in the other script actually :stuck_out_tongue:

Okay, so in script #2 I changed the “bool lockOutOf” to “public bool lockOutOf”, and I got about 100 compile errors.
Then I tried moving “public bool lockOutOf” to the 7th line, under “public class DoorScript : MonoBehaviour {”
This made the compile errors go away, but then when I tried using it in script #1. The code I wrote is below.

using UnityEngine;
using System.Collections;

public class CursorLock : MonoBehaviour
{


    void Start()
    {

    }
    void Update()
    {

        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;

        if (lockOutOf = false)
        {
            Cursor.lockState = CursorLockMode.None;
        }
        if (lockOutOf = true)
        {
            Cursor.lockState = CursorLockMode.Locked;
        }

    }
}

But when I do this, I get two errors, one for each time I use lockOutOf. They say that "the name lockOutOf does not exist in the current context. So what am I doing wrong now? lockOutOf is a public variable, so script 1 should be able to use it, right??

@eclolev’s script isn’t quite as straightforward as he’s making it seem. In order to access script 1 from script 2 you need a reference to it, and he doesn’t do that. @Jamster is closer, but the syntax needs to be: “public static bool lockOutOf;” in your cursor script, and then any script can access it using “CursorLock.lockOutOf = true;”. A note of caution: this is usually only a good way to go about it if there is one and only one of the thing in the scene. Cursor lock out is exactly such a situation, so it’s good for this case. Incidentally, it would also be good for your dialog box - more on that in a second.
(edit: there’s a lot more, but I wanted to post this immediately since there’s still this whole conversation with bad advice happening as I type it)

1 Like

Ahhh yeah… It’s one of those days :sweat_smile:

Ok, I followed your suggestions and it stopped the compiling errors, but the script just doesn’t work now. So if you don’t mind, I’ll just post the whole script, and you can tell me how to fix it if you can.

Script 1 (CursorLock): Supposed to lock the cursor, and then lock/unlock it depending on whether lockOutOf is true or false.

using UnityEngine;
using System.Collections;

public class CursorLock : MonoBehaviour
{

    public static bool lockOutOf;

    void Start()
    {

    }
    void Update()
    {

        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;

        if (lockOutOf = false)
        {
            Cursor.lockState = CursorLockMode.None;
        }
        if (lockOutOf = true)
        {
            Cursor.lockState = CursorLockMode.Locked;
        }

    }
}

Script 2 (DoorScript): Is supposed to make a GUI appear if the player is in a certain area (near the person that they’re talking to), and pressed the “e” key. I also supposed to set lockOutOf to true or false, depending on whether or not the player is near the person they’re talking to or not.

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class DoorScript : MonoBehaviour {

    public static bool lockOutOf;


    // Use this for initialization
    void Start () {

}

    // Update is called once per frame
    void Update()
    {


        float mainChar;
        mainChar = GameObject.Find("MainChar").transform.position.x;

        if ((mainChar <= -153.6f & mainChar >= -771.6f) & (Input.GetKey(KeyCode.E)))
        {


            GameObject.Find("DialogScreen").transform.localScale = new Vector3(1, 1, 1);
            CursorLock.lockOutOf = false;

        }

        if ((mainChar > -153.6f & mainChar < -771.6f))
        {
            GameObject.Find("DialogScreen").transform.localScale = new Vector3(0, 0, 0);
            CursorLock.lockOutOf = true;
        }


    }
}

I don’t know if this matters or not, but here’s what’s in the actual game. Hopefully this won’t overcomplicate things, if it does just ignore it.
I have the player, who’s called “MainChar”. he’s just a sprite with a 2d collider, a movement script, and a rigidbody. The CursorLock script is also attached to him, since I didn’t know where to put it. The Main Camera is a child of his, so that it follows him around.
I have two seperate canvases, one is in world space and contains an image that when clicked, makes another image appear.
The GUI that appears is a child of the second canvas, which is in the screen space. The child of this, the GUI that appears, is an image called “DialogScreen”
Hopefully this helps a little, if not just ignore it.

Again, I’m sorry if my coding is just completely wrong, or if I’m missing some super basic stuff, but I just started coding a week or two ago. So if you guys could help me, I’d really appreciate it. And sorry for the long posts. I’m not great at explaining this stuff.

(continued from my last post) The static variable will work just fine as long as there is one and only one door in your game. This seems like an unlikely proposition. :slight_smile: However, let’s say you add a second door. Do you want them to be fighting over whether the cursor should be locked or not? Because that’ll happen.

First, let’s talk about those numbers in your door script. That’s called “hard-coding”, and it’s bad. It guarantees that you won’t be able to re-use that door script for any other door. So, let’s replace those numbers with public floats that you will be able to modify in the door’s Inspector view:

public float minInteractionPositionX = -771.6f;
public float maxInteractionPositionX = -153.6f;

....
if (mainChar >= minInteractionPositionX && mainChar <= maxInteractionPositionX && Input.GetKey(KeyCode.E) ) {

You should also rename mainChar to a more descriptive name like mainCharXPosition, but I’m not gonna do that just now (you’ll see why towards the end of the post).

Instead, I think you should use the concept of separating your GUI from your main functionality. The general principle is this: Your in-game objects should not be aware that the GUI even exists. They expose the information the GUI needs, but all the work that the GUI needs is done by the GUI, not by the objects. If you completely scrap your GUI and rebuild it, you should ideally not be required to change a single line of your in-game objects’ code in order to do so.

So how can we make the GUI behave correctly in this scenario? By having it keep a reference to the player. In this case, we can use something called a singleton. So you now know how you can have a static variable, and you cna have variables that point to objects? Let’s combine those concepts, and have a static variable that points to the one instance of the object in the scene:

public static Player playerInstance;
void Awake() {
playerInstance = this;
}

Put this code in the script that controls your player. Now, anytime any script wants to do anything with your player object, you can access it using Player.playerInstance. An example will come in a second.

So what does this have to do with your door and cursor lock-out? Well, when your player comes across a door, right now your door directly modifies the UI. But, conceptually, what we want the UI to be displaying is “Whatever the player is interacting with right now.” So we want the player itself to know what it’s interacting with right now. And that is the door will modify.

So let’s add a public variable to the Player script:

public DoorScript interactingWithDoor = null;

Most of the time, this variable will be null, meaning the player is not interacting with a door. However, when the player walks up and presses E, the door will tell the player, “hey, player, you’re interacting with me now!”:

if (Player.playerInstance.transform.position.x >= minInteractionPositionX && Player.playerInstance.transform.position.x <= maxInteractionPositionX && Input.GetKey(KeyCode.E) ) {
Player.playerInstance.interactingWithDoor = this;
}
if (Player.playerInstance.interactingWithDoor == this && (Player.playerInstance.transform.position.x < minInterationPositionX || Player.playerInstance.transform.position.x > maxInteractionPositionX) ) {
Player.playerInstance.interactingWithDoor = null;
}

(Being able to access the component itself is the strength of a singleton over just static variables. That’s how we’re able to access the Transform attached to it, and get its position directly.)

So what this does: If the player walks up to the door and presses E, the door tells the player “Hey! It’s me! I’m the one you’re interacting with!”. If the player then walks away from that door, the door sets this to null, but only if that same door is the one the player was interacting with (which is the reason to do this instead of a simple bool). If some other door was being interacted with, it’ll leave it alone.


So now that we have well-structured data, we are finally ready to hook the GUI into it. On your cursor locking code, you can simply put this:

if (Player.playerInstance.interactingWithDoor != null) {
//cursor is locked
}

Now your GUI is responsible for your GUI, and the player script doesn’t need to worry about it. More importantly, the doors don’t need to fight over it. Your dialog screen should have the same logic on it, and make itself appear and disappear. Bonus: Your door scripts can even have your own variables on it that your dialog box can easily access (e.g. a customizable message that appears that’s different for every door you open) - simply make that a public string variable on the door, and your dialog box can access it like so:

someTextObject.text = Player.playerInstance.interactingWithDoor.customMessage;
1 Like

I’m in the process of reading your whole post, and changing the code according to it. Thank you so much for the help, I really appreciate it. I think I might be able to get the script to work now, so thank you.

And just to be clear, in your post when you say “Player”, should I change that to the name of MainChar’s movement script? Or is that referencing the actual player (in which case I should replace it with “MainChar”)?
Or should I just leave it as Player? When I did that (left it as Player) I got a ton of compile errors, so I’m just wondering what that is referring to.

[edit]: Here are all the names of the objects in the game, if it helps any.

The sprite that the player controls is called “MainChar”. His movement script is called “PlayerMovement”. The canvas that is in the object space, and holds the door that you press “e” near to get the dialog, is called “InGameChat”. It’s child is an image called “Door”, which is supposed to make the dialog appear when you press “e” near it. The canvas that contains the actual dialog is called “FullScreenGUI”, and it’s in the screen space. It’s child is “DialogScreen”, which is an image that is supposed to appear when you press “e” near “Door”. Again, sorry if this confused, just trying to help.

Whatever the name of the script that is on your main character - looks like it should be PlayerMovement.

1 Like

Sorry to keep bothering you, I probably shouldn’t have tried to write something this difficult so early on. But everything besides the door script is compiling. The door script has errors pretty much all over this part:

       if (PlayerMovement.playerInstance.transform.position.x >= minInteractionPositionX && PlayerMovement.playerInstance.transform.position.x <= maxInteractionPositionX && Input.GetKey(KeyCode.E) )
        {
        PlayerMovement.playerInstance.interactingWithDoor = this;
        }
        if (PlayerMovement.playerInstance.interactingWithDoor == this && (PlayerMovement.playerInstance.transform.position.x<minInterationPositionX || PlayerMovement.playerInstance.transform.position.x> maxInteractionPositionX) )
        {
        Player.playerInstance.interactingWithDoor = null;
        }

Any idea what’s wrong here? This honestly has gotten to complicated for me to understand. I’m not really sure where to even start editing it to make it work, so I might just start from scratch with all the new stuff, and try and write it that way. But if you have anything that could help me, I’d be glad to hear it.

What are the actual errors?

Often if there are clusters of a bunch of errors, the problem is a mismatched parenthesis or bracket, so check for those. (It’s possible I had one in the code I typed, I didn’t test it before posting it)

1 Like

It’s 64 errors, I doubt you want to go through all of them. And I’m pretty sure it’s not a bracket or a parenthesis, I’ve triple checked it. I think I might know what’s wrong, going by the error statements. I’ll try my best to explain it, I don’t know if I’m right but this seems to be what the 64 errors are sayings. And I’m not trying to insult your coding or anything, just saying what it looks like is wrong. Anyways…

Most of the errors are “does not exist in current context errors”. For example, “x”, “transform”, or “position” “does not exist in the current context”. I think the replacing “mainChar” with “PlayerMovement.playerInstance” might have messed something up. If I’m understanding this whole thing right, playerInstance doesn’t have a transform, a position, or an x value so that’s why it’s not working. Again, not really sure, and that’s only part of the problem.
[edit]: I also thing there’s something wrong with this line, in the first if statement.

PlayerMovement.playerInstance.interactingWithDoor = this;

this line doesn’t work, but in the line a few lines down, in the second if statement it’s the same except instead of “this” it says “null”

PlayerMovement.playerInstance.interactingWithDoor = null;

I don’t know what the problem is exactly, but “this” isn’t in Visual Studio’s suggested words thing.

So yeah, I don’t really know what the problem is, there’s just too many errors. So I’m just gonna start from scratch. If it’s not too much trouble for you to just try writing the whole code, since I probably just made an error when I was putting your coding ideas into the script. Or, if you just don’t feel like doing anything, that’s fine. You’ve already helped a ton, so if you don’t want to do any more that’s perfectly fine. But if you do have an idea of why it could be getting errors, I’d like to know.

OK, so the problem is probably that you’ve used the wrong name for the player script. “PlayerMovement” should be whatever the name of the player’s class in the script is (which should be the same as the name of the .cs file for the script).

If that is what the name is (to your understanding), select the player object in the editor, take a screenshot, and post it here - that should help.

1 Like

Ok here’s a screen shot of the hierarchy, and the main character in the inspector.

The code that’s going wrong is in another gameObject called “door” (you can see it in the hierarchy) I can take a screenshot of that in the inspector if you want, but that’s not the player script you were talking about. The player script is PlayerMovement.

2336163--157899--Screenshot.png

‘this’ is a keyword that refers to the specific object on which the code is being run. It’s usually implicit - for example, “this.transform.position” is the same as “transform.position”.

OK, can you paste in the relevant code from PlayerMovement.cs?

1 Like
using UnityEngine;
using System.Collections;
public class PlayerMovement : MonoBehaviour
{

    public float speed = 200f;//walk speed
    public float sprint = 300f;//sprint speed
    public DoorScript interactingWithDoor = null;

    public static PlayerMovement playerInstance;
    void Awake()
    {
        playerInstance = this;
    }

There’s more to it, but the rest is just the script that moves the sprite when you press the movement keys. I didn’t change that part, and it’s not really relevant.
Here’s the rest of the relevant code, now that you know pretty much know everything that’s going on.

CursorLock:

using UnityEngine;
using System.Collections;

public class CursorLock : MonoBehaviour
{

    public static bool lockOutOf;

    void Start()
    {

    }
    void Update()
    {

        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;

        if (PlayerMovement.playerInstance.interactingWithDoor != null)
        {
            Cursor.lockState = CursorLockMode.None;
        }
        if (PlayerMovement.playerInstance.interactingWithDoor != this)
        {
            Cursor.lockState = CursorLockMode.Locked;
        }

    }
}

DoorScript(errors underlined):

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class DoorScript : MonoBehaviour {

  public static bool lockOutOf;


  // Use this for initialization
  void Start () {

  }

  // Update is called once per frame
  void Update()
  {
  public float minInteractionPositionX = -771.6f;
  public float maxInteractionPositionX = -153.6f;

  float mainChar;
  mainChar = GameObject.Find("MainChar").transform.position.x;

  if (PlayerMovement.playerInstance.transform.position.x >= minInteractionPositionX && PlayerMovement.playerInstance.transform.position.x <= maxInteractionPositionX && Input.GetKey(KeyCode.E))
  {
  PlayerMovement.playerInstance.interactingWithDoor = this;
  }
  if (PlayerMovement.playerInstance.interactingWithDoor == this && (mainChar.transform.position.x<minInteractionPositionX || PlayerMovement.playerInstance.transform.position.x> maxInteractionPositionX))
  {
  PlayerMovement.playerInstance.interactingWithDoor = null;
  }
  }
 

    
}

Again, I totally understand if you don’t feel like doing all this. But if you do, It would really help.