Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Door opens from any distance

Discussion in 'Scripting' started by Harardin, Aug 12, 2015.

  1. Harardin

    Harardin

    Joined:
    Aug 5, 2015
    Posts:
    58
    Hi to everyone, I have a little problem.

    Made two scripts for opening door when button is pressed. The problem is door opens from any distance, and I need it opens only when player press button in front of a door.

    Here is first script what attached to a Camera of FPS controller char.

    Code (CSharp):
    1. public class DoorRayCast : MonoBehaviour
    2. {
    3.     public float Doordistance = 1.5f;
    4.     private bool reachindDoor = false;
    5.    
    6.     void Start ()
    7.     {
    8.        
    9.     }
    10.     private IEnumerator isDoorClose ()
    11.     {
    12.         while (true)
    13.         {
    14.             if (Input.GetButtonDown("actButton"))
    15.             {
    16.                 if (!reachindDoor)
    17.                     checkForDoor();
    18.                 else
    19.                     reachindDoor = false;
    20.             }
    21.             yield return null;
    22.         }
    23.  
    24.     }
    25.     private void checkForDoor ()
    26.     {
    27.         Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5F, 0.5F, 0));
    28.         RaycastHit data;
    29.         if (Physics.Raycast (ray, out data, Doordistance))
    30.         {
    31.             if (data.transform.tag == "door")
    32.             {
    33.                 reachindDoor = true;
    34.                 GetComponent<DoorsActAnim>();
    35.                 return;
    36.             }
    37.         }
    38.         reachindDoor = false;
    39.     }
    40. }
    And a second one what starts an animation.

    Code (CSharp):
    1. public class DoorsActAnim : MonoBehaviour
    2. {
    3.     private Animator DoorAnim;
    4.     private AnimatorStateInfo BaseLayer;
    5.     private AnimatorStateInfo currentBaseState;
    6.     static int idleDoor = Animator.StringToHash("Base Layer.apartment_door_idle");
    7.     static int openDoor = Animator.StringToHash("Base Layer.apartment_door_open");
    8.     static int closeDoor = Animator.StringToHash("Base Layer.apartment_door_close");
    9.     public float Doordistance = 1.5f;
    10.     public AudioClip openDoorSound;
    11.     public AudioClip closeDoorSound;
    12.     private AudioSource DoorSound;
    13.    
    14.     // Use this for initialization
    15.     void Start()
    16.     {
    17.        
    18.         DoorAnim = GetComponent<Animator>();
    19.         DoorSound = GetComponent<AudioSource>();
    20.     }
    21.     void FixedUpdate()
    22.     {
    23.        
    24.         currentBaseState = DoorAnim.GetCurrentAnimatorStateInfo(0);
    25.  
    26.         if (Input.GetButtonDown("actButton"))
    27.         {
    28.            
    29.  
    30.                     DoorSound.PlayOneShot(openDoorSound);
    31.                     if (currentBaseState.nameHash == closeDoor)
    32.                     {
    33.                         DoorAnim.SetTrigger("Open");
    34.                         DoorSound.PlayOneShot(openDoorSound);
    35.                     }
    36.                     else
    37.                     {
    38.                         DoorAnim.SetTrigger("Close");
    39.                         DoorSound.PlayOneShot(closeDoorSound);
    40.                     }
    41.                 }
    42.             }
    43.         }
    44.    
    45.  
     
  2. Harardin

    Harardin

    Joined:
    Aug 5, 2015
    Posts:
    58
    I know the trouble is in in DoorActAnim Script in the if (Input.GetButtonDown(“actButton”)) part just don’t know how to fix it, and make it right. I am a newbie in Scripting.
     
  3. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    Code (csharp):
    1.  
    2. GetComponent<DoorsActAnim>();
    3.  
    this line does nothing, "get me the component", "ok, now what?"... "oh nothing"
     
    blizzy and Deleted User like this.
  4. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    that script does nothing about checking the distance... so it will always work. Both scripts are working independantly of each other.

    I think you are trying to make the first script tell the second script "do something". In which case you need to create a function, not use an Update in DoorsActAnim
    and then you can use

    Code (csharp):
    1.  
    2. GetComponent<DoorsActAnim>().WhateverTheFunctionIsCalled();
    3.  
    ("get me the component", "ok, now what?"... "and now do this thing")

    this way the input is checked for distance in the first script, if it's within range and any other prerequisites are met the animation handler script is told to do something i.e. open the door.
     
  5. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    Change FixedUpdate in the second script to just Update, first off- there's no physics in there, so it's better to just run it all once per frame like normal. IsDoorClose() is currently running every single frame, infinitely. In that situation, there's no reason to incur the overhead of a coroutine- just make it a normal function and have it called every frame in Update() instead. None of this is important now, because you need to delete most of it anyways.

    Now, as for the distance problem, both scripts have independent actions that occur when a single button is pressed. The action in the door's animation script has no dependence on anything except that button press. What you need to do is move the entirety of that into a new function called "ToggleDoor", which you'll then call from "data.GetComponent<DoorsActAnim>().ToggleDoor();" in your raycast. In fact, just move the "If GetButtonDown" into that raycast and call the function only if the raycast results are tagged "door" AND the button is pressed.
     
  6. Harardin

    Harardin

    Joined:
    Aug 5, 2015
    Posts:
    58
    Code (CSharp):
    1. public class DoorRayCast : MonoBehaviour
    2. {
    3.     public float Doordistance = 1.5f;
    4.  
    5.    
    6.     void Start ()
    7.     {
    8.        
    9.     }
    10.     void Update ()
    11.     {
    12.         Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5F, 0.5F, 0));
    13.         RaycastHit data;
    14.         if (Physics.Raycast (ray, out data, Doordistance))
    15.         {
    16.             if (data.transform.tag == "door")
    17.             {
    18.                
    19.                     if (Input.GetButtonDown("actButton"))
    20.                     {
    21.                         GetComponent<DoorsActAnim>().ToggleDoor();
    22.                     }
    23.                
    24.             }
    25.         }
    26.        
    27.     }
    28. }
    Can’t add a data.GetComponent<DoorsActAnim>().ToggleDoor();
    It causes an error RayCastHit does not contain a definition of GetComponent
     
  7. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    data.gameObject.GetComponent<DoorsActAnim>().ToggleDoor();
     
  8. Harardin

    Harardin

    Joined:
    Aug 5, 2015
    Posts:
    58
    Code (CSharp):
    1. void Update ()
    2.     {
    3.         Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5F, 0.5F, 0));
    4.         RaycastHit data;
    5.         if (Physics.Raycast (ray, out data, Doordistance))
    6.         {
    7.             if (data.transform.tag == "door")
    8.             {
    9.              
    10.                     if (Input.GetButtonDown("actButton"))
    11.                     {
    12.                         data.collider.GetComponent<DoorsActAnim>().ToggleDoor();
    13.                     }
    14.              
    15.             }
    16.         }
    17.      
    18.     }
    19. }
    Still same error, but if to make it collider error Is disappear, but door don’t open.

    data.gameObject didn't helped. I think I miss something
     
  9. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    Yup, I was wrong- I thought you could just get the GameObject directly, but this way works. You haven't shown us the script that has the ToggleDoor() function in it though, so copy that over.
     
  10. Harardin

    Harardin

    Joined:
    Aug 5, 2015
    Posts:
    58
    Oh yeah sorry abou that here it is:

    Code (CSharp):
    1. public class DoorsActAnim : MonoBehaviour
    2. {
    3.     private Animator DoorAnim;
    4.     private AnimatorStateInfo BaseLayer;
    5.     private AnimatorStateInfo currentBaseState;
    6.     static int idleDoor = Animator.StringToHash("Base Layer.apartment_door_idle");
    7.     static int openDoor = Animator.StringToHash("Base Layer.apartment_door_open");
    8.     static int closeDoor = Animator.StringToHash("Base Layer.apartment_door_close");
    9.     public float Doordistance = 1.5f;
    10.     public AudioClip openDoorSound;
    11.     public AudioClip closeDoorSound;
    12.     private AudioSource DoorSound;
    13.    
    14.     // Use this for initialization
    15.     void Start()
    16.     {
    17.        
    18.         DoorAnim = GetComponent<Animator>();
    19.         DoorSound = GetComponent<AudioSource>();
    20.     }
    21.    public void ToggleDoor()
    22.     {
    23.      
    24.        
    25.         currentBaseState = DoorAnim.GetCurrentAnimatorStateInfo(0);
    26.  
    27.         if (Input.GetButtonDown("actButton"))
    28.         {
    29.          
    30.  
    31.                     DoorSound.PlayOneShot(openDoorSound);
    32.                     if (currentBaseState.nameHash == closeDoor)
    33.                     {
    34.                         DoorAnim.SetTrigger("Open");
    35.                         DoorSound.PlayOneShot(openDoorSound);
    36.                     }
    37.                     else
    38.                     {
    39.                         DoorAnim.SetTrigger("Close");
    40.                         DoorSound.PlayOneShot(closeDoorSound);
    41.                     }
    42.                 }
    43.        
    44.             }
    45.  
    46.         }
    47.    
    48.  
     
  11. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    No need for the Input check in this one, since you're already doing that check in the other script.
     
  12. Harardin

    Harardin

    Joined:
    Aug 5, 2015
    Posts:
    58
    Yep I clean Input check but still can't get the door open
     
  13. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    The string tag on the door has to be exactly right (right capitalization too), your button press "actButton" has to be in the Input list in Unity, the distance has to be great enough to actually be able to reach the door (try removing the distance completely for a minute, as that will set it to "infinity" by default), you need to have a box collider on the door object (which is NOT set to "trigger", if you don't have Edit => Project Settings => Physics set to "raycast hit triggers"), the door object and its collider both have to be active.

    If none of that works, put some Debug.Logs in the code after every conditional statement to see where it's being foiled.
     
  14. Harardin

    Harardin

    Joined:
    Aug 5, 2015
    Posts:
    58
    Code (CSharp):
    1. public class DoorRayCast : MonoBehaviour
    2. {
    3.     public float RayDistanse = 0f;
    4.  
    5.  
    6.     void Start()
    7.     {
    8.  
    9.     }
    10.  
    11.  
    12.     void Update()
    13.     {
    14.  
    15.         RaycastHit hit;
    16.         Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    17.        
    18.         if (Physics.Raycast(ray, out hit, RayDistanse))
    19.         {
    20.             if (hit.transform.tag == "DoorTag")
    21.             {
    22.  
    23.                 if (Input.GetButtonDown("actButton"))
    24.                 {
    25.                     //hit.collider.enabled = true;
    26.                     hit.collider.GetComponent<DoorsActAnim>().ToggleDoor();
    27.                     Debug.Log("Input hit");
    28.                 }
    29.                 Debug.Log("hit Ray");
    30.             }
    31.             Debug.Log("hit Ray 01");
    32.         }
    33.         //Debug.Log("Start");
    34.     }
    35. }
    36.  
    I checked all with a debug, problem starts some where in this part of code, but I can’t understand where everything is set up right I checked settings and tags like 5 times, even changed some of them for incase.

    Code (CSharp):
    1. RaycastHit hit;
    2.         Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    3.        
    4.         if (Physics.Raycast(ray, out hit, RayDistanse))
    5.         {
    6.             if (hit.transform.tag == "DoorTag")
    7.             {
     
  15. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    I didn't mean to set the RayDistanse variable to 0f, that'll literally not move anywhere. You need to remove the variable entirely from the raycast so there's only a ray and a hit, or change "RayDistanse" to "Mathf.Infinity" in the raycast- which will do exactly the same thing.

    Anyways, that'll only tell you if this is the part that was going wrong- you'll be back to being able to activate it from any distance- though you'll at least have to be looking right at it. If that is the problem, then you need to just keep adjusting the distance until you've got it set to something that works, but is reasonably close.
     
  16. Harardin

    Harardin

    Joined:
    Aug 5, 2015
    Posts:
    58
    Unfortunately it’s not a distance problem.

    Code (CSharp):
    1.  void Update()
    2.     {
    3.  
    4.         RaycastHit hit;
    5.         Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    6.        
    7.         if (Physics.Raycast(ray, out hit))
    8.         {
    9.             if (hit.transform.tag == "DoorTag")
    10.             {
    11.  
    12.                 if (Input.GetButtonDown("actButton"))
    13.                 {
    14.                    
    15.                     hit.collider.GetComponent<DoorsActAnim>().ToggleDoor();
    16.                     Debug.Log("Input hit");
    17.                 }
    18.                 Debug.Log("hit Ray");
    19.             }
    20.             Debug.Log("hit Ray 01");
    21.         }
    22.         //Debug.Log("Start");
    23.     }
    24. }
    I am start to becoming desperate.
     
  17. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    I just noticed that you switched over to using ScreenPointToRay- is there actually a cursor on the screen? I had assumed that this was first person, so ViewportPointToRay how you had it was fine. Also, is the current camera the only camera? Instead of using Camera.main you can just grab the GetComponent<Camera>() to make sure that the proper camera is the one being raycasted from (assuming this script is attached to the camera object).
     
    Last edited: Aug 12, 2015
  18. Harardin

    Harardin

    Joined:
    Aug 5, 2015
    Posts:
    58
    When script look like this If (Physics.Raycast(ray, out hit, RayDistanse)) start to work at least debugLog says like this.

    but the last part what should redirect on animation script don't work, I think i miss some mistake in there

    But at least RayCastig work correct right now.

    Code (CSharp):
    1. void FixedUpdate()
    2.     {
    3.  
    4.         RaycastHit hit;
    5.  
    6.         Ray ray = CameraMain.ViewportPointToRay(new Vector3(0, 0, 0));
    7.  
    8.         if (Physics.Raycast(ray, out hit, RayDistanse))
    9.         {
    10.  
    11.            
    12.                 if (hit.transform.tag == "DoorTag")
    13.                 {
    14.  
    15.  
    16.                     //hit.collider.enabled = false;
    17.                     if (Input.GetButtonDown("actButton"))
    18.                     {
    19.  
    20.                         hit.collider.gameObject.GetComponent<DoorsActAnim>().ToggleDoor();
    21.                         Debug.Log("Input hit");
    22.                     }
    23.  
    24.                 }
    25.                 Debug.Log("hit Ray 01");
    26.             }
    27.             //Debug.Log("Start");
    28.         }
    29.     }
    30.  
     
  19. Harardin

    Harardin

    Joined:
    Aug 5, 2015
    Posts:
    58
    Guess I just find an error

    NullReferenceException: Object reference not set to an instance of an object

    DoorRayCast.FixedUpdate () (at Assets/doors_active/DoorRayCast.cs:34)

    in this part of Script

    Code (CSharp):
    1. hit.collider.gameObject.GetComponent<DoorsActAnim>().ToggleDoor();
    2.                         Debug.Log("Input hit");
     
  20. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    You put it back in FixedUpdate- there's no physics here, so leave it in Update. When you do ViewportPointToRay, you need to use .5f for the x and y values to mean "middle of the screen". It looked like you had an extra "}" in there after everything else. DoorsActAnim needs to be the name of the class and the file of the animation script you made, it needs to be properly spelled and capitalized, it needs to be attached to the same object (the door) that the collider is attached to, and it needs to be enabled.

    Code (csharp):
    1. void Update()
    2. {
    3.    RaycastHit hit;
    4.    Ray ray = GetComponent<Camera>().ViewportPointToRay(new Vector3(.5f, .5f, 0f));
    5.  
    6.    if (Physics.Raycast(ray, out hit, RayDistance))
    7.    {
    8.       if (hit.transform.tag == "DoorTag")
    9.       {
    10.          if (Input.GetButtonDown("actButton"))
    11.          {
    12.             hit.collider.GetComponent<DoorsActAnim>().ToggleDoor();
    13.          }
    14.       }
    15.    }
    16. }
     
    Last edited: Aug 12, 2015
  21. Harardin

    Harardin

    Joined:
    Aug 5, 2015
    Posts:
    58
    Oh my I am such a stupid, I applied Collider on a door in Hierarchy, not on a main prefab, sorry for vesting your time, and thank for your help.