Reputation: 425
I'm working on simple strategy game mechanics. I have a Barracks prefab. When I add the Barracks on the scene and click on the Barracks, I receive an NullReferenceException
error:
NullReferenceException: Object reference not set to an instance of an object PlacementController.Update () (at Assets/Scripts/PlacementController.cs:64)
The error is received when I try to reach collider name of the Barracks using Raycast2D.
Barracks prefab has a Box Collider2D collider(trigger is checked) and its tag is "Building" and its layer is "Buildings". It has a rigidbody2D component and it is a kinematic rigidbody.
I can not figure out this problem. Please help me.
Thanks 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 am sharing answer, and thanks 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);
}
Upvotes: 4
Views: 17266
Reputation: 687
Thanks @анонимно, your answer works pretty good for me, I just was needing to hit a ray with the mousePosition and know if this position hits with some 2D gameObject, such as an sprite.
I'm calling this hit in OnMouseUp() method.
void OnMouseUp(){
RaycastHit2D ray = Physics2D.GetRayIntersection(Camera.main.ScreenPointToRay(Input.mousePosition));
if (ray)
{
GameObject hittedGameObject = ray.collider.gameObject;
// Do something else
}
}
Upvotes: 0
Reputation: 1
OK! i check all internet, and none understand what people really needs when talking abour raycast2D, i finally find what they need, take, and be happy )) ill try post answer to everywhere so people can easy find it if its need. From camera screen to 2D sprite, sprite should be with any collider, rigidbody on sprite not need.
//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 work with choosen obj.
Put script on camera, now everyone will be happy, couse in internet even unity3D community not understand what people really needs with raycast2D, hope maybe in future they will make this function easier ))
Upvotes: 0
Reputation: 13277
With the new UI system, you don't have to handle clicks manually like this anymore. Just implement IPointerClickHandler on your MonoBehaviour, and ensure that there's EventSystem and PhysicsRaycaster present in the scene.
Upvotes: 1
Reputation: 11452
Unity has two physics engines, which are very similar, but this is one area where they are different in a subtle and confusing way.
The 3D engine offers Physics.Raycast
, which returns true
on hit, or false
otherwise, and allows you to pass a RaycastHit
by reference if you need to know more about the hit.
The 2D engine offers Physics2D.Raycast
, which instead returns a RaycastHit2D
on hit, or null
otherwise. The way your code is written, the hit
you access is not the same hit that was returned 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 RaycastHit2D
has an implicit conversion to bool
.)
Unity had only the 3D engine for a long time, so a lot of older documentation will talk as if that's the only one. Watch out for that.
Upvotes: 7