1
\$\begingroup\$

(2D Project) I have a very basic set-up in which I have a Hallway with a door and a bunch of other objects. I have a player that starts on the left side of the hallway and only moves on the x-axis. The player has a Box Collider 2D and a Rigidbody 2D. He has a script that allows him to move and within the script I have a method called "CheckEnterDoor()", which, if the bool "main" is true, > if you press e, unloads the hallway and its objects and loads a secondary room. If you press e while in the secondary room, the opposite happens, secondary room gets unloaded, main hallway gets loaded (they become invisible, atleast, I am not sure what technically happens to them [SetActive(false)]) enter image description here

I call this method from within a different script which, instead of being attached to the player, is attached to the door. The door has a Collider2D which is set to "Is Trigger", so that you can pass through it and use it as more of an "area of interactivity", atleast thats the way I am trying to use it. It just has the basic setup so that the door script can access the player script and then within "OnTriggerStay2D", which, the way I understood it, is supposed to be some sort of a "while(in_Collider2D_area)", I try to make it possible to open the door.

enter image description here

The issue comes up when I actually try to do this when playing the game. I gave the door a massive collider2d box and the player a very tiny one enter image description here

enter image description here

but pressing e while inside of the door box only works SOMETIMES. Sometimes while I'm walking towards it I'll press e and it works. Sometimes I'll do that exact same thing and it doesn't. Sometimes I need to move around a bit within the massive box while spamming e to make it work. I can always get it to work, but it seems to be completely random as to WHEN it actually works. I have seen people have similar-ish issues with this in some 2015 post, the suggested solution was to use a Kinematic OR Dynamic Rigidbody 2D Body Type instead of a static one, because that could apparently cause issues. My Rigidbody2D was set to Dynamic by default and the only option within it that I changed was the gravity so that the player wouldn't just fall through the floor. Using the Kinematic Body Type did not resolve the problem either, though. Another fix I saw was to put the Rigidbody 2D to "Never Sleep" mode, which I did, but it again did not change anything. I might not have been able to find a proper answer to this because I am unsure how to actually formulate my question or describe the issue without making it overly specific.

**I have used Debug.Log("blabla"); and it has continously given out a ton of messages into the console, meaning the Program seems to fully realise that I AM inside of that Collider2D box, yet will not let me execute the code. I am now thinking it might be a code problem instead of a box-dragging or rigidbody settings problem.

This is my first time posting here and also my first time working with Unity, if I need to send the project or full source code or anything like that somehow please let me know and I will do it.

\$\endgroup\$
2
  • \$\begingroup\$ Code should always be shared as correctly formatted text, not as images. \$\endgroup\$
    – DMGregory
    Feb 17 at 2:35
  • \$\begingroup\$ Please post code in text form and not as screenshots. This enables people to copy&paste your sourcecode into their answers, making it much easier for them to give you corrected code. \$\endgroup\$
    – Philipp
    Feb 17 at 8:51

1 Answer 1

1
\$\begingroup\$

I'm relatively new to Unity myself, but I think what's happening here is that GetKeyDown only returns true for the first frame in which it is pressed.

OnTriggerStay2D may not fire every frame, and/or it might be a different frame by the time Input.GetKeyDown executes. When you spam the key, you eventually get the timing right and hit a frame where Input.GetKeyDown is called during that first frame.

I'd suggest capturing any Input flags in the Update function which runs exactly once per frame. Compare to how the horizontal and vertical axes are captured in the Update function of the Ruby's Adventure tutorial.

  1. Introduce a bool isPlayerInDoor to your Movement, either as a public member or with a helper function like SetPlayerInDoor(bool).
  2. Instead of calling CheckEnterDoor from OnTriggerStay2D, instead use OnTriggerEnter2D and OnTriggerExit2D to update isPlayerInDoor. (Side note: this may not be relevant at the moment, but you may want to check that the colliding object is in fact your player!)
  3. Capture Input.GetKeyDown("e") in Movement's Update function, where it will reliably return true once and only once per press.
  4. You can move the code from CheckEnterDoor to the Update function, or you can call it from Update if you pass it the captured value from GetKeyDown. In either case, add a check for the new isPlayerInDoor bool, which will be true from entrance to exit of the trigger.

Hope this helps. Tangentially, you may also consider GetButtonDown over GetKeyDown. GetButtonDown opens the door (no pun intended) to using Input Manager to support players who want to reconfigure keys.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Yes, thank you, this worked. In case anyone has a similar issue and manages to find this post, I will post the corrected code here: In Update: CheckEnterDoor(PlayerInDoor); after adding a bool parameter called inRange to the CheckEnterDoor method and "wrapping" a if (inRange == true) { around the entire method. My previous OnTriggerStay2D has been replaced by a OnTriggerEnter2D which sets PlayerInDoor = true and a OnTriggerExit2D which sets PlayerInDoor = false. Also I am having a hard time formatting this comment because pressing enter posts it. Sorry. \$\endgroup\$ Feb 17 at 12:37

You must log in to answer this question.

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