Home > Software engineering >  Unity 2D. Why both possible actions are triggered by pressing button?
Unity 2D. Why both possible actions are triggered by pressing button?

Time:03-24

I'm trying to make it possible to close and open door while player is colliding with door opener. But it just do both - opens and closes by pressing E key. What seems to be the problem?

{
    
    bool DoorTriggered = false;
    bool DoorClosed = true;
    [SerializeField] private DoorOpener door;
    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.E) && DoorTriggered && DoorClosed)
        {
            door.OpenDoor();
            DoorClosed = false;
        }
    
        if (Input.GetKeyDown(KeyCode.E) && DoorTriggered && !DoorClosed)
        {
            door.CloseDoor();
            DoorClosed = true;
        }

    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.TryGetComponent(out PlayerScript _player))
        {
            DoorTriggered = true;
        }
    }
    private void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.TryGetComponent(out PlayerScript _player))
        {
            DoorTriggered = false;
        }
    }
}

CodePudding user response:

Your code is running from top to bottom. It starts by running the first line, to the second, and so on. You are checking if the door is closed and then opening it, and then on the next line you are checking if it is open, and then closing it. This causes the door to open and then close.

Solution: You could easily swap the two if statements' places, although it would probably cause some errors. Rather than simply swapping the two, we can use an if-else statement to ensure that you get the solution you need.

{
    
    bool DoorTriggered = false;
    bool DoorClosed = true;
    [SerializeField] private DoorOpener door;
    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.E) && DoorTriggered && DoorClosed)
        {
            door.OpenDoor();
            DoorClosed = false;
        }
    
        else
        {
            door.CloseDoor();
            DoorClosed = true;
        }

    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.TryGetComponent(out PlayerScript _player))
        {
            DoorTriggered = true;
        }
    }
    private void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.TryGetComponent(out PlayerScript _player))
        {
            DoorTriggered = false;
        }
    }
} 

CodePudding user response:

This answer explains the issue - your code runs from top to bottom so after the first code block is executed you enter the second condition as well.

However, it is still error prone.

What you actually should rather do is using if - else to call your code blocks exclusively like

private void Update()
{
    if (Input.GetKeyDown(KeyCode.E) && DoorTriggered)
    {
        if(DoorClosed)
        {
            door.OpenDoor();
            DoorClosed = false;
        }
        else
        {
            door.CloseDoor();
            DoorClosed = true;
        }
    }
}

or also

private void Update()
{
    if (Input.GetKeyDown(KeyCode.E) && DoorTriggered)
    {
        if(DoorClosed)
        {
            door.OpenDoor();
        }
        else
        {
            door.CloseDoor();
        }

        DoorClosed = !DoorClosed;
    }
}
  • Related