(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.
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;