Object detection with Raycast2D

I am working on a simple game strategy. I have a collection of barracks. When I add Barracks to the scene and click on Barracks, I get the error NullReferenceException

:

NullReferenceException: Object reference not set to PlacementController.Update () object instance (in Assets / Scripts / PlacementController.cs: 64)

The error is received when I try to reach the barracks collider name using Raycast2D.

The Barracks Collection has a Box Collider2D (trigger checked), and its tag is "Construction", and its layer is "Buildings". It has a rigid 2D element and is a kinematic rigid body.

I cannot figure out this problem. Please help me.

Thank you for your time.

using UnityEngine;
using System.Collections;

public class PlacementController : MonoBehaviour
{
    private Buildings buildings;
    private Transform currentBuilding;
    private bool _hasPlaced;
    public LayerMask BuildingsMask;
    public void SelectBuilding(GameObject g)
    {
        _hasPlaced = false;
        currentBuilding = ((GameObject)Instantiate(g)).transform;
        buildings = currentBuilding.GetComponent<Buildings>();
    }

bool CheckPosition()
{
    if (buildings.CollidersList.Count > 0)
    {
        return false;
    }
    return true;
}

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


    Vector3 m = Input.mousePosition;
    m = new Vector3(m.x, m.y, transform.position.z);
    Vector3 p = GetComponent<Camera>().ScreenToWorldPoint(m);


    if (currentBuilding != null && !_hasPlaced)
    {

        currentBuilding.position = new Vector3(p.x,p.y,0);

        if (Input.GetMouseButtonDown(0))
        {
            if (CheckPosition())
            {
                _hasPlaced = true;
            }
        }
    }
    else
    {
        if (Input.GetMouseButtonDown(0))
        {
            RaycastHit2D hit = new RaycastHit2D();
            Ray2D ray2D = new Ray2D(new Vector2(p.x,p.y), Vector3.down );
            //Ray2D ray = new Ray(transform.position,new Vector3(p.x,p.y,p.z));
            if (Physics2D.Raycast(new Vector2(p.x,p.y),Vector3.down,5.0f,BuildingsMask) )
            {
                Debug.Log(hit.collider.name); //error
            }
        }
    }

}

      

------------------ I share the answer and thank you for your help ------------------- -

 if (Input.GetMouseButtonDown(0) && !EventSystem.current.IsPointerOverGameObject())
        {
            RaycastHit2D hit = new RaycastHit2D();
            Ray2D ray2D = new Ray2D(new Vector2(p.x,p.y), Vector3.down );
            hit = Physics2D.Raycast(new Vector2(p.x, p.y), Vector3.forward, 5.0f, BuildingsMask);

                Debug.Log(hit.collider.name);

        }

      

+3


source to share


4 answers


Unity has two physics engines that are very similar, but this is one area where they differ in subtle and confusing ways.

The 3D engine offers Physics.Raycast

one that returns true

on impact or false

otherwise and allows you to pass RaycastHit

by link if you need to know more about the hit.

A 2D engine suggests Physics2D.Raycast

which instead returns RaycastHit2D

on impact or null

otherwise. As your code is written, accessing hit

is not the same hit that was caused by the raycast call.

So, you need something closer to this:



RaycastHit2D hit = Physics2D.Raycast(...); //edit in your raycast settings
if (hit) {
    //do something with the hit data
}

      

(You may notice that it RaycastHit2D

has an implicit conversion to bool

.)

Unity has only had a 3D engine for a long time, so many old documents will speak as if it were the only one. Watch this.

+5


source


With the new user interface system, you no longer have to handle clicks manually. Just add the IPointerClickHandler to your MonoBehaviour and make sure there is an EventSystem and PhysicsRaycaster present in the scene.



+1


source


OK! I check the whole internet and nobody understands what people really need when they say abour raycast2D, I will finally find what they need, take it and be happy)) bad try to answer the answer everywhere so people can easily find it if it's necessary. From the camera screen to the 2D sprite, the sprite should be with any collider, you don't need a rigid body on the sprite.

//create 2 empty places for objects

public RaycastHit2D hit;
public GameObject choosen;

//in update put click on mouse //take Method play by clicking mouse

void Update(){
if (Input.GetKeyDown (KeyCode.Mouse0)) {
    RayCaster ();
    }
}

// create raycast Method

void RayCaster (){
    RaycastHit2D ray = Physics2D.GetRayIntersection(Camera.main.ScreenPointToRay (Input.mousePosition));//making ray and object, taking mouse position on screen from camera
    if(!UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject (-1)) {
        if (ray.collider != null) {// for non error, check maybe you hit none collider sprite
            hit = ray;// not hit is our obj from scene, but we cant work with it as an object
            choosen = hit.transform.gameObject;// making hit obj as normal object, now we can work with it like with 3Dobject, not as sprite
        }
    }
}

      

Then we work with the selected object.

Put the script on the camera, now everyone will be happy, couse on the Internet even the community3D community does not understand what people with raycast2D really need, hope that in the future they will facilitate this function))

0


source


Thanks @anonymously, your answer works really well for me, I just needed to hit the ray with the mousePosition and see if that position hits some 2D gameObject like a sprite.

I am calling this hit in the OnMouseUp () method.

void OnMouseUp(){
    RaycastHit2D ray = Physics2D.GetRayIntersection(Camera.main.ScreenPointToRay(Input.mousePosition));

    if (ray)
    {
        GameObject hittedGameObject = ray.collider.gameObject;

        // Do something else

    }
}

      

0


source







All Articles