Home > Back-end >  Unity script fields - unique to each instance?
Unity script fields - unique to each instance?

Time:12-20

I'm creating a message system for my Unity game. I have this script, TouchPlayer attached to objects which the player can interact with. I can then just edit the MyTextArea field in the editor for each object instance.

It's not performing exactly as I expect it should. For example:

If I have 2 objects with this script, I can trigger the collision with one, press X, and the message displays. I leave the collision zone, go to the other object, and the other object's message already displays (without the prompt, PRESS X). Why is this?

public class TouchPlayer : MonoBehaviour {

    [TextArea] public string MyTextArea;
    [SerializeField] GameObject Player;
    [SerializeField] GameObject UIMessageBoxGroup;
    [SerializeField] GameObject MessageBox;
    public TMP_Text messageTextBox;

    bool showMessage = false;
    bool collided = false;

    void Start() {
      UIMessageBoxGroup.SetActive(false);
    }

    void Update() {
      if (Input.GetKey(KeyCode.X)) {
        showMessage = true;
      }

      if (collided) {
        if (showMessage) {
          messageTextBox.text = MyTextArea;
        } else {
          messageTextBox.text = "PRESS X";
        }
      }

      transform.LookAt(Player.transform.position);
      transform.Rotate(0, -90, 0);
    }

    void OnTriggerEnter(Collider other) {
      if (other.gameObject.CompareTag("Player")) {
        collided = true;
        UIMessageBoxGroup.SetActive(true);
      }
    }

    void OnTriggerExit(Collider other) {
      if (other.gameObject.CompareTag("Player")) {
        collided = false;
        showMessage = false;
        UIMessageBoxGroup.SetActive(false);
      }
    }

}

CodePudding user response:

Well on each instances in Update you do

if (Input.GetKey(KeyCode.X)) 
{ 
    showMessage = true; 
}

this is done for all the instances simultaneously! ;)

=> Even for all instances where you never did collide with the showMessage stays true forever. So as soon as you collide with one of these you immediately handle the if(showMessage) case.

You would want to make sure input isn't even handled at all as long as you didn't collide yet:

void Update() 
{
    // If not collided do absolutely nothing
    if(!collided) return;

    if (Input.GetKey(KeyCode.X)) 
    {
        showMessage = true;
    }

    messageTextBox.text = showMessage? MyTextArea : "PRESS X";

    transform.LookAt(Player.transform.position);
    transform.Rotate(0, -90, 0);
}

CodePudding user response:

I think the the problem is you are setting collided = false; in the ontrigger exit.

void OnTriggerExit(Collider other) {
  if (other.gameObject.CompareTag("Player")) {
    collided = false;
    showMessage = false;
    UIMessageBoxGroup.SetActive(false);
  }
}

So the messageTextBox.text = "PRESS X"; will never be reached, so you are not achieving the default state you are after.

if (collided) { //this will be false
    if (showMessage) {
      messageTextBox.text = MyTextArea;
    } else {
      messageTextBox.text = "PRESS X";
    }
  }

So you need to reset the state in the OntriggerExit :

void OnTriggerExit(Collider other) {
  if (other.gameObject.CompareTag("Player")) {
    collided = false;
    showMessage = false;
    UIMessageBoxGroup.SetActive(false);
    messageTextBox.text = "PRESS X"; //set the default state
  }
}

Or incorporate the collided condition to your update, so that the state is updated when collided is false:

if (showMessage && collided) {
  messageTextBox.text = MyTextArea;
} else {
  messageTextBox.text = "PRESS X";
}
  

CodePudding user response:

If I add showMessage = false; to OnTriggerEnter(), it works.

I assumed it would already be false when the variable is initialised (bool showMessage = false;), but apparently not...?

  • Related