Raycasting to find mouseclick on Object in unity 2d games - unity3d

I am trying to delete the object on which the mouse is clicked. I am making a 2D game using the new Unity3D 4.3. Here is the code I'm using
void Update () {
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if(Physics.Raycast(ray,out hit))
{
isHit = false;
Destroy(GameObject.Find(hit.collider.gameObject.name));
}
}
}
The control is not entering the inner if loop. (isHit is not being set as false).

You cannot use 3D physics functions on the new 2D stuff. Use the 2D functions instead. Example:
RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
if(hit.collider != null)
{
Debug.Log ("Target Position: " + hit.collider.gameObject.transform.position);
}

This question is a bit old, but I was looking for a a way to get a GameObject with a mouse click in unity 2D, and the Answer from Esa almost helped me, but I couldn't afford to make it to work, so with a bit of research I saw that Camera.main.ScreenToWorldPoint was returning the center of the screen area of the Camera and to it work right. it required to enter the difference in Z position from the camera and the nearest GameObject. My Camera was set by default in -10 and my GameObject was in 0, so all I needed to do is set my Input.mousePosition.z to 10. So if you are getting problem to work with Esa's code (like me :( )the code bellow may help you:
RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 10)), Vector2.zero);
if(hit.collider != null)
{
Debug.Log ("Target Position: " + hit.collider.gameObject.transform.position);
}

First attach any type of 2D collider to your GameObject, then pick one of those solutions;
1st Case - If there are more than 1 GameObject on top of each other, and you try to understand specific GameObject is clicked:
void Update ()
{
if (Input.GetMouseButtonDown (0)) {
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit2D[] hits = Physics2D.GetRayIntersectionAll (ray, Mathf.Infinity);
foreach (var hit in hits) {
if (hit.collider.name == name) {
MyFunction ();
}
}
}
}
2nd Case - If there is only 1 GameObject, and you try to understand if it is clicked:
void Update ()
{
if (Input.GetMouseButtonDown (0)) {
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit2D hit = Physics2D.GetRayIntersection (ray, Mathf.Infinity);
if (hit.collider != null && hit.collider.name == name) {
MyFunction ();
}
}
}

You've to attach a mesh collider(any collider) with your object first to enter the inner If. Then,
Destroy(hit.collider.gameObject);
will simply do the job.
There's might be an other work around here.
void Update () {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if(Physics.Raycast(ray,out hit))
{
if(Input.GetMouseButtonDown(0))
{
isHit = false;
Destroy(hit.collider.gameObject);
}
}
}

Related

Got an error about RayCast when getting the mouse position

NullReferenceException: Object reference not set to an instance of an object
DragBlock.Update () (at Assets/Script/DragBlock.cs:13)
using UnityEngine;
public class DragBlock : MonoBehaviour
{
private bool isBeingHeld = false;
private Vector3 startPos;
private Transform heldObject;
private void Update()
{
if (Input.GetMouseButton(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
if (hit.transform.CompareTag("Blocks"))
{
isBeingHeld = true;
startPos = hit.transform.position;
heldObject = hit.transform;
}
}
}
if (isBeingHeld)
{
Vector3 currentMousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
currentMousePos.z = heldObject.position.z;
heldObject.position = currentMousePos;
}
if (Input.GetMouseButtonUp(0))
{
isBeingHeld = false;
}
}
}
I tried to change the group of the object tried to check the position and so on in this code it should check the position of the mouse and drag the object with the Blocks tag
If line 13 is this one...
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
... then the only part of the code that could realistically be null is the Camera.main property. Camera.main is returned by Unity when Unity looks for, and finds, a Camera in your scene that's tagged "MainCamera".
I suggest that you might have removed or changed that tag of the Camera, or a parent of the camera, and now Unity can't find an appropriate camera.
This is echoed in the online documentation https://docs.unity3d.com/ScriptReference/Camera-main.html

Dragging an object with raycast is laggy

When dragging an object slowly with a raycast the object moves with a bit of lag.
When dragging the object fast the mouse pointer gets out of the field of layer raycasting so the object is no more moving.
The main project is dragging a cube on a plane.
But in order to make the project more simpler, I opened a new 2D project and made a circle and assigned to it the following script, and attached to it a sphere collider (the main target is in 3D space).
// If some one wrote:
private Vector2 deltaPos;
void Update () {
Vector2 touchPos;
if (Input.GetMouseButtonDown (0)) { // Clicking the Target
RaycastHit hit;
var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
if (Physics.Raycast (ray, out hit, Mathf.Infinity)) {
touchPos = new Vector3 (hit.point.x, hit.point.y);
deltaPos.x = touchPos.x - transform.position.x;
deltaPos.y = touchPos.y - transform.position.y;
Debug.Log ("You Clicked Me");
}
}
if (Input.GetMouseButton (0)) {
RaycastHit hit;
var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
if (Physics.Raycast (ray, out hit, Mathf.Infinity)) {
transform.position = new Vector2 (hit.point.x - deltaPos.x, hit.point.y - deltaPos.y);
}
}
}
I expected to drag the sphere regularly, but what happens is that the pointer goes outside the sphere collider when moving fast, therefore the circle stops moving.
I found this article, then I changed the void from Update() to FixedUpdate() but same result.
Try putting your physics code in FixedUpdate() function which is built for physics calculation. then if it's laggy, you can changeFixed Timestep in physics settings.
Fixed Timestep: A framerate-independent interval that dictates when physics calculations and FixedUpdate() events are performed.
https://docs.unity3d.com/Manual/class-TimeManager.html
EDIT
this code:
if (Physics.Raycast (ray, out hit, Mathf.Infinity))
checks if the raycast has hit something, therefore when the pointer goes out of the sphere there is nothing else to hit, so the if condition returns false and you cannot move it, to solve the problem add a big quad or plane as child to your camera and make sure it fills the camera view perfectly, and it's behind all your other scene elements.
you also can make a script that sets this plane for you.
EDIT 2
As another approach to solve the issue, you can use flags.
Add this to your camera, or edit it to your needs.
public class DragObjects : MonoBehaviour
{
Camera thisCamera;
private Transform DraggingObject;
bool DraggingFlag = false;
RaycastHit raycast;
Ray ray;
Vector3 deltaPosition;
void Start()
{
thisCamera = GetComponent<Camera>();
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
ray = thisCamera.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out raycast, Mathf.Infinity))
{
DraggingObject = raycast.collider.transform;
DraggingFlag = true;
deltaPosition = thisCamera.ScreenToWorldPoint (Input.mousePosition) - DraggingObject.position;
}
}
else if (Input.GetMouseButton(0))
{
if (DraggingFlag)
{
DraggingObject.position = new Vector3 (thisCamera.ScreenToWorldPoint (Input.mousePosition).x - deltaPosition.x, thisCamera.ScreenToWorldPoint (Input.mousePosition).y - deltaPosition.y, DraggingObject.position.z);
}
}
else if (Input.GetMouseButtonUp(0))
{
DraggingFlag = false;
}
}
}
Remember to cash your Camera.main in a variable at the start, because it is not performant and does this in the background:
GameObject.FindGameObjectsWithTag("MainCamera").GetComponent<Camera>();

Two different Raycast 2D are hitting at the same time when i touch one of them in Unity 2D

I create one raycast 2D to destroy the first gameObject on click and created a second raycast 2D to destroy the second gameObject on click.
When i click on the first gameObject both gameObjects are destroyed at the same time, why does that happen and How can I make it destroy only the object I touched?
// First gameObject Script
using UnityEngine.EventSystems;
RaycastHit2D hit1Up = Physics2D.CircleCast(transform.position, 0.5f, Vector2.up * 0.35f);
RaycastHit2D hit1Bottom = Physics2D.CircleCast(transform.position, 0.5f, Vector2.down * 0.77f);
Debug.DrawRay(transform.position, Vector3.up * 0.35f, Color.green);
Debug.DrawRay(transform.position, Vector3.down * 0.77f, Color.green);
Ray firstRay = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Input.GetMouseButtonDown(0) && !EventSystem.current.IsPointerOverGameObject())
{
if (hit1Up.collider != null || hit1Bottom.collider != null)
{
if (hit1Up.collider.tag == "TagName1" || hit1Bottom.collider.tag == "TagName1")
{
Debug.Log("You touched TagName1");
destroy(this.gameObject);
}
}
}
// Second gameObject Script
using UnityEngine.EventSystems;
RaycastHit2D hit2Up = Physics2D.CircleCast(transform.position, 0.5f, Vector2.up * 0.35f);
RaycastHit2D hit2Bottom = Physics2D.CircleCast(transform.position, 0.5f, Vector2.down * 0.77f);
Debug.DrawRay(transform.position, Vector3.up * 0.35f, Color.yellow);
Debug.DrawRay(transform.position, Vector3.down * 0.77f, Color.yellow);
Ray secondRay = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Input.GetMouseButtonDown(0) && !EventSystem.current.IsPointerOverGameObject())
{
if (hit2Up.collider != null || hit2Bottom.collider != null)
{
if (hit2Up.collider.tag == "TagName2" || hit2Bottom.collider.tag == "TagName2")
{
Debug.Log("You touched TagName2");
destroy(this.gameObject);
}
}
}
if (mouse is down) { check that the object I'm interested in exists, then destroy it }
Your code isn't checking that the ray actually hit the object! Or, for that matter, even performing a ray cast to see if the ready his anything at all.
if (hit2Up.collider != null || hit2Bottom.collider != null)
Gosh, I should hope this is true before your code ever runs. This check is useless.
if (hit2Up.collider.tag == "TagName2" || hit2Bottom.collider.tag == "TagName2")
I presume this will either always be true, or always false. Given that your code is destroying the object, I suspect that it is true. This check is useless.
What you should do:
Call Physics.raycast using the out RaycastHit parameter (this will be wrapped in an if statement, if you don't hit anything, no need to perform any additional checks)
Check that the hit.collider == hitUp.collider
You also don't need two scripts for this, the same one used twice with different values will suffice.
Example implementation:
string tagName;
Update() {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if(Physics.Raycast(ray, out hit)) {
if(hit.collider.CompareTag(tagName)) {
Debug.Log("You touched " + tagName);
destroy(hit.collider.gameObject);
}
}
}
Note: if you are using the 2D physics, you need to use RaycastHit2D and Physics2D respectively. The 2D and 3D physics engines don't in any way communicate.
Thanks #Draco18s for your response, it helped me come up with the 2D version logic I needed via some research. Cheers!
string tagName1, tagName2;
if (Input.GetMouseButtonDown(0))
{
Vector2 worldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast(worldPoint, Vector2.zero);
if (hit.collider != null)
{
//Debug.Log(hit.collider.name);
if (hit.collider.CompareTag(tagName1))
{
print(tagName1);
Destroy(hit.collider.gameObject);
} else if (hit.collider.CompareTag(tagName2))
{
print(tagName2);
Destroy(hit.collider.gameObject);
}
}
}

Moving GameObject with RayCast hit position causing object to move towards Raycast start position

I have RayCast represented by a LineRenderer in Unity, so it looks like a laser. I want this laser to move objects it collides with so that the object follows the hit.point of the Raycast hit.
My code doesn't work, because I move these GameObjects to the hit.point, which causes the object to comes towards the start point of the Raycast, because a new hit.point gets calculated since the object is moving to hit.point. I understand why this is happening, but I'm not sure how to get the object to move with the Raycast, but not effect a new hit.point.
Here's my update function in my script attached to my Laser GameObject. Does anyone know how I can fix my code so that the object moves with the hit.point?
void Update()
{
Vector3 target = calculateDeltaVector();
lr.SetPosition(0, palm.transform.position);
RaycastHit hit;
if (Physics.Raycast(palm.transform.position, target , out hit))
{
if (hit.collider)
{
lr.SetPosition(1, hit.point);
if (hit.transform.gameObject.tag == "Chair")
{
GameObject chair = hit.transform.gameObject;
// !!! move object to hit point, problem HERE
chair.transform.position = hit.point;
hitLock = false;
}
}
}
else lr.SetPosition(1, target * 50);
}
In Unity Inspector, you can select the object and change the layer to "2: Ignore Raycast" This will make the raycast ignore the object and go through it.
Don't know, but your code should move the chair to the chair, which likely will make the chair go towards you.
You have to implement Begin and End the raycast move, e.g using mouse click.
Below is the example
public class Mover : MonoBehaviour
{
public Collider selectedChair;
void Update ()
{
Vector3 target = calculateDeltaVector();
lr.SetPosition(0, palm.transform.position);
RaycastHit hit;
if (Physics.Raycast(palm.transform.position, target , out hit))
{
if (hit.collider)
{
lr.SetPosition(1, hit.point);
if (hit.transform.gameObject.tag == "Chair" && Input.GetMouseButton(0)) //if you want to move it you have to click mouse button first
{
selectedChair = hit.collider;
hit.collider.enabled = false; //disable the collider of currently selected chair so it won't go towards you
}
if (selectedChair)
{
// !!! move object to hit point, problem HERE
selectedChair.transform.position = hit.point;
hitLock = false;
}
if (Input.GetMouseButton(0))
{
selectedChair.enabled true;
selectedChair = null; //release it
}
}
}
else lr.SetPosition(1, target * 50);
}
}

Turn Sub-Object Code (raycast & mouse click & sub-objects)

Game characters are going somewhere that is clicked with the mouse
My problem : the code only works over a GameObject. I want to use one in the ground in the box, it can not.
I use a line of code :
public GameObject obj;
void Update() {
if(Input.GetMouseButton(0)) {
RaycastHit rayHit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (obj.collider.Raycast (ray, out rayHit, Mathf.Infinity)) {
transform.position = rayHit.point;
renderer.material.color = Color.green;
}
}
}
Map as the only model so I need to do. prevents me from making changes to my map
I need to call the individual sub-objects. but I could not.
Translating google translate :)
Try using Physics.Raycast(ray, out rayHit). This will raycast from your screen into the world. Then you can check the type of the object:
if (rayHit.collider.GetType() == typeof(YourTypeHere))
{
doSomething();
}