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);
}
source to share
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.
source to share
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.
source to share
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))
source to share
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
}
}
source to share