0

In my game on Unity3d I have a player object with main camera component. I need to disable player and then enable another object with another camera, but I have sctripts, which detect if player look at some object (using raycast). And if player with his camera are disabled, I have error. That's why I chech if player are enabled. But by some reason unity ignore this check

   void Update ()
    {
        if (player == null)
            player = GameObject.FindGameObjectWithTag("Player");

        if (Input.GetButton("Fire1"))
            if (DoPlayerLookAtButton() && isAimationReadyToPlay)
                OpenCloseDoor();
    }

    bool DoPlayerLookAtButton()
    {
        if (player != null)
        {
            if (player.activeSelf) // why Unity don't see this string?
            {
                int layerMask = 1 << 9;
                layerMask = ~layerMask;

                RaycastHit _hit;
                // I have error here:
                Ray _ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2, 0));
                bool isHit = Physics.Raycast(_ray, out _hit, 2.0f, layerMask);

                if (isHit && _hit.collider == thisCollider) return true;
                else return false;
            }
            else return false;
        }
        else return false;
    }

enter image description here

Edit 1 enter image description here

Amazing User
  • 3,473
  • 10
  • 36
  • 75

1 Answers1

1

The most important thing to understand here is that GameObject.FindGameObjectWithTag, GameObject.Find and other FindXXX functions for GameObjects cannot and will not be able to find GameObjects that are not active in the scene.

This is the reason you are getting that error. In most cases, you have two options:

1.Assign player from the Editor:

Make the player variable a public variable then assign the player to the player slot from the Editor.

public GameObject player;

With this, you don't need to use GameObject.FindGameObjectWithTag again and player cannot be null unless you explicitly set it to null.

2.If your GameObject has to be In-active by default then make it active from the Editor.

Find it with GameObject.FindGameObjectWithTag at the begining of the scene in the Start or Awake function then quickly set make it in-active with player.SetActive(false);.


Finally, Unity does not support finding in-active GameObjects by default but below are the functions once can use to find them. Do not abuse them because they are slow:

Find in-active GameObject by Name:

GameObject FindObjectInActiveByName(string name)
{
    Transform[] objs = Resources.FindObjectsOfTypeAll<Transform>() as Transform[];
    for (int i = 0; i < objs.Length; i++)
    {
        if (objs[i].hideFlags == HideFlags.None)
        {
            if (objs[i].name == name)
            {
                return objs[i].gameObject;
            }
        }
    }
    return null;
}

Find in-active GameObject by Tag:

GameObject FindObjectInActiveByTag(string tag)
{

    Transform[] objs = Resources.FindObjectsOfTypeAll<Transform>() as Transform[];
    for (int i = 0; i < objs.Length; i++)
    {
        if (objs[i].hideFlags == HideFlags.None)
        {
            if (objs[i].CompareTag(tag))
            {
                return objs[i].gameObject;
            }
        }
    }
    return null;
}

Find in-active GameObject by Layer:

GameObject FindObjectInActiveByLayer(int layer)
{

    Transform[] objs = Resources.FindObjectsOfTypeAll<Transform>() as Transform[];
    for (int i = 0; i < objs.Length; i++)
    {
        if (objs[i].hideFlags == HideFlags.None)
        {
            if (objs[i].gameObject.layer == layer)
            {
                return objs[i].gameObject;
            }
        }
    }
    return null;
}

EDIT:

With your more information, the problem is from here Camera.main.ScreenPointToRay:

If your camera is in-active or your camera is under a GameObject that is in-active, Camera.main will return null. It will not be able to find the Camera. When it returns null and you try to call its ScreenPointToRay function, you get an exception.

Also, if you have another camera in the scene that you toggle to, you have to make sure that you change the tag of that camera to "MainCamera" if that's the camera you use for Raycast. Check this post for more information on that. You do that because Camera.main will look for enabled Camera with the "MainCamera" tag.

Community
  • 1
  • 1
Programmer
  • 121,791
  • 22
  • 236
  • 328
  • Thanks! I understand, that Unity can't find inactive objects. I can't understand, why it don't see condition `if (player.activeSelf)`? Because player object are disabled and Unity anyway exeute the code inside this condition, but it shouldn't – Amazing User May 20 '17 at 09:13
  • 1
    From the screenshot your posted, you are getting `NullReferenceException`. Isn't it on that line of code(`player.activeSelf`)? – Programmer May 20 '17 at 09:16
  • @Progranner No, it is from the line "// I have error here:" – Amazing User May 20 '17 at 09:19
  • 1
    Oops my bad. This is where `Camera.main.ScreenPointToRay` is when you double click on the error? Also, does the error relate to your question at-all. I think I may have written something entirely different.... – Programmer May 20 '17 at 09:22
  • Error "NullReferenceException" by itself are not relates to my question =) I use `Camera` and `Raycast` to check if player are look at some object. And if player with his camera are disabled, then I have this error. That's why I have string `if (player.activeSelf)`, but it don't work. With this string, or without this string I have the same error – Amazing User May 20 '17 at 09:27
  • 1
    I get it now. Before I modify my answer, I want to be sure where the problem is. Please double click on the error from Unity Editor and it will take you to where the error is in your code. Post that line of code in the comment section – Programmer May 20 '17 at 09:31
  • I've posted a screenshot to my question in the *Edit 1* – Amazing User May 20 '17 at 09:38
  • I've added "MainCamera" tag to the another camera and now it works, thanks =) – Amazing User May 20 '17 at 10:02
  • 1
    You're welcome. Without that screenshot, we would have thought that the problem is from `player.activeSelf`. Happy coding! – Programmer May 20 '17 at 10:03