[SOLVED] Playing door open animation on button press and other condition?

I am writing a door open script that detects if the player is near the door, displays a UI text if so, and then allows the player to press a button to open the door, which should then stay open for a few seconds and play the closing animation.

I have most of this working, but now I am stuck trying to figure out how to play the animations. I have already made two animation clips; one for open and one for close. Can someone help me figure out how to play the open animation, wait a few seconds, and then play the close animation?

using UnityEngine;
using System.Collections;

public class doorScript : MonoBehaviour
{
//box collider to see if player is near the door
     public Collider theCollider;
//canvas with text that reads "Press R to open"
     public Canvas doortext;
     public bool doorisClosed;

     void Awake ()
     {
          theCollider = GetComponent <BoxCollider> ();
          doortext = doortext.GetComponent<Canvas> ();
          doortext.enabled = false;
     }

     void Update ()
//if the door text is enabled and the player presses R, go to changeDoorState
     {
          if (doortext.enabled == true && (Input.GetKeyDown(KeyCode.R)))
          {
               changeDoorState();
          }
     }

     void changeDoorState ()
//this is the part I need help with.
     {
          if (doorisClosed == true)
          {
               //play the open animation
               doorisClosed = false;
               //wait for () seconds
               //play the close animation
               doorisClosed = true;
          }
     }
//checks to see if the player is in the collider, and displays the door text if so
     void OnTriggerEnter(Collider other)
     {
          if(other.gameObject.tag == "Player")
          {
               doortext.enabled = true;
               Debug.Log("player detected");
          }
     }
//checks to see if player has left the collider, and disables door text if so
     void OnTriggerExit(Collider other)
     {
          if (other.gameObject.tag == "Player")
          {
               doortext.enabled = false;
               Debug.Log("player left");
          }
     }
}

You can use “OnTriggerExit” function to close the door or if u want to wait for some time use coroutine

1 Like

I will most likely need to use the coroutine as this same mechanic is going to translate into some other features for which i’ll need to be able to use WaitForSeconds.

The part I’m having the trouble with the most is just playing the animation. On line 34, i’m just not sure how to type that I want to play a certain animation clip.

Update your code with bellow code

void Update ()
//if the door text is enabled and the player presses R, go to changeDoorState
{
      if (doortext.enabled == true && (Input.GetKeyDown(KeyCode.R)))
      {
           StartCoroutine("changeDoorState");
      }
}
IEnumerator changeDoorState ()
{
    //play the open animation
    //>>>>>>>>>>>>>>>>>>>Add Open animation line here<<<<<<<<<<<<<<<<<<<
   
    //wait for () seconds
    yield return new WaitForSeconds(10);
  
    //play the close animation
    //>>>>>>>>>>>>>>>>>>>Add Close animation line here<<<<<<<<<<<<<<<<<<<
       
}
2 Likes

Thank you again; I think this has me 90% of the way there, but I’m still having trouble playing the animations. Most of this script is based off of a tutorial I found which uses JavaScript, which I know nothing about. I converted the bulk of that script into C# the best I can with my limited understanding, but it seems that I’ve had to add quite a few things to get the same functionality so far. I’m guessing that JavaScript doesn’t necessarily need to use a coroutine for some reason?

On line 32 and 37, I am being told I need an object reference, which is no suprise, but I’m not sure how I should be implementing that. I don’t have the animation clips currently attached to anything; could someone help point me in the right direction on how to implement them? I tried putting them in an animator on the door itself, but the animator wants to use either the open or close animation as the default state, when really I want the default state to just be static.

How do I get the animations to actually play by script and if I do need to associate the animations with an object, what would be the best way to go about that?

using UnityEngine;
using System.Collections;

public class doorScript : MonoBehaviour
{
//box collider to see if player is near the door
     public Collider theCollider;
//canvas with text that reads "Press R to open"
     public Canvas doortext;
     public bool doorisClosed;

     void Awake ()
     {
          theCollider = GetComponent <BoxCollider> ();
          doortext = doortext.GetComponent<Canvas> ();
          doortext.enabled = false;
     }

     void Update ()
     { //if the door text is enabled and the player presses R, start coroutine
          if (doortext.enabled == true && (Input.GetKeyDown(KeyCode.R)))
          {
               StartCoroutine ("changeDoorState");
          }
     }

     IEnumerator changeDoorState ()
     {
          if (doorisClosed == true)
          {
               Animation.Play("doorOpen");
               door isClosed = false;
              
               yield return new WaitForSeconds (5);

               Animation.Play("doorClose");
               door isClosed = true;
          }
     }
//checks to see if the player is in the collider, and displays the door text if so
     void OnTriggerEnter(Collider other)
     {
          if(other.gameObject.tag == "Player")
          {
               doortext.enabled = true;
               Debug.Log("player detected");
          }
     }
//checks  to see if player has left the collider, and disables door text if so
     void OnTriggerExit(Collider other)
     {
          if (other.gameObject.tag == "Player")
          {
               doortext.enabled = false;
               Debug.Log("player left");
          }
     }
}

Ok I figured this out. Or at least figured out a way to make it work. What I did was create a third animation for the door where I just didn’t animate the door at all and called it doorIdle. I put this on an animator controller and attached that to the animator on the door. I then dragged my doorOpen and doorClose animation onto the animator controller and did not set up any transitions or anything.

Once that was set up on the door, I just added a public Animator anim; and then in the start anim = getComponent();

This is all I needed in order to get the script to play the animations. I needed the animations in an animator even though I was not using any transitions and needed another “animation” in order to have a static idle state. This works, but if anyone knows a more efficient way to eliminate the “idle” placeholder I’d be interested to hear.

The tutorial I based all of this on was written in JavaScript and was using some outdated features such as the old GUI system and animation systems. Here is a link to the video for reference; I hope this helps in case anyone else is looking for a working way to do this using C#.

Here is the code that is working now, in case anyone is interested:

using UnityEngine;
using System.Collections;

public class doorScript : MonoBehaviour
{
//box collider to see if player is near the door
     public Collider theCollider;
     public Canvas doortext;
     public bool doorisClosed;
//I added the following line for referencing the animator
     public Animator anim;


     void Awake ()
     {
          theCollider = GetComponent <BoxCollider> ();
          doortext = doortext.GetComponent<Canvas> ();
          doortext.enabled = false;
//to get the animator component
          anim = GetComponent<Animator> ();
     }

     void Update () 
     { 
          if (doortext.enabled == true && (Input.GetKeyDown(KeyCode.R)))
          {
               StartCoroutine ("changeDoorState");
          }
     }

     IEnumerator changeDoorState ()
     { 
          if (doorisClosed == true) 
          {
               anim.Play("doorOpen");
               doorisClosed = false;
               yield return new WaitForSeconds (5);
               anim.Play ("doorClose");
               doorisClosed = true;
          }
     }

     void OnTriggerEnter(Collider other)
     {
          if(other.gameObject.tag == "Player") 
          {
               doortext.enabled = true;
          }
     }

     void OnTriggerExit(Collider other)
     {
          if (other.gameObject.tag == "Player") 
          {
               doortext.enabled = false;
          }
     }
}
1 Like

Improved. I also added the following snippet. this makes the door text disappear while the door is in the open position, so that you are told to “Press R to open” only when you are actually able to do so.

     void OnTriggerStay(Collider other)
     {
     if (other.gameObject.tag == "Player" && doorisClosed == false) 
          {
          doortext.enabled = false;
          }
     if (other.gameObject.tag == "Player" && doorisClosed == true) 
     {
          doortext.enabled = true;
     } 
}

Hello I want to only open/close the door when the “Player” is near te door or the door hangle which is an empty gameobject. Also that the message appears only when Im near the door. This is my code

using UnityEngine;
using System.Collections;

public class doorOpenandClose : MonoBehaviour {

    //Text variables
    public bool T_ActivatedOpen = true;
    public bool T_ActivatedClose = false;
    public bool activateTrigger = false;

    public GameObject textO;
    public GameObject textC;

    //Animator variables
    Animator animator;
    bool doorOpen;
    //Sound variables
    public GameObject doorOpenSound;
    public GameObject doorCloseSound;






    void Start () { //what happens in the beginning of the game.
        textC.SetActive (false);
        textO.SetActive (false);
        T_ActivatedOpen = true;
        T_ActivatedClose = false;

        animator = GetComponent<Animator> ();
        doorOpen = false;


        doorCloseSound.SetActive (false);
        doorOpenSound.SetActive (false);



   
    }
   

    void Update () { //The main function wich controlls how the system will work.

        if (T_ActivatedOpen == true)
            T_ActivatedClose = false;

        else if (T_ActivatedClose == true)
            T_ActivatedOpen = false;

        if (activateTrigger && Input.GetKeyDown (KeyCode.E)) //For some reaseon you can't have both E (open and close).
            {
               
                T_ActivatedOpen = false;
                T_ActivatedClose = true;
                textO.SetActive (false);
                textC.SetActive (true);
                doorOpen = true;

                doorOpenSound.SetActive (true);
                doorCloseSound.SetActive (false);

            if (doorOpen)
            {
                doorOpen = true;
                doorController ("Open");
            }
               
            }
            else if(T_ActivatedClose && activateTrigger && Input.GetKey (KeyCode.F))
            {
                T_ActivatedOpen = true;
                T_ActivatedClose = false;
                textO.SetActive (true);
                textC.SetActive (false);

                doorCloseSound.SetActive (true);
                doorOpenSound.SetActive (false);
   
            if (doorOpen)
            {
                doorOpen = false;
                doorController ("Close");
            }
               
            }
    }


                                                       
    void OnTriggerEnter(Collider col) //If you enter the trigger this will happen.
    {
        if(col.gameObject.tag == "Player")
        {

                activateTrigger = true;
            if((T_ActivatedOpen == true))
            textO.SetActive (true);

            if((T_ActivatedClose == true))
                textC.SetActive (true);
        }
       
    }


    void OnTriggerExit(Collider col) //If you exit the trigger this will happen.
    {
        if(col.gameObject.tag == "Player")
        {
            textO.SetActive (false);
            textC.SetActive (false);
            activateTrigger = false;
        }

    }

    void doorController(string direction) //Animator function.
    {
        animator.SetTrigger(direction);
    }
       
}