Andrea Maps
Andrea Maps

Reputation: 97

Go to next level when Key is grabbed by Player Unity 2d

I need some help with a feature I'm implementing for a game made in Unity 2D. The player must take a key in order to unlock a door (maybe showing an animation) and when the player go in front of that door if he has the key, he will automatically go to the next level. I need help, cause the door is not letting go to the next level.

Here is the KEY code/script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class KeyScript : MonoBehaviour {

    //public AudioSource coinSoundEffect;
    public AudioClip key1;

    void Awake () {

        //source = GetComponent<AudioSource>();
    }

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
    void OnCollisionEnter2D (Collision2D other) {
        Debug.Log("Chiave Presa");

        if(other.gameObject.tag =="Player")
            GameObject.Find("KeyDoor").SendMessage("HitKey");
        SoundManager2D.playOneShotSound(key1);
    }

}

Here is the DOOR code/script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class DoorScript : MonoBehaviour {

    public bool key = false;
    public string nextLevelName;

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }

    void HitKey (){
        Debug.Log("La porta è sbloccata");
        key = true;
        Destroy (GameObject.Find ("Key"));
    }


    void OnCollisionEnter2D (Collision2D other){
        if(other.gameObject.tag == "Player"){
            if (key == true){
                Application.LoadLevel(nextLevelName);
                //Destroy(gameObject);
                //GameObject.Find("Key").SendMessage("DestroyKey"); //If you also want to destroy the key
                //GoToNextLevel ();

            }
        }
    }

    void OnTriggerEnter2D (Collision2D other)
    {
        Application.LoadLevel(nextLevelName);
    }

    public virtual void GoToNextLevel()
    {
        //loadingImage.SetActive(true);
        Application.LoadLevel(nextLevelName);

    }


}

The code works but when the player goes in front of the door, he is not passing to the next level. Any help or hint appreciated. Cheers

Upvotes: 2

Views: 1058

Answers (3)

mrogal.ski
mrogal.ski

Reputation: 5920

First of all, you're missing one thing:

is Component based engine

This means you should make interactions between Components, not GameObjects.

In your script there's a public field public bool key which should not be accessible from the outside. But if you're looking for simple and wrong answer that will work then you can just replace this line :

GameObject.Find("KeyDoor").SendMessage("HitKey");

Into this one :

GameObject.Find("KeyDoor").GetComponent<DoorScript>().key = true;

In that case you'll end up with messy code and unstable game. What I can recommend to you as an good alternative is to rewrite your logic a bit.

Instead of making a MonoBehaviour which is not needed you can just create a Component :

public class KeyComponent : Component
{
    [SerializeField]
    AudioClip m_KeyPickupSound;

    [SerializeField]
    bool m_IsPickedUp;

    public bool PickedUp
    {
        get { return m_IsPickedUp; }
    }

    public void PickUp()
    {
        m_IsPickedUp = true;
        SoundManager2D.playOneShotSound(m_KeyPickupSound);
    }
}

Now attach this into your Player's Components list and in your door script do:

void OnCollisionEnter2D (Collision2D other)
{
    if(other.GetComponent<KeyComponent>() != null && other.GetComponent<KeyComponent>().PickedUp)
    {
        SceneManager.LoadScene(2);
    } 
}

Now only thing left is to update your Player's MonoBehaviour and add simple collision check :

void OnCollisionEnter2D(Collision2D other)
{
    if(other.tag == "TAG_FOR_KEY")
        GetComponent<DoorScript>().PickUp();
}

Now you're interacting with Components and not GameObject which then require less effort changing some scripts.

Upvotes: 4

Juan Bayona Beriso
Juan Bayona Beriso

Reputation: 727

Make sure your player needs to have a Rigidbody2D and a Collider2D and the door has a Collider2D component

If your doors Collider2D is a trigger you must use void OnTriggerEnter2D(Collider2D other).

Another problem may be that "Level 2" isn't added to your build settings, make sure that it is added to the level's list.

Answering your last comment as it seemed the problem was that the Collider2D on the door, you can make this in a lot of ways, the easiest way is this:

Add a public string variable called nextLevelName in your Door's script, then when calling LoadLevel, use this variable. You can change the value from the inspector in each level. The problem with this is that if you rearrange the levels then you need to change the strings in each level.

The best solution in that case is this one:

int currentLevelNum = SceneManager.GetActiveScene().buildIndex;
SceneManager.LoadScene(currentLevelNum+1);

This way if you have your levels in order in your build settings you don't need to do anything else.

Upvotes: 1

Gunnar B.
Gunnar B.

Reputation: 2989

First off, you should change Application.LoadLevel to SceneManager.LoadScene. The first is obsolete in the newer versions of unity.

Second you need to make sure that your scenes are actually registered in File -> BuildSettings and the parameter you pass to LoadScene matches either the index in that list or the name as string.

Upvotes: 1

Related Questions