0
votes

I have the following FollowingNPC game object, which is supposed to follow the Player object if there is direct vision:

FollowingNPC

Here the Player object:

Player

The BlockingLayer and Player Layers have the physics collision enabled between each other:

Collision Matrix

The FollowingNPC hast the following script attached, that always returns a "Not Hit" result: Raycast always false. This is not the expected output, as both objects seem to have a clear view between each other and the debug ray can be drawn without problems.

public class FollowingNPC : MonoBehaviour
{
    private Vector3 heading, direction;
    private float distance;

    void Update()
    {
        heading = GameObject.FindGameObjectWithTag("Player").transform.position - transform.position;
        distance = heading.magnitude;
        direction = heading / distance;

        RaycastHit hit;
        if (Physics.Raycast(transform.position, direction, out hit))
        {
            if (hit.transform== GameObject.FindGameObjectWithTag("Player").transform)
            {
                Debug.DrawRay(transform.position, direction * distance, Color.red);
                Debug.Log("Hit Player");
            }
            else
            {
                Debug.DrawRay(transform.position, direction * distance, Color.yellow);
                Debug.Log("Hit Wall");
            }

        }
        else
        {
            Debug.DrawRay(transform.position, direction * distance, Color.white);
            Debug.Log("Not Hit");
        }
    }
}

Solved:

As derHugo suggested, Physics2D.Raycast should be used here. This function does not return a bool, so this is the implementation that worked for me:

void Update()
{
    heading = GameObject.FindGameObjectWithTag("Player").transform.position - transform.position;
    RaycastHit2D hit = Physics2D.Raycast(transform.position, heading.normalized, LayerMask.GetMask("Player"));

    if (hit.collider != null)
        if (hit.transform == GameObject.FindGameObjectWithTag("Player").transform)
            Debug.Log("Hit Player");
        else
            Debug.Log("Hit Wall");
    else
        Debug.Log("Not Hit");
}

Also, it's important to note that, even with the mask, the Raycast returned the hit with the collider of FolloginNPC, so I had to disable it. I'll have to do some investigation or search a workaround.

1
Do you mean Raycast and false? Raytracing is used in lightning systems and not related to what you are talking about ;)derHugo

1 Answers

2
votes

Note that in Unity the Physics and Physics2D are completely independent and separated Physics engines!

  • Built-in 3D physics (Nvidia PhysX engine integration)
  • Built-in 2D physics (Box2D engine integration)

You have Rigidbody2D and Collider2D so you would rather want to use Physics2D.Raycast!

You should also strongly avoid using FindGameObjectWithTag in Update and even worse multiple times as it is quite expensive! Rather do it once and store the result.

// If possible and best would be to already reference it via the Inspector
[SerilaizeField] private Transform player;

// As fallback get it ONCE on runtime
private void Awake()
{
    if(!player) player = GameObject.FindGameObjectWithTag("Player").transform;
}

void Update()
{
    // actually those wouldn't really need to be fields
    heading = player.position - transform.position;
    distance = heading.magnitude;
    // This line isn't really necessary
    // If something I would use 
    //direction = heading.normalized
    direction = heading / distance;

    var hit = Physics2D.Raycast(transform.position, direction);

    if (hit.collider)
    {
        if (hit.transform == player)
        {
            Debug.DrawRay(transform.position, direction * distance, Color.red);
            Debug.Log("Hit Player");
        }
        else
        {
            Debug.DrawRay(transform.position, direction * distance, Color.yellow);
            Debug.Log("Hit Wall");
        }
    }
    else
    {
        Debug.DrawRay(transform.position, direction * distance, Color.white);
        Debug.Log("Not Hit");
    }
}

Later you should also remove all these Debug.Log since they are also quite expensive when done in Update!