I've tried some examples of code to handle click on object, but they are don't work.
I have object's mesh on scene:
On Main Camera there is one C# Script Component with code:
using UnityEngine;
using System.Collections;
public class cameraAnim3 : MonoBehaviour
{
void Update() {
if (Input.GetMouseButtonDown (0)) { // if left button pressed...
print ("cli!!!");
// create a ray passing through the mouse pointer:
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast (ray, out hit)) { // if something hit...
print ("clicked on object!!!");
// if you must do something with the previously
// selected item, do it here,
// then select the new one:
Transform selected = hit.transform;
selected.gameObject.SetActive (true);
print (selected.gameObject.name);
// do whatever you want with the newly selected
// object
}
}
}
}
When I clicked with left button on the mesh of head, in console message "cli!!!" showed, but no message "clicked on object!!!" was showed.
How to catch click on this mesh?
Answer is here Unity: Object is not being detected by raycast for highlighting
The modern to detect collisions is to implement IPointerClickHandler interface, and ensure that you have an EventSystem and a relevant Raycaster (2d or 3d, depending on what collider are you using) present in the scene. It's much better than writing your own code to manage clicks and pointer positions. Also, the game object itself has to have a Collider component. It can either be a mesh collider, or a more generic (and better for performance) box collider.
Related
I'm creating a top down 2D game, where the player has to break down trees. I made it so the player casts a ray toward the mouse, and when the ray hits a tree, it should lower the tree's health. I don't get any errors when I run the game or click, but it seems like the tree isn't detecting the hits.
void Update()
{
...
if (Input.GetMouseButtonDown(0))
{
RaycastHit2D hit = Physics2D.Raycast(playerRb.transform.position, mousePosition - playerRb.transform.position, 2.0f);
if (hit.collider != null)
{
if (hit.collider == GameObject.FindWithTag("Tree"))
{
hit.collider.GetComponent<TreeScript>().treeHealth--;
}
}
}
}
Still pretty new to coding and I'm teaching myself, so please make your answer easy to understand to help me learn.
Input.mousePosition is equal to the pixel your mouse is on. This is very different than the location your mouse is pointing at in the scene. To explain further, Input.mousePosition is where the mouse is. Think about it. If the camera was facing up, the mouse positon would be the same, but where they are clicking is different.
Instead of using Input.mousePosition, You should pass this into a function called Ray Camera.ScreenPointToRay();
You just input the mouse position and then use this new ray to do the raycast.
ANOTHER EXTREMELY IMPORTANT THING 1: Do not use Camera.main in Update(), as it uses a GetComponet call, which can cause perormance decreases. Store a reference of it in your script and use that.
Extremely important thing 2: I notice you are using GetComponent to change the tree's health. This is fine, but do not use GetComponent if you don't have to.
Like this:
Camera cam;
void Start()
{
cam = Camera.main; //it is fine to use this in start,
//because it is only being called once.
}
void Update()
{
...
if (Input.GetMouseButtonDown(0))
{
Ray ray = cam.ScreenPointToRay(Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast(ray);
...
}
}
You need to convert your mouse position from screen point to world point with Z value same as the other 2D objects.
Vector3 Worldpos=Camera.main.ScreenToWorldPoint(mousePos);
Also use a Debug.DrawRay to check the Raycast
Debug.DrawRay(ray.origin, ray.direction*10000f,Color.red);
Source
There are many questions like this, but I didn't find a valid solution to my problem.
I would like to click an object behind a collider, this is my code:
void Update () {
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
Debug.Log(hit.transform.name);
}
}
I put this code inside the script attached to the first object but the debug log will never be called.
Any ideas?
If I understand your question right, you want to click on the yellow sphere (see image) and want the name of the white cube?
There are two possible ways to do that:
1. Ignore Raycast Layer
You could give the yellow sphere the unity standard layer "Ignore Raycast":
Then your code should work (I added the on left mouse click)
void Update()
{
if (Input.GetMouseButtonDown(0)) // Click on left mouse button
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
Debug.Log(hit.transform.name);
}
}
}
2. Use Layer Mask
See: Using Layers and Bitmask with Raycast in Unity
If that's not what you're looking for please give further information and a screen shot of your problem.
I have a prefab that is instantiated when the user buys the item from my In-game store, how ever many is instantiated, the all of prefab has a start position of a certain position. The prefab can be dragged around the scene using this TouchScript package I found online! My issue: I want to play the prefab's animation every time the user is dragging the prefab around the screen, I attempted this by creating a RaycastHit2D function that would allow me to detect if the user has clicked on the prefab's collider, script below:
if (Input.GetMouseButtonDown (0)) {
Vector2 worldPoint = Camera.main.ScreenToWorldPoint (Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast (worldPoint, Vector2.zero);
if (hit.collider != null) {
if (this.gameObject.name == "Item5 (1)(Clone)" +item5Increase.i) {
monkeyAnim.SetBool ("draging", true);
Debug.Log (hit.collider.name);
}
} else {
monkeyAnim.SetBool ("draging", false);
}
}
However if I were to buy more than one prefab, all instantiated prefabs will play it's animation when I start to drag only one of the instantiated prefabs, hope I'm making sense. Can some one help me? Thank you!
I faced a similar issue with platforms in my 2D game. The solution I would suggest is to create a GameObject that acts as the current item you wish to animate, and a LayerMask that acts as a filter for which objects your raycast can hit. You can use this LayerMask in conjunction with the Physics2D.Raycast API, which has an overload method that takes a LayerMask as a parameter.
Start by creating a new layer, which can be done by going to the top right of an object in your scene and accessing the "Layer" box. Once you've created a new layer (I called mine "item"), make sure your prefab's layer is assigned correctly.
Then, create an empty object in your scene, and attach this script to it. On that object you will see a dropdown menu that asks which layers your raycast should hit. Assign it the "item" layer; this ensures that your raycast can only hit objects in that layer, so clicking on anything else in your game will produce no effect.
using UnityEngine;
public class ItemAnimation : MonoBehaviour
{
private GameObject itemToAnimate;
private Animator itemAnim;
[SerializeField]
private LayerMask itemMask;
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
CheckItemAnimations();
}
else if (Input.GetMouseButtonUp(0) && itemToAnimate != null) //reset the GameObject once the user is no longer holding down the mouse
{
itemAnim.SetBool("draging", false);
itemToAnimate = null;
}
}
private void CheckItemAnimations()
{
Vector2 worldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast(worldPoint, Vector2.zero, 1, itemMask);
if (hit) //if the raycast hit an object in the "item" layer
{
itemToAnimate = hit.collider.gameObject;
itemAnim = itemToAnimate.GetComponent<Animator>();
itemAnim.SetBool("draging", true);
Debug.Log(itemToAnimate.name);
}
else //the raycast didn't make contact with an item
{
return;
}
}
}
This question already has answers here:
How to detect click/touch events on UI and GameObjects
(4 answers)
Closed 4 years ago.
Is there way to call the onclick event from a raycast?
I have world scale canvas attached to an object that has images with buttons.
When I select the button with the mouse my event function is called.
But now I am trying to adjust the code so I can avoid using mouse all together.
[SerializeField]
private Image cursor;
[SerializeField]
private LayerMask uI;
if (Input.GetButtonDown("Fire1"))
{
Ray ray = Camera.main.ScreenPointToRay(cursor.transform.position);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100,uI))
{
Debug.Log(hit.collider);
}
}
This is the code I use to raycast into the world space canvas which works and returns the images but I am not sure how I can now call the onclick event since I am not using the mouse but a image instead
Is there way to call the onclick event attached to image that I raycast to or do I have to redo my entire script and not use on click events?
Hen you hit a GameObject, get its list of components that implement OnPointerClick event
IPointerClickHandler clickHandler=collider.gameObject.GetComponent<IPointerClickHandler>();
once you have that reference (its not null) you can call
PointerEventData pointerEventData=new PointerEventData(EventSystem.current);
clickHandler.OnPointerClick(pointerEventData)
That should do the job
I believe that the Button component does what you seek as well.
But to answer your question about raycasts.
Is there way to call the onclick event from a raycast?
//Example raycast code
//Variables
public RayCastHit _Hit;
public LayerMask _RaycastCollidableLayers; //Set this in inspector, makes you able to say which layers should be collided with and which not.
public float _CheckDistance = 100f;
//Method
void PerformRaycast(){
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Physics.Raycast(ray, out _Hit, _CheckDistance + 0.1f, _RaycastCollidableLayers);
if (_Hit.collider == null)
{
Debug.Log("Raycast hit nothing");
return null;
}
GameObject go = _Hit.collider.gameObject;
}
Your raycast hits an object and stores a reference to that object. As you can see in my example you can fetch the game object through the RaycastHit.
When you have the game object you can access any scripts on it through GetComponent<>(), this means you can say.
GameObject go = _Hit.collider.gameObject;
OnClickScript ocs = go.GetComponent<OnClickScript>();
ocs.OnClick();
If I misunderstood your query, please let me know.
I try to create a VR scene in unity using google cardboard sdk. I add a cube and CardboardMain.prefab to scene. There is an example scene that detect focus on cube. Its hierarchy view is :
I don't know how to add GUIReticle object or prefab like as the image.
How can I detect focus on an object?
Actually you could make the script by your own and it is quite simple.
You could detect whether the user is looking at your object or not by using RayCast from the Main Camera. If the RayCast hit your object, then it is being focused on.
For example:
using UnityEngine;
using System;
[RequireComponent(typeof(Collider))]
public class LookableObject : MonoBehaviour {
[SerializeField]
Transform cam; // This is the main camera.
// You can alternately use Camera.main if you've tagged it as MainCamera
bool focus; // True if focused
Collider gazeArea; // Your object's collider
public void Start () {
gazeArea = GetComponent<Collider> ();
}
public void Update () {
RaycastHit hit;
if (Physics.Raycast (cam.position, cam.forward, out hit, 1000f)) {
focus = (hit.collider == gazeArea);
} else {
focus = false;
}
}
}
Edit: This is just an example. You probably would want to make a script to do the Raycast only just once instead of doing the Raycast on each of your object over and over again to make your project runs faster.