Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Simplest way to change Scene with a collider and a key press?

Discussion in 'Scripting' started by Kamelot89, Sep 30, 2016.

  1. Kamelot89

    Kamelot89

    Joined:
    Sep 20, 2016
    Posts:
    11
    Hello!

    I have a simple code:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.SceneManagement;
    4.  
    5. public class FrontDoorOutside : MonoBehaviour {
    6.  
    7.         void OnTriggerEnter(Collider other)
    8.  
    9.                
    10.             {
    11.                 SceneManager.LoadScene (2);
    12.             }
    13.         }
    14.    
    15.    
    16.  
    17.  
    18.    
    19.  
    20.  
    My character is a rigidbody with a collider and if he enters the object that has the script above attached, he will change the scene. What would be the simplest way to add a query for a key to be pressed such as if(Input.GetKeyDown(KeyCode.E));. I tried everything but can't get a solution.
     
  2. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    Since the physics events only fire on FixedUpdates, the chances of an onkeydown event happening at the same frame the physics event fires is not reliable.

    A very simple implementation could be like this:
    Code (CSharp):
    1. public KeyCode changeScenesKey;
    2. bool colliding;
    3.  
    4. private void OnTriggerEnter(Collider other) {
    5.     colliding = true;
    6. }
    7. private void OnTriggerExit(Collider other) {
    8.     colliding = false;
    9. }
    10.  
    11. private void Update() {
    12.     if(colliding && Input.GetKeyDown(changeScenesKey)) {
    13.         SceneManager.LoadScene(2)
    14.     }
    15. }
     
    Kamelot89 likes this.
  3. Karsten

    Karsten

    Joined:
    Apr 8, 2012
    Posts:
    183
    try this

    Code (CSharp):
    1. public class FrontDoorOutside : MonoBehaviour
    2. {
    3.     bool MustLoadScene = false;
    4.  
    5.     void OnTriggerEnter(Collider other)
    6.  
    7.  
    8.     {
    9.         if (MustLoadScene == true)
    10.         {
    11.             MustLoadScene = false;//we dont want to load the scene multible times
    12.             SceneManager.LoadScene(2);
    13.         }
    14.        
    15.     }
    16.  
    17.     void Update()
    18.     {
    19.         if (Input.GetKeyDown(KeyCode.E)) MustLoadScene = true;
    20.     }
    21. }
    22.    
     
  4. Kamelot89

    Kamelot89

    Joined:
    Sep 20, 2016
    Posts:
    11

    this one works perfect. thanks


    this one requires to press the key right at the same time you touch the collider. when I stand in it it won't work.
     
    Karsten and LiterallyJeff like this.
  5. Kamelot89

    Kamelot89

    Joined:
    Sep 20, 2016
    Posts:
    11
    would it be possible to add a timer before the scene change?

    I thought about something like this but it doesn't work. why not?

    Code (CSharp):
    1.     public KeyCode changeScenesKey;
    2.     bool colliding;
    3.     public float Timer = 10f;
    4.  
    5.     private void OnTriggerEnter(Collider other)
    6.     {
    7.         colliding = true;
    8.  
    9.     }
    10.     private void OnTriggerExit(Collider other)
    11.     {
    12.         colliding = false;
    13.  
    14.  
    15.     }
    16.  
    17.     private void Update ()
    18.     {
    19.        
    20.  
    21.         if (colliding && Input.GetKeyDown (changeScenesKey))
    22.         {
    23.  
    24.             Timer = Timer - Time.deltaTime;
    25.             {
    26.                 if(Timer >= 0)
    27.             {
    28.                    
    29.             }
    30.                 if(Timer <= 0)
    31.                     {
    32.                         SceneManager.LoadScene (2);
    33.                     }
    34.                 }
    35.             }
    36.         }
    37. }
     
  6. Karsten

    Karsten

    Joined:
    Apr 8, 2012
    Posts:
    183
    line 21 is evaluate to "true" max 1 time per keypress right?
     
    Kamelot89 likes this.
  7. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    That is correct, which means the timer will not increment properly.

    My favorite way to wait for things is to use Coroutines:
    Code (CSharp):
    1. public KeyCode changeScenesKey;
    2. public float Timer = 10f;
    3.  
    4. private bool colliding;
    5. private bool sceneChanging;
    6.  
    7. private void OnTriggerEnter(Collider other) {
    8.     colliding = true;
    9. }
    10. private void OnTriggerExit(Collider other) {
    11.     colliding = false;
    12. }
    13.  
    14. private void Update() {
    15.     if(!sceneChanging && colliding && Input.GetKeyDown(changeScenesKey)) {
    16.         sceneChanging = true;
    17.         StartCoroutine(sceneChangeCoroutine());
    18.     }
    19. }
    20.  
    21. private IEnumerator sceneChangeCoroutine() {
    22.     yield return new WaitForSeconds(Timer);
    23.     sceneChanging = false;
    24.     SceneManager.LoadScene(2);
    25. }
    make sure you have "using System.Collections" at the top in order to use IEnumerator.

    Here's how you can do it without coroutines:
    Code (CSharp):
    1. public KeyCode changeScenesKey;
    2. public float Timer = 10f;
    3.  
    4. private bool colliding;
    5. private bool sceneChanging;
    6. private float elapsedTime;
    7.  
    8. private void OnTriggerEnter(Collider other) {
    9.     colliding = true;
    10. }
    11. private void OnTriggerExit(Collider other) {
    12.     colliding = false;
    13. }
    14.  
    15. private void Update() {
    16.     if(sceneChanging) {
    17.         elapsedTime += Time.deltaTime;
    18.         if(elaspedTime >= Timer) {
    19.             SceneManager.LoadScene(2);
    20.             elapsedTime = 0;
    21.             sceneChanging = false;
    22.         }
    23.     } else if(colliding && Input.GetKeyDown(changeScenesKey)) {
    24.         sceneChanging = true;
    25.     }
    26. }
     
    Last edited: Oct 4, 2016
    Kamelot89 likes this.
  8. Kamelot89

    Kamelot89

    Joined:
    Sep 20, 2016
    Posts:
    11
    Without Coroutine is easier to understand for me at the moment. Now I want to get my character to be unable to move during the timer since it is supposed to act like a short loading screen with a panel or image infront of the camera that fades to black. Should I try to get the rigidbody of my character to disabled or should I disable the movement script for that? How do I get them?
     
  9. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    There are many ways you could organize the code communication.

    One way which is probably easiest to understand is to have the scene changer script get the player's component and disable it just after setting "sceneChanging = true". You could get the player script by using GameObject.FindGameObjectWithTag("Player") to get the player gameobject, or FindObjectOfType<MovementScript>() to directly find the script on the player (assuming there is only one of these in the scene).

    Ideally, the scene changer script wouldn't know about the player script at all, and would just do its thing. The player would check a value before acting on input. However doing that kind of organization is more complex and would require a longer explanation.
     
    Last edited: Oct 5, 2016
    metaldc4life and Kamelot89 like this.
  10. Kamelot89

    Kamelot89

    Joined:
    Sep 20, 2016
    Posts:
    11
    Thank you Jeffrey, I got it!
     
    LiterallyJeff likes this.