0

I am trying to display a message saying 'Press E to talk to NPC' when the player is collided with the NPC collider and when the player is not collided with the NPC the message is disabled. The message does appear upon collision but it does not disabled when there are no collisions I have tried so many things but nothing seem to work. Can anyone help? HERE IS MY CODE AND SOME THINGS I HAVE TRIED:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Task_7 : MonoBehaviour
{
   public GameObject PressEmsg;
   //public bool isNearNPC = true;
  // Start is called before the first frame update
  void Start()
 {
    PressEmsg.gameObject.SetActive(false);
}

// Update is called once per frame
void Update()
{
    Collider[] nearbyColliders = Physics.OverlapSphere(transform.position, 5f);

    //bool isNearNPC = false;
    //we are looping in the array hitColliders
    foreach(Collider collider in nearbyColliders)
    {
        if(collider.gameObject.tag == "NPC")
        {
            PressEmsg.gameObject.SetActive(true);
            print("NPC DETECTED");
            //isNearNPC = true;
        }

        else
        {
            PressEmsg.gameObject.SetActive(false);
            print("NPC NOT DETECTED");
        }
        /*
        else if(collider.gameObject.tag != "NPC")
        {
            PressEmsg.gameObject.SetActive(false);
            print("NPC NOT DETECTED");
        }
        */
        
    }   

    /*foreach(Collider collider1 in notnearbyColliders)
    {
        if(collider1.gameObject.tag != "NPC")
        {
            PressEmsg.gameObject.SetActive(false);
            print("NPC NOT DETECTED");
        }
    }
    */
   
    
}


}
Z.Mizzi
  • 13
  • 2

2 Answers2

0

It seems like if you don't have any collisions, you won't get into your for loop.

Before looping over the found colliders I would default the message to be not active, but I'd use a variable so I only actually call the message state method once:

bool isNearNpc = false;

Collider[] nearbyColliders = Physics.OverlapSphere(transform.position, 5f);

foreach(Collider collider in nearbyColliders)
{
    if(collider.gameObject.tag == "NPC")
    {
        print("NPC DETECTED");
        isNearNpc = true;
    }
}


PressEmsg.gameObject.SetActive(isMessageActive);
print($"NPC DETECTED: { isNearNpc }");
ps2goat
  • 8,067
  • 1
  • 35
  • 68
0

If you have no collisions at all you will not have any iteration of your loop. So the deactivate will not happen, except you have a nearby object without the tag NPC.

Further you are iterating through all the nearby objects and check for each of them if it has the tag NPC. So the loop fully depends on the order in which the colliders are iterated. It might e.g. happen that you first have a hit that has the tag, then you have a second hit that doesn't => you falsely deactivate the object again.

You should rather use Linq Any like e.g.

using System.Linq;

...

void Update()
{
    var nearbyColliders = Physics.OverlapSphere(transform.position, 5f);

    // This will be true if any of the nearbyColliders has the tag "NPC"
    // If there are no colliders this will automatically be false accordingly
    var detected = nearbyColliders.Any(collider => collider.CompareTag("NPC"));
    // Basically this equals somewhat doing 
    //var detected = false;
    //foreach(var collider in nearbyColliders)
    //{
    //    if(collider.CompareTag("NPC"))
    //    {
    //        detected = true;
    //        break;
    //    }
    //}

    PressEmsg.gameObject.SetActive(detected);
    print(detected ? "NPC detected" : "NPC not detected");
}

In general for performance reasons avoid logging in Update! Even though your users don't see the log it is still done and is quite expensive.


Note: Typed on smartphone but I hope the idea gets clear

derHugo
  • 83,094
  • 9
  • 75
  • 115
  • Im tyring to use your code however it's giving me red lines underneath some of the syntax – Z.Mizzi Jan 17 '21 at 15:44
  • @Z.Mizzi which ones? ;) I typed it on my smartphone so maybe there are some syntax issues – derHugo Jan 17 '21 at 15:45
  • Oh ahah um the line that goes: var detected = nearbyColliders.Any(collider => collider.CompareTag("NPC"); There is a red line undearneath 'var' and the semicolon – Z.Mizzi Jan 17 '21 at 15:56
  • Do you get any error in the Unity console? Oh and there was a missing `)` after `"NPC")` – derHugo Jan 17 '21 at 16:25