0
\$\begingroup\$

So, I need to load a different level when the user has crossed the entire level and collides (or triggers) a certain object. For that I have declared

using UnityEngine;
using UnityEngine.SceneManagement;

public class PacMan : MonoBehaviour
{    
    bool GameEnded = false;
    public float delay;
    
    // Ends the level
    public void GameOver()
    {
        if (GameEnded == false)
        {
            GameEnded = true;
            Invoke("Restart", delay);
        }
    }

    public GameObject LvlCompleteUI;

    // Restarts the level
    void Restart()
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().name);
    }

    public void LvlComplete()
    {
        LvlCompleteUI.SetActive(true);
        Debug.Log("GameOver");
    }
}

and then calling the function via

public class WinTrigger : MonoBehaviour
{ 
    // public PacMan pacMan;
    
    void OnCollisionEnter(Collision collision)
    {
        if (collision.collider.tag == "LvlWon")
        {
            FindObjectOfType<PacMan>().LvlComplete();
        }        
        
        // FindObjectOfType<PacMan>().LvlComplete(); 
        // pacMan.LvlComplete();      
    }
}

But, this is not working as the collision doesn't seem to be working. Neither does trigger. Any ideas why this is not working? Maybe the way I am doing it is wrong.

Edit:

  • PacMan is my PACkage MANager; basically it loads the scenes.
  • The WinBox is the object that will load the next scene on collision.
  • I did have Is Trigger on when I was trying the OnTriggerEnter() method.

PacMan script:

    using UnityEngine;
    using UnityEngine.SceneManagement;

    public class PacMan : MonoBehaviour
    {    
        bool GameEnded = false;
        public float delay;
        
        // Ends the level
        public void GameOver()
        {
            if (GameEnded == false)
            {
                GameEnded = true;
                Invoke("Restart", delay);
            }
        }

        public GameObject LvlCompleteUI;

        // Restarts the level
        void Restart()
        {
            SceneManager.LoadScene(SceneManager.GetActiveScene().name);
        }

        public void LvlComplete()
        {
            LvlCompleteUI.SetActive(true);
            Debug.Log("GameOver");
        }
    }

Movement Script:

    using UnityEngine;

    public class Movement : MonoBehaviour
    {
        public Rigidbody RB;

        // public bool forward;
        // public bool back;
        public bool left;
        public bool right;

        // public string isTrueF;
        // public string isTrueB;
        public string isTrueL;
        public string isTrueR;

        void Update()
        {
            // bool forward = Input.GetKey(KeyCode.W);
            // bool back = Input.GetKey(aKeyCode.S);
            bool left = Input.GetKey(KeyCode.A);
            bool right = Input.GetKey(KeyCode.D);
            
            // if (forward == true)
            // {
            //     isTrueF = "True";
            // } else {
            //     isTrueF = "False";
            // }        
            // if (back == true)
            // {
            //     isTrueB = "True";
            // } else {
            //     isTrueB = "False";
            // }
            if (left == true)
            {
                isTrueL = "True";
            } else {
                isTrueL = "False";
            }
            if (right == true)
            {
                isTrueR = "True";
            } else {
                isTrueR = "False";
            }
        }

        void FixedUpdate()
        {
            // if (isTrueF == "True")
            // {
            //     RB.AddForce(1000 * Time.deltaTime, 0, 0); 
            // }
            // if (isTrueB == "True")
            // {
            //     RB.AddForce(-1000 * Time.deltaTime, 0, 0); 
            // }
            RB.AddForce(0, 0, 500 * Time.deltaTime);
            
            if (isTrueL == "True")
            {
                RB.AddForce(-25 * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
            }
            if (isTrueR == "True")
            {
                RB.AddForce(25 * Time.deltaTime, 0, 0, ForceMode.VelocityChange); 
            }

            if (RB.position.y <= 0f)
            {
                FindObjectOfType<PacMan>().GameOver();
            }

            // if (Input.GetKey("d"))
            // {
            //     RB.AddForce(1000 * Time.deltaTime, 0, 0);
            // }
            // if (Input.GetKey("a"))
            // {
            //     RB.AddForce(-1000 * Time.deltaTime, 0, 0);
            // }
            // if (Input.GetKey("w"))
            // {
            //     RB.AddForce(0, 0, 1000 * Time.deltaTime);
            // }
            // if (Input.GetKey("s"))
            // {
            //     RB.AddForce(0, 0, -1000 * Time.deltaTime);
            // }
        }
    }

Win Trigger Script:

    using UnityEngine;

    public class WinTrigger : MonoBehaviour
    { 
        // public PacMan pacMan;
        
        void OnCollisionEnter(Collision collision)
        {
            if (collision.collider.tag == "Finish")
            {
                FindObjectOfType<PacMan>().LvlComplete();
            }        
            
            // FindObjectOfType<PacMan>().LvlComplete(); 
            // pacMan.LvlComplete();      
        }
    }

Player Collision Script:

    using UnityEngine;

    public class PlayerCollision : MonoBehaviour
    {      
    void OnCollisionEnter (Collision collisionInfo)
    {
        if (collisionInfo.collider.tag == "Obstacles")
        {
            GetComponent<Movement>().enabled = false;
            FindObjectOfType<PacMan>().GameOver();
        }
    }

Here's the hierarchy and first map:

hierarchy_1 hierarchy_2 map pacman player win_box

\$\endgroup\$
8
  • \$\begingroup\$ You have a typo in OnCOllisonEnter. \$\endgroup\$
    – user35344
    Commented Aug 9, 2021 at 15:47
  • \$\begingroup\$ its still not working. after correcting the typo that is \$\endgroup\$
    – dotmashrc
    Commented Aug 9, 2021 at 15:58
  • \$\begingroup\$ Is the tag "LvlWon" on the PacMan, or the WinTrigger? And have you checked if the PacMan has Rigidbody and Collider? We just need more information to fix your problem. \$\endgroup\$
    – Joseph
    Commented Aug 9, 2021 at 16:27
  • 1
    \$\begingroup\$ Note that OnCollision and OnTrigger are not the same thing. The first requires a rigidbody, and the second the "Is Trigger?" flag enabled on the collider. There are about 50 other things which could be wrong. Please show us how you set up the objects involved in this collision. \$\endgroup\$
    – Philipp
    Commented Aug 9, 2021 at 16:45
  • \$\begingroup\$ will that be enough info? \$\endgroup\$
    – dotmashrc
    Commented Aug 9, 2021 at 19:02

1 Answer 1

1
\$\begingroup\$

The object passed to an OnCollisionEnter method is the other object triggering the collision. The method of your class WinTrigger is checking if that object has the tag "Finish" before doing anything else. But the player does not have that tag. It doesn't have a tag at all. So nothing is going happen here.

I would write the method like this:

void OnCollisionEnter(Collision collision)
{
    var pacMan = collision.gameObject.GetComponent<PacMan>();
    if (pacMan != null)
    {
        pacMan.LvlComplete();
    }             
}

This code attempts to retrieve the PacMan component from the object which triggered the collision. When the object has such a component, then it calls the LvlComplete method on it. When the object doesn't have such a component, the method does nothing.

I greatly prefer this pattern of identifying collision partners via their components over the use of tags for several reasons:

  1. You can only put one tag on an object, which quickly becomes insufficient in more complex games with multiple interlocking systems. But you can add any number of components to an object. Sometimes I create pure "tag components" which are completely empty classes inheriting from MonoBehaviour and only exist to tag a gameObject as eligible for some interaction which is implemented somewhere else.
  2. You usually only care about whether or not the colliding object supports certain operations this collision will cause. Which it usually does if it has all the required components.
  3. Your development environment will tell you immediately when you misspell a component name in GetComponent<PakMan>(). But tag names are string literals. So when you misspell them, then your code just won't work and no error or warning message will give you a hint why.
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .